python製 構成管理ソフト
chef(まともに使ったことないので良く知らないけど)は各nodeが管理サーバへアクセスする方式で、ansibleはサーバから各nodeへアクセスするpush方式。なので一部のmoduleを利用しない限り、各nodeへ何かをinstallする必要はない。管理サーバからsshでアクセスができれば良い。
ファイルをコピーする、コマンドを実行する、などの処理を定義しているものがmodule。
それらをまとめたものがplaybook。
まとめって書いているけど後半疲れてきてただ列挙しているだけなのであまりまとまってない。
(ほんとに初期設定の導入部分をかじった程度だけど)chefの仕組みは理解し辛かったけのに対して、ansible はわかりやすいと思います。個人的に。
install
# yum install -y --enablerepo=epel ansible
- 設定ファイル (yumでinstallした場合)
- /etc/ansible/ansible.cfg
- /etc/ansible/hosts
- /usr/share/ansible/module_name
hosts
yumでinstallするとdefaultのファイルは/etc/ansible/hostsになる。
単にhosts(ip, hostname) を書いていくだけでも良いし、ini形式でグループにすることも可能。また、www-[1:5]、www-[01:09]、app-[a:e] のように[]を使うと複数のホストに展開してくれる。
実行
> # ansible
ping module で各hostsへの疎通を確認しておく。
# ansible all -m ping sv01 | success >> { "changed": false, "ping": "pong" } sv02 | success >> { "changed": false, "ping": "pong" }
moduleを指定しない場合はdefaultのcommand moduleになる(-a で指定した引数を実行する)。
commandと似たshell moduleもあって、名前の通りshellの環境変数($PATH, $HOMEなど)を使ったり'||'、'&&'などを引数で使う、リダイレクトを使いたい場合はshell module を使う。他にもmoduleは盛りだくさん。yumの場合は/usr/share/ansible 以下に入ってる。
# ansible all -a 'uptime' sv01 | success | rc=0 >> 14:47:58 up 15 days, 8:23, 0 users, load average: 0.00, 0.00, 0.00 sv02 | success | rc=0 >> 14:47:58 up 39 days, 12:09, 0 users, load average: 0.00, 0.00, 0.00
module
cliでもdocument見れる。
# ansible-doc module_name
ファイルをコピーする、コマンドを実行する、などの処理を定義しているものがmodule。
公式のドキュメントざっと斜め読みしてとりあえず使ってみたmoduleメモ。
System
Commands
- command
- 引数をcommandとして実行
- shell
- shellを使って引数をcommandとして実行
- shellなので'>>'、$HOME などが使える
- script
- localのscriptをremoteに転送してremoteで実行する
- ~/.ansible/tmp/以下に一時ファイルが作られて、実行後に削除されるみたい
- "action: script /tmp/test.pl hoge fuga" を実行して、remoteでps見てたら
- "bash -c chmod +x /root/.ansible/tmp/ansible-1371288988.93-24846179799534/test.pl; /root/.ansible/tmp/ansible-1371288988.93-24846179799534/test.pl hoge fuga" とあった
File
- copyやtemplateでbackupオプションをyesにすると、ファイルに変更があった場合に日付付きでbackupしてくれる
- copy
- localのファイルをremoteにcopy
- copy src=/path/to/src dest=/path/to/dest
- copy時にowner、mode(権限) も指定可能
- fetch
- remotenのファイルをlocalのdirectoryにcopy
- fetch src=/path/to/src dest=/path/to/dest
- destdirの下に各remoteのhostごとに /path/to/dest/hostname/path/to/src のようにディレクトリが作られる
- file
- 既存のfileの権限、オーナを変更したり、symlinkを作成したりする
- file path=/path/to/file owner=foo mode=0644
- file src=/path/to/src dest=/path/to/dest state=link
- template
- localのtemplateファイルをremoteにcopy
- varsで設定した変数を定義しておけばcopyに展開してくれる
Network
- get_url
- 指定したURLからファイルをdownloadする
- get_url url=http://example.com/file dest=/path/to/file
- uri
- 指定したURLにアクセスする
- "各node"にpyhonのurlparse httplib2 moduleが必要
- pip などでinstallしておく
- installされていないと"msg: httplib2 is not installed"というエラーメッセージが出る
- httpでアクセスをするのはclientなので、client側にhttplib2 moduleがいる。
- 当初、ansible = clientにインストール不要というのを思い込んでいたけど、それはansible自体が不要なのであってその他のpython module等は用途によっては必要
Notification
mail, irc, jabber などを使って通知するmodule
- jabber
- to "user ID or name of the room, when using room use a slash to indicate your nick."
- とあるけど、roomを使ってない場合でも末尾に"/"を入れないとエラーになる
invalid output was: Traceback (most recent call last): File "/root/.ansible/tmp/ansible-1371788441.16-271641304974135/jabber", line 1052, in <module> main() File "/root/.ansible/tmp/ansible-1371788441.16-271641304974135/jabber", line 103, in main to, nick = re.split( r'/', module.params['to']) ValueError: need more than 1 value to unpack
# grep -n 'to, nick' ../library/notification/jabber 103: to, nick = re.split( r'/', module.params['to'])
ここで、"/"でsplitしてるけど、toに"/"を含んでない場合に、配列の数が一致しないからエラーになる?
playbook
moduleを組み合わせた一連の処理を定義する。定義したyamlはansible-playbook で使う。
# ansible-playbook filename.yml
↑のdocのsample
--- - hosts: webservers vars: http_port: 80 max_clients: 200 user: root tasks: - name: ensure apache is at the latest version action: yum pkg=httpd state=latest - name: write the apache config file action: template src=/srv/httpd.j2 dest=/etc/httpd/conf/httpd.conf notify: - restart apache - name: ensure apache is running action: service name=httpd state=started handlers: - name: restart apache action: service name=httpd state=restarted
playbookの主な内容
- Basics
hosts, user などを設定。userにroot以外を指定する場合、sudoできるよう設定しておいて"sudo: yes" と書ける。sudo実行時にパスワードが必要な場合はansible-playbook に--ask-sudo-pass (-K) を指定する。
vers には変数を設定する。配列も設定可能。playbookの中や、template (jinja2)で利用する。
These variables can be used later in the playbook like this:
$varname or ${varname} or {{ varname }}
とあるが、templateの中では全て使えるが、playbookのyaml内では$varname, ${varname} しか使えなかった。pathは引数で{{ varname }} を使うと、そのまま"{{ varname }}"という文字で扱われて、想定している動作にならなずに失敗した。
--- - hosts: webservers user: root vars: http_port: 80 van_halen_port: 5150 other: 'magic' resolvers: - 192.168.1.10 - 192.168.1.20
- Tasks List
ansibleで実行させたい処理を記述する。
name: 標準出力に表示されるdescription。
action: moduleと引数を指定する
actionの省略した書き方で、moduleをそのままyamlのkeyにすることも可能。
tasks: - name: install latest nginx action: yum name=nginx state=latest enablerepo=epel - name: make sure nginx is running action: service name=nginx state=started
これは↓でもOK。
tasks: - name: install latest nginx yum: name=nginx state=latest enablerepo=epel - name: make sure nginx is running service: name=nginx state=started
エラーを無視する
失敗したときにエラーを無視させる場合はtasks内のリストの項目で"ignore_errors: True" としておく。
例えばatdサービスをOS起動時に起動しないようにしたい(chkconfig atd off)時は、
service: name=atd enabled=no などと書けばいいわけだけど、atd がinstallされていない場合はエラーになって処理が止まる。起動しないようにする設定なので、installされていない場合はそのままエラーを無視して処理を進めて欲しいといった場合はtasksを次のように書く。
tasks: - name: make atd not running service: name=atd state=stopped enabled=no ignore_errors: True
追記
ansible variables
ansible_os_family => "Redhat" などansibleが定義している変数。setup モジュールで確認可能。
# ansible hostname -m setup (snip) "ansible_lsb": { "codename": "Final", "description": "CentOS release 5.9 (Final)", "id": "CentOS", "major_release": "5", "release": "5.9" }, (snip)