ansibleを使ってみる¶
Chefが猛烈な勢いで流行り始めている今日このごろですが、似たようなものは 世の中にいくつもあります。今日はその中の一つ、 Ansible を使ってみます。
書いていたらやたらと長くなったので何回か続きます。
軽くご紹介¶
インストールの前にどのようなツールなのかを軽く説明します。マシンの設定 を自動で行なってくれる、というツールなのはChefと同じです。
そのポリシーは githubのページ に書かれています。
シンプルな設定
最初から超速くて並列
サーバーやデーモンとかいらない。今あるsshdだけあればいい
クライアント側になにもいらない
モジュールは「どんな」言語でも書ける
超強力な分散スクリプトを書くためのイケてるAPI
rootじゃなくても便利に使える
今までで一番使える設定管理システム
さて、では見て行きましょう。
インストール¶
ansibleはpythonで書かれています。実行する側には2.6以上が、実行される側 には2.4以上が必要です。
他にも
paramiko
PyYAML
jinja2
が必要ですが、そのあたりはpipがめんどうみてくれるので、
% pip install ansible
でOKです。
使ってみる¶
% echo "127.0.0.1" > ~/ansible_hosts
% export ANSIBLE_HOSTS=~/ansible_hosts
% ansible all -m ping --ask-pass
SSH password:
127.0.0.1 | success >> {
"changed": false,
"ping": "pong"
}
と出ればOKです。これは、
ansbileの対象となるホストを設定
-m pingを実行
という感じです。
対象となるホストを設定¶
/etc/ansible/hosts を次のように書きます。これはiniファイル形式です。グ ループ化しておくといいですね。/etcに書けなくても、さっきのように ANSBLE_HOSTS 環境変数を設定したり -i で指定できるので問題ないです。
mail.example.com
[servers]
foo.example.com
bar.example.com
[webservers]
web[01:50].example.com <-- web01から50まで指定
[databases]
db-[a:f].example.com <-- こういうのもあり
実際にはホストやグループごとに個別に変数を設定できたりと、結構柔軟に書けます。
使い方¶
以上のように設定して、実際の実行は以下のようにします。
% ansible <対象> -m <モジュール名> -a <引数>
例
% ansible webservers -m service -a "name=httpd state=restarted"
さて、では、これから実際の使い方の例を並べてみます。
# webサーバーを10並列でrebootかける
% ansible webservers -a "/sbin/reboot" -f 10
# sudoで実行
% ansible atlanta -a "/usr/bin/foo" -u username --sudo
# shellモジュールを経由して実行
% ansible raleigh -m shell -a 'echo $TERM'
モジュールについてはあとで説明します。
ファイルを扱う
# 手元の/etc/hostsを各サーバーの/tmp/hostsにコピー
% ansible webservers -m copy -a "src=/etc/hosts dest=/tmp/hosts"
# 各サーバーのa.txtのownerを変更
% ansible webservers -m file -a "dest=/srv/foo/a.txt mode=600 owner=mdehaan"
パッケージ
# yumでinstall
% ansible webservers -m yum -a "name=acme state=installed"
# version指定
% ansible webservers -m yum -a "name=acme-1.5 state=installed"
# 最新指定
% ansible webservers -m yum -a "name=acme state=latest"
# インストールされていないこと
% ansible webservers -m yum -a "name=acme state=removed"
モジュール¶
ここまでで、ansbileの基礎的な使い方はわかったと思います。そして、 -m で 指定するモジュールというものがあることも。
モジュールはchefで言うところの「Resource」に当たるものです。結構いっぱ い用意されており、 ここ にまと まっています。
モジュールは自分で作成することもできます。
標準入力でオプションを受け取る
標準出力で実行結果を返す(出力形式は基本JSONで。ただし、key=value を空白でつなげたものでも)
ということさえ守っていれば、言語はなんでも大丈夫です。ただし、「冪等性」 は守ったほうがいいでしょう。既存のモジュールは冪等性があります。
詳しくは こちら をご覧ください。
playbook¶
モジュールは単一の機能だけを提供するものですので、これだけでは自動構成 できません。モジュールを組み合わせて、一連の動作を設定する必要がありま す。これを書くのが playbook と呼ばれるものです。
以下にapacheを設定する例を書きます。
---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
user: root
tasks:
- name: apacheを最新に
action: yum pkg=httpd state=latest
- name: apacheの設定ファイルを書き出す
action: template src=/srv/httpd.j2 dest=/etc/httpd.conf
notify:
- apache再起動
- name: apacheが起動していることを確認
action: service name=httpd state=started
handlers:
- name: apache再起動
action: service name=httpd state=restarted
これを実行するのには、 apache.yamlというファイル名で保存したとすると、
% ansible-playbook playbook.yml -f 10
とします。この例では10並列で実行しています。
感じがつかめたところで、順に説明していきます。
playbookの設定¶
- hosts: webservers
vars:
http_port: 80
max_clients: 200
user: root
hostsは実行するホストですね。先ほど ansible コマンドでも指定しましたね。 (ここが分離されてると共有しやすくなるんだけどな)
varsは使用する変数です。playbookの中で $http_port と指定したり、 templateモジュールのjinja2で使われたりします。
tasks設定¶
tasks:
- name: apacheを最新に
action: yum pkg=httpd state=latest
- name: apacheの設定ファイルを書き出す
action: template src=/srv/httpd.j2 dest=/etc/httpd.conf
notify:
- apache再起動
tasksは実際に実行する動作を指定します。nameはその名前を、actionでモジュー ルと引数を指定します。
実行順序は、書いてある順番で実行されます。
handlers¶
handlers:
- name: apache再起動
action: service name=httpd state=restarted
tasksの設定中で notify というのがありましたが、notifyで指定した動作を 受けるのがhandlerです。これにより、
設定ファイル書き出し
apache再起動
という流れになります。chefのnotify/subscribeと一緒ですね。
なお、handlerは必ず最後に実行されます。つまり、tasksで「apache再起動」 が何回も指定されていたとしても、最後に一回だけしか実行されません。
includeでtaskを再利用¶
一度書いたtaskは include で再利用できます。
---
- name: apache再起動
action: service name=apache state=restarted
とだけ書かれたファイルを用意しておけば、
tasks:
- include: tasks/foo.yml
- include: tasks/bar.yml user=shirou
と書けます。2つ目のincludeではuserという変数に別の値を入力しています。これで、 {{ user }} となっているところを置き換えられます。
また、handlerでもincludeできます。
playbookの再利用¶
- name: this is a play at the top level of a file
hosts: all
user: root
tasks:
- name: say hi
tags: foo
action: shell echo "hi..."
- include: load_balancers.yml
- include: webservers.yml
- include: dbservers.yml
tasksやhandlerと同じように、playbookそのものもincludeできます。 上記例では、load_balancersなどを読み込み、さらに実行するhostsを上書き しています。
role¶
これら再利用をまとめたのがroleです。
site.yml
webservers.yml
fooservers.yml
roles/
common/
files/
templates/
tasks/
handlers/
vars/
webservers/
files/
templates/
tasks/
handlers/
vars/
というようなファイル構成を作り、以下のようなplaybookを書きます。
---
- hosts: webservers
roles:
- common
- webservers
このplaybookを実行すれば、roles/webserversの中身が設定されます。
rolesは以下のような動作をします。xは上記"webservers"などと読み替えてください。
roles/x/tasks/main.yml があればそこに書かれているtaskが自動でinclude
roles/x/handlers/main.yml があればそこに書かれているhandlersが自動でinclude
roles/x/vars/main.yml があればそこに書かれているvarsが自動でinclude
copy taskは、roles/x/files/以下のファイルをパス指定なしで参照できる
template taskaは、roles/x/templates以下のファイルをパス指定なしで参照できる
chefで言うところのcookbookが近いですね。
変数を別ファイルに書き出したい¶
---
- hosts: all
user: root
vars:
favcolor: blue
vars_files:
- /vars/external_vars.yml
var_filesとしておけば、変数を外だし出来ます。
OSごとに挙動を変えたい¶
ansible_os_family という変数がセットされており、それを使います。
例えば、Debian系とCentOSとではapacheのパッケージ名が違いますが、
---
- hosts: all
user: root
vars_files:
- "vars/common.yml"
- [ "vars/{{ ansible_os_family }}.yml", "vars/os_defaults.yml" ]
tasks:
- name: make sure apache is running
action: service name={{ apache }} state=running
というように書いておき、 vars/CentOS.yml にこう書いておくと、
---
# for vars/CentOS.yml
apache: httpd
CentOSの場合はhttpdが使われることになります。なにも当てはまらなければ os_defaults.ymlが使われます。仮にos_defaults.ymlがない場合はエラーとなります。
なお、この機能を使うためにはfacterかohaiを入れる必要があります。
状態に応じて動作を変える¶
tasks:
- name: "Debian Familyだったらshutdownする"
action: command /sbin/shutdown -t now
when: ansible_os_family == "Debian"
whenを使うとできます。さらに、registerというものがあり、これはactionの 出力を受け取ります。この2つを併用すると、こういうこともできます。
tasks:
- action: template src=/templates/foo.j2 dest=/etc/foo.conf
register: last_result
- action: command echo 'ファイルが変更されました'
when: last_result.changed
この例ではactionのtemplateで変更があったら、echoが実行されます。
FAQ¶
naiveのsshを使うには¶
“–connection=ssh を引数につけるか
export ANSIBLE_TRANSPORT=ssh とする
実行時間が超長いコマンドがあるんだけど¶
# timeoutを3600秒にしてバックグラウンドで実行
% ansible all -B 3600 -a "/usr/bin/long_running_operation"
127.0.0.1 | success >> {
"ansible_job_id": "27789765441",
"results_file": "/home/shirou/.ansible_async/27789765441",
"started": 1
}
# 得られたjob idを使って状態を得る。jobidは全ホスト同じ
% ansible all -m async_status -a "jid=123456789"
# 60秒ごとにポーリング
% ansible all -B 1800 -P 60 -a "/usr/bin/long_running_operation --do-stuff"
まとめ¶
chefでserverを使うまでもなくchef-soloで十分なレベル(20台ぐらいまで?)で あれば、このansibleを試してみる価値はあるかもしれません。
ただし、ansibleは並列実行をサポートしていますので、かなりの台数までまか なえるかもしれません。特に、実行先のホストにはなにも必要ない点は chef-soloの比べてアドバンテージと言えるでしょう。
ということで、実はいままではドキュメントを読んだことしか書いていません ですが、実際にplaybookを使ってみようと思います。
ということで、まて次号!
Comments
comments powered by Disqus