AnsibleでGCEサーバーをセットアップする

という tweet を見て、Docker Meetup で GCE の $500 分クーポンをもらっていたのを思い出したので試してみました。

ブラザから操作してみる

まずは、Ansible を使わないでブラウザからインスタンスを立ち上げてみます。https://console.developers.google.com/

Web Console から手動でインスタンスを立ち上げるには、プロジェクトを作成・選択し、画面左にあるメニューから「COMPUTE」→「COMPUTE ENGINE」→「VMインスタンス」→「Spin up VMs fast」で「Create an instance」

次のような入力・選択項目がありました。
"AnsibleでGCEサーバーをセットアップする"の続きを読む

Ansible でコマンドの出力を後の task で使う

Ansible Advent Calendar 2013 のネタとして書こうとした残骸があったので、書いてみる。

Ansible は task の実行結果を register という設定で変数に保存できます。
rc でコマンドの exit code に、stdout / stderr で標準出力/標準エラーにアクセスできます。

# mod_passenger.so のインストールされているべきパスを取得する
- name: get mod_passenger.so path
  shell: /opt/ruby-{{ ruby_version }}/bin/passenger-install-apache2-module --snippet | grep passenger_module | awk '{print $3}'
  register: mod_passenger_path
  changed_when: False

# 先の結果を利用して mod_passenger.so の存在確認を行う
- name: check mod_passenger.so installed
  command: test -f {{ mod_passenger_path.stdout }}
  register: mod_passenger_installed
  failed_when: mod_passenger_installed.rc not in [0, 1]
  changed_when: False

# mod_passenger.so がまだ存在しなかったら build する
- name: build mod_passenger.so
  environment:
    PATH: "/opt/apache_{{ httpd_version }}/bin/:/bin:/usr/bin:/usr/local/bin"
  command: >
    /opt/ruby-{{ ruby_version }}/bin/passenger-install-apache2-module
    --apxs2-path /opt/apache_{{ httpd_version }}/bin/apxs --auto
    creates={{ mod_passenger_path.stdout }}
  when: mod_passenger_installed.rc == 1

# httpd.conf に書く passenger の設定を取得する
- name: get passenger snippet
  command: >
    /opt/ruby-{{ ruby_version }}/bin/passenger-install-apache2-module
    --snippet
  changed_when: False
  register: passenger_snippet

# template で先の snippet を使う
- name: httpd.conf
  template: >
    src=httpd.conf.j2
    dest=/opt/apache_{{ httpd_version }}/conf/httpd.conf
    owner=root group=root mode=0644
  notify: restart httpd

httpd.conf.j2 の中で次の様に register で保存した値を使うことができます。

{{ passenger_snippet.stdout }}
{% if passenger_snippet.stdout %}
PassengerPoolIdleTime 1200
PassengerMaxPoolSize 5
#PassengerPreStart http://localhost/
{% endif %}

changed_when: False はコマンドが exit code = 0 で終了すると changed として扱われて、「えっなんか変更された?」ってちょっとビビるのを回避するためです。

failed_when: mod_passenger_installed.rc not in [0, 1] は test コマンドでファイルが存在しなかった場合に failed として扱われて「ドキッ」としないためです。ignore_errors: True としても赤字で表示されちゃうので。

Ansible Tutorial リニューアルしました

この投稿は Ansible Advent Calendar 2013 の23日目の記事です。
22日目: Ansibleを導入したい人の為のくどきポイント

前回の Advent Calendar ポストの翌日が3736回目の誕生日だったのですが、胃腸炎でゲロゲロしながら過ごした @yteraoka です。息子もゲロゲロしてて、ゲロゲロがゲロゲロを介護するという老老介護ならぬゲロゲロ介護でした。素晴らしい誕生日ですね。。。

最近の Ansible の話題と言えば ANSIBLEWORKS GALAXY ですが、こっちは明日、明後日できっと誰か書いてくれますよね。Ansible 開発者の書いた Playbook とか参考になりますね。へ〜、はぁ〜って見てました。っていうほどまだ見れてないけど今後、どんどん参考にしていきたい。

今日の話題は Ansible Tutorial をリニューアルしましたよという告知。まぁ、内容的にはほとんど変わってないわけですけど... ググると上位に出てくるので Ansible の変化にもついていかないとなという事で。

一応変更点を上げると

  • 1.4 でテストした
  • かつて {{ foo }} が使えなかったモジュールで ${ foo } としていたところを {{ foo }} が使えるようになったので変更。${ fooo } は廃止予定のようです。
  • WordPress の Secret Key 設定に https://api.wordpress.org/secret-key/1.1/salt/ を使って register, stdout を活用 (php で require した方が良かった?)
  • Ansible in detail は全然更新できなかったので Wiki に変更
  • その Wiki に failed_when, changed_when を追加。この機能便利です。
  • あと typo の修正とか細かい所は忘れました

もっと書きたいことはあったりしますが Wiki に追加して行こうと思います。

まだ、入門には使えるんじゃないかなと我ながら思ってます。Ansible 使ってみようかなって思ってる人は試してみてください。ではでは〜

明日は @r_rudi さんです。

Ansible 最近の発見

この投稿は Ansible Advent Calendar 2013 の13日目の記事です。
前日はこちら

2打席目です。

息子二人が連続で胃腸炎にかかりゲロとの戦いを強いられていて書こうと思っていたネタの準備ができなかったので、モジュール一覧ページを見て、「おーっ、こんな機能あったんだぁ!」って思ったものを書いてみます。

