今更ですが構成管理ツールの Ansible を使ってみたのでメモります。
環境は OSX10.10.2, ターゲットホストは Ubuntu14.04。
Ansibleのインストール
対象ホストへには ssh で接続するので `~/.ssh/config` に必要なssh設定を記述します。
$ cat ~/.ssh/config
Host "Ubuntu14.04's-IP"
HostName "Ubuntu14.04"
User ubuntu
Port 22
IdentityFile ~/.ssh/id_rsa
TCPKeepAlive yes
IdentitiesOnly yes
OSXに Ansible をインストールします。2系の場合。
$ brew update
$ brew info ansible
ansible: stable 2.0.2.0 (bottled), devel 2.1.0.0-0.2.rc2, HEAD
$ brew install ansible
下記は 1系の場合です。
$ sudo pip install ansible
$ ansible --version
ansible 1.8.4
configured module search path = None
$ echo "Ubuntu14.04's-IP" > ~/ansible_hosts
$ export ANSIBLE_HOSTS=~/ansible_hosts
$ ansible all -m ping --ask-pass -u ubuntu
SSH password:
xxxxxxx | success >> {
"changed": false,
"ping": "pong"
}
上記では インベントリ (実行する対象ホストの情報) を環境変数 ANSIBLE_HOSTS で指定しましたが, pip でインストールした場合, /etc/ansible/hosts がデフォルトのようです。または, -i オプションで直接指定できます。
# ansible 1.8.4 (pip)
$ ansible --help
...
-i INVENTORY, --inventory-file=INVENTORY
specify inventory host file
(default=/etc/ansible/hosts)
# ansible 2.0.2 (brew)
$ ansible --help
-i INVENTORY, --inventory-file=INVENTORY
specify inventory host path
(default=/usr/local/etc/ansible/hosts) or comma
separated host list.
Playbook
Playbookはyamlの構文で記述します。簡単なPlaybookを書いてみます。
---
# simple.yml
- hosts: Ubuntu14.04's-IP
user: ubuntu
sudo: no
gather_facts: False
tasks:
- debug: msg="Hello! Ansible!"
実行してみます。
# 構文チェック
$ ansible-playbook -i ansible_hosts simple.yml --syntax-check
# 実行
$ ansible-playbook -i ansible_hosts simple.yml
パッケージ管理システム(apt-get, pip)でインストールする簡単な Playbook を書きます。
見通しをよくするために, ある単位で外部ファイルにまとめておきます。
---
# python.yml
- name: install python2.7-dev
apt: pkg=python2.7-dev state=latest
- name: install python-pip
apt: pkg=python-pip state=latest
- name: install flask
pip: name=flask
- name: install requests
pip: name=requests
- name: install selenium
pip: name=selenium
- name: install pyvirtualdisplay
pip: name=pyvirtualdisplay
includeで外部ファイルを呼びます。
---
# ubuntu.yml
- hosts: Ubuntu14.04's IP
user: ubuntu
sudo: yes
gather_facts: False
tasks:
- name: install vim
apt: pkg=vim state=latest
- name: install git
apt: pkg=git state=latest
- name: install supervisor
apt: pkg=supervisor state=latest
- name: install td-agent
shell: curl -L https://toolbelt.treasuredata.com/sh/install-ubuntu-trusty-td-agent2.sh | sh
- include: tasks/python.yml
when で条件判定によるタスク実行制御したり, resisterで実行結果を変数に設定したりできます。
実行してみます。-vvvv オプション で詳細な実行内容が見れます。
$ ansible-playbook ubuntu.yml -i ansible_hosts -vvvv
task実行時に何も変更がない場合は ok にカウントされ, 何かしら変更がある場合は changed にカウントされます。ただし, shell-commandを使うと, 何もインストールしていないような場合でも changed になります。
Nginxの設定ファイル変更時に再起動する
nginx.conf を local から remote に転送し, 内容に変更がある場合に Nginx を再起動させます。
notify により callback された時の処理を定義しておきます。
---
# handlers/main.yml
- name: restart nginx
service: name=nginx state=restarted enabled=yes
下記 copy の結果が changed の時に notify に指定した handler の name に一致する task が実行されます。
---
- name: install nginx
apt: name=nginx
- name: copy nginx.conf
copy: src=/your/path/to/nginx.conf dest=/etc/nginx/conf.d owner=ubuntu mode=0644
notify: restart nginx
変更があった場合に, ちゃんと restart された事を確認しました。
$ ps -eo lstart,pid,args | grep nginx
Sat May 28 21:56:13 2016 21572 grep --color=auto nginx
Mon May 23 22:53:38 2016 22860 nginx: master process /usr/sbin/nginx
ansible-vault を使うと, パスワードを含むファイルを暗号化することができます。 具体的には –ask-valut-pass オプションで指定したパスワードを使って暗号化され, 処理実行時に復号化されます。
Roles を使うと見通しの良いディレクトリ構成になりそうです。全体的に Chef より手軽に使える印象でした。
Troubleshooting
リモートホストの OS が CentOS や RHEL の場合, デフォルトで SELinux が有効になっていて ansible-playbook 実行時にエラーとなることがあります。
Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!
単純に libselinux-python をインストールすれば良いです。
$ sudo yum install libselinux-python
[1] Ansible の Playbook を使ってみる
[2] Ansibleでのパスワードの取り扱い
[3] Ansible、コマンド実行結果を”ok”にする(冪等性を保つ方法)
[4] AnsibleでNginxをソースからインストール
[5] Ansibleでシェルコマンドを実行させるときのノウハウ
[6] Ansible マジック変数の一覧と内容
[7] ansible でファイルがある場合のみ実行したい場合のベストプラクティス