ようやく自宅サーバや開発環境仮想マシンの構築手順を Ansible 化した。
この手のツールはハマりポイント+よく使うイディオムを抑えるのが大事。Pythonプロダクトらしく非常にドキュメントが充実しているのだけど、充実しすぎているのでポイントを自分のためにもまとめておくことにする。
例はおもに Ansible のドキュメントから引用させていただきました。
設定ファイルを書きかえる(一行)
lineinfile
モジュールを使う。使い方は以下のような形になる。
1name: enalbe sudo without password if user belongs to the wheel group
2lineinfile: "dest=/etc/sudoers state=present regexp='^%wheel' line='%wheel ALL=(ALL) NOPASSWD: ALL'"
state
を absent
にすれば削除することができる。動きとしては regexp
にマッチする行をみつけたら line
に書きかえる、という動作になる。またデフォルトでは regexp
にマッチする行がない場合最終行に追加される。
上記のほかにも regexp
にマッチする業の前後に追記するなど柔軟な動作が可能。
ファイルコピーを行う(再帰的)
copy
モジュールを使えばファイルコピーできるのは当たり前なのだが、じゃあディレクトリの場合どうするかというとてっとりばやくは以下のようにするとよい。
1shell: rsync -a /path_to/source/ /path_to/dest/ creates=/path_to/dest/hoge
このとおり、 rsync
してしまうのがよい。上記はターゲットマシン上どうしでの rsync
で、playbookを実行しているホスト→ターゲットマシンで実行する場合は以下。
1local_action: command rsync -a /path_to/source/ {{ inventory_hostname }}:/path_to/dest/
local_action
を使うとターゲット上でなくplaybookを実行しているホスト上でコマンドを実行できる。
make installする
make install
するソフトウェアをどうするか。一つ目のパターンはよく見る形で以下のように1個ずつタスクにする。
1- name: "wget hoge src"
2 command: wget -O http://example.com/hoge.tar.gz creates=hoge.tar.gz
3
4- name: "expand src"
5 command: tar xvfz hoge.tar.gz creates=hoge
6
7# 続く…
私の場合こっちというのは以下のような形で1個にまとめてしまう。たかが make install
に上記のようにつらつらタスクを書きまくるのはしんどいので。
1name: install python3.3
2shell: >-
3 wget http://www.python.org/ftp/python/3.3.2/Python-3.3.2.tgz &&
4 tar zxvf Python-3.3.2.tgz &&
5 rm -f Python-3.3.2.tgz &&
6 cd Python-3.3.2 &&
7 ./configure --prefix=/usr/local/python3.3.2 --enable-shared &&
8 make &&
9 paco -D make install
10 chdir=/usr/local/src creates=/usr/local/python3.3.2/bin/python3.3
もちろん、途中でこけると中途半端なことになるのだがそうそうコケないのでこれでよいと思っている。
変数を使いこなす
ターゲット固有の情報はデフォルトで収集される。内容を見たければ ansible hostname -m setup
と実行すればよい。
他のホストの情報は以下のようにすればアクセスできる。
1{{ hostvars['test.example.com']['ansible_distribution'] }}
変数は実行時にコマンドラインオプションで上書きできる。
1ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo"
ループを使いこなす
Ansibleは結構複雑なループが使える。ただ実用的な範囲で言うと以下ぐらいを抑えておくとよいのでは。
with_items
による単純ループ
1name: add several users
2user: name={{ item }} state=present groups=wheel
3with_items:
4 - testuser1
5 - testuser2
with_items
+ 辞書によるループ
1name: add several users
2user: name={{ item.name }} state=present groups={{ item.groups }}
3with_items:
4 - { name: 'testuser1', groups: 'wheel' }
5 - { name: 'testuser2', groups: 'root' }
コマンド実行結果を with_items
で回す
1- name: retrieve the list of home directories
2 command: ls /home
3 register: home_dirs
4
5- name: add home dirs to the backup spooler
6 file: path=/mnt/bkspool/{{ item }} src=/home/{{ item }} state=link
7 with_items: home_dirs.stdout_lines
8 # same as with_items: home_dirs.stdout.split()
with_sequence
による整数範囲ループ(Pythonの range
のようなもの)
1file: dest=/var/stuff/{{ item }} state=directory
2with_sequence: start=4 end=16 stride=2
do-until(+sleep)ループ
1action: shell /usr/bin/foo
2register: result
3until: result.stdout.find("all systems go") != -1
4retries: 5
5delay: 10
ファイルglobでループ
1copy: src={{ item }} dest=/etc/fooapp/ owner=root mode=600
2with_fileglob:
3 - /playbooks/files/fooapp/*
条件分岐を使いこなす
これまた条件分岐もいろいろできることはあるのだが、以下のパターンを抑えておくとよいと思う。
単純な変数による分岐
1- name: "shutdown Debian flavored systems"
2 command: /sbin/shutdown -t now
3 when: ansible_os_family == "Debian"
コマンド実行結果による分岐
1tasks:
2 # まずはコマンドを実行してresultに格納
3 - shell: /usr/bin/foo
4 register: result
5 ignore_errors: True
6
7 # タスクが失敗した場合
8 - debug: msg="it failed"
9 when: result|failed
10
11 # タスクにより更新された場合
12 - debug: msg="it changed"
13 when: result|changed
14
15 # タスクが成功した場合
16 - debug: msg="it succeeded"
17 when: result|success
18
19 # タスクがskipされた場合
20 - debug: msg="it was skipped"
21 when: result|skipped
22
23 # タスクの標準出力によって分岐
24 - shell: echo "hi does not found"
25 when: result.stdout.find('hi') != -1
複数ターゲットが関連するタスクを実行する
ローリングアップデートのように複数ターゲットが連動して動くタスクがある。その場合、playbookを実行するマシンを核としてタスクを作ればよい。
1- hosts: webservers
2 serial: 5
3
4 tasks:
5 - name: take out of load balancer pool
6 local_action: command /usr/bin/take_out_of_pool {{ inventory_hostname }}
7
8 - name: actual steps would go here
9 yum: name=acme-web-stack state=latest
10
11 - name: add back to load balancer pool
12 local_action: command: /usr/bin/add_back_to_pool {{ inventory_hostname }}
local_action
モジュールはplaybookを実行しているホストで実行するコマンドを定義する。上記の例だとWEBサーバを5並列でLB切り離し→更新→LB組み込みを実行する。
この程度を理解していればだいたいやりたいことはできるはず。あとはモジュール一覧を頭にいれるだけですね。ついつい shell
でゴリ押ししそうになるのでぐっとそこをこらえて…