fetch モジュールの validate_md5

validate_md5={yes|no}

というパラメータが 1.4 で追加されていました。fetch 元と fetch してきたファイルの md5sum を比較して正しくコピーできたことを確認できます。
しかし copy モジュールにはこの機能ないんですね。
代わりにといっては何ですが、 copy と template モジュールには

validate=任意のコマンド

というパラメータがあります。 %s というマクロが使えて、作成した一時ファイル(rename前)の path に置換されて実行されます。例えば Apache のコンフィグファイルであれば

validate="/usr/sbin/httpd -t -f %s"

とすることで syntax check に失敗したら rename 前にエラーで終了させることができます。起動しない設定ファイルを反映してしまうことを防げます(もちろん syntax check では見つけられないミスもありますが)。
おっと、1.4 で lineinfile モジュールにもこの機能が追加されていました。

unarchive モジュール

1.4 で新規に追加されたモジュールです。 command モジュールで tar xf ... chdir=/some/where 使えば tar.gz でも tar.bz2 でも tar.xz も自動判別して展開はしてくれますが、このモジュールを使うと tar--diff 機能で差分が見つかった場合のみ実際に展開されます。これはちょっと便利。changed かどうかは重要ですからね。 zip ファイルの場合は常に展開されるようです。

file モジュールの state=touch

これまでは file, directory, link, hard, absent だけでしたが、touch が 1.4 で追加されていました。
Passenger アプリの deploy 時に tmp/restart.txt の timestamp を更新することでアプリだけリロードさせることができますが、こんな場合に使えますね。
もちろん

command: touch /some/where/tmp/restart.txt

でできるんですけど。

postgresql_privs

思ってたより便利そう。
ヤバい時間がない...

postgresql_user

1.4 からパスワードが必須ではなくなってました。LDAP 認証時にはパスワード設定する必要ないから助かる。

頓挫した技術系アドベントカレンダーの一覧(2013年) に乗ってしまうと困るから今日はこれで終了。

3打席目やります。

明日は私の誕生日です(さらにおじさんに...)
じゃなくって、明日は @r_rudi さんの2打席目です。

ansible の copy でファイルを glob 指定する

この投稿は Ansible Advent Calendar 2013 の5日目の記事です。
前日はこちら

こんにちは、Ansible Tutorial をそろそろリニューアルしないといけないなと思いつつ、更新すら全然できていない yteraoka です。あの Playbook は 1.2 時代に書いて 1.3 でも 1.4 でもテストしてないので動かないかもしれない... WordPress だってバージョンの指定がもう古いし。

このブログの前回のポスト「ansible の copy/template で例外対応」で次は fileglob を試してみると書いたので、今日はそれをやってみます。

が、その前に...
前回、with_first_found を試して copy モジュールは期待通りに動作したのに template はちょっと期待と違う動作となりました。なんでかなぁ?とコードをチラ見してたところこんな発見がありました。

first_available_file を使うと、期待通りに role の templates ディレクトリの中を順番に探してくれました。
ヤッタネ!

では今日の本題 fileglob を使ったファイルのコピーです。『えっ!そんなの copy モジュールでディレクトリ毎コピーすればいいじゃん!』っていう Ansible マスターなお方はちょいとお待ちを。
copy モジュールの再帰コピーは 1.4 からの新機能 Ansible 1.4 Released! なんです。私、まだ 1.3 ユーザーなのです。 EPEL さんなかなか 1.4 にならないので只今 Python コンパイル中でござる。

では順番に。

テキトーにファイルを準備

$ ls roles/test/files/conf.d
aaa  bbb  ccc  ddd.conf  eee.conf

files ディレクトリの conf.d/*.conf を対象にしてみる。 debug モジュール便利ですね。

$ cat roles/test/tasks/fileglob.yml 
---
- debug: msg={{ item }}
  with_fileglob: conf.d/*.conf
  tags: test

実行

$ ansible-playbook -i hosts site.yml -l ansibletest1 -t test -v

PLAY [ansibletest1] *********************************************************** 

GATHERING FACTS *************************************************************** 
ok: [ansibletest1]

TASK: [debug msg=] ************************************************************ 
ok: [ansibletest1] => (item=/home/ytera/ansible/roles/test/files/conf.d/ddd.conf) => {"item": "/home/ytera/ansible/roles/test/files/conf.d/ddd.conf", "msg": "/home/ytera/ansible/roles/test/files/conf.d/ddd.conf"}
ok: [ansibletest1] => (item=/home/ytera/ansible/roles/test/files/conf.d/eee.conf) => {"item": "/home/ytera/ansible/roles/test/files/conf.d/eee.conf", "msg": "/home/ytera/ansible/roles/test/files/conf.d/eee.conf"}

PLAY RECAP ******************************************************************** 
ansibletest1               : ok=2    changed=0    unreachable=0    failed=0

期待通りに動作しそうです。
conf.d/* とかまるっとコピーしたいなんて用途ありますよね。 rsync とか tar で展開とかだと変更がないのに changed になって、不要な notify が実行されたりするかもしれませんからね。

さて、1.4 からの再帰コピーですが、rsync ライクな実装になっていて、 src のディレクトリ指定で最後に '/' をつけておくと、そのディレクトリの中身だけをコピーし、 '/' を付けなかった場合はそのディレクトリごとコピーされるんです。どんどん便利になって素敵ですね。私もちょっぴり貢献をば https://github.com/ansible/ansible/pull/4027

それでは明日は takuan_osho さんの記事をお楽しみに〜。