今更ながらAnsibleでちょっと遊んでみたのでその備忘録です。
今回はこちらのページとSoftware Design 2014年11月号にお世話になりました。
1. Ansibleとは
AnsibleはPythonで開発された構成管理ツールです。構成管理ツールといえばChefですが、Chefとの主な違いは下記のとおりです。
- 設定される側にChefクライアントのようなアプリケーションをインストールする必要がない。Python(2.4以上)が導入されておりsshでログインできればOK。
- Chefのレシピに比べると構成情報を書くのが楽。RecipeかいてJSONいじって・・・とかではなくてplaybook(Ansibleの構成情報を記述するファイル)にさらっとかける。
- 構成情報はYAMLで書く。Ruby苦手でも大丈夫。
上述のように、Chefに比べ、管理される側に色々入れる必要がなく、構成情報の記述が楽なので、Infrastructure as Codeを始めるには持って来いじゃないでしょうか:-)
2. 実行環境の整備
2.1 実行環境
Macのvagrant上にCentOSを2台立てて、IPを下記のとおりに設定します。
VagrantでCeontOS 6.5のboxがすでに追加されていることを前提とします。
役割 | OS | ip addr |
---|---|---|
ホスト | OS X 10.9.5 | - |
Ansibleサーバ(nodeA) | CentOS 6.5 | 192.168.33.11 |
Ansibleに設定されるノード(nodeB) | CentOS 6.5 | 192.168.33.12 |
2.2 環境構築
今回は2台のノードを立てるので、下記のVagrantfileを利用します。
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "ceontos"
config.vm.define :node1 do |node|
node.vm.box = "ceontos"
node.vm.network :forwarded_port, guest: 22, host: 2041, id: "ssh"
node.vm.network :private_network, ip:"192.168.33.11"
end
config.vm.define :node2 do |node|
node.vm.box = "ceontos"
node.vm.network :forwarded_port, guest: 22, host: 2041, id: "ssh"
node.vm.network :private_network, ip:"192.168.33.12"
end
end
vagrant up
し, node1, node2を起動します。
$ vagrant up
node1,node2のssh周りの設定をします。最後のscpはnode1に秘密鍵をコピーしておき、node1からnode2へsshログインできるようにするためのものです。
$ vagrant ssh-config node1 > ssh_config
$ vagrant ssh-config node2 >> ssh_config
$ scp -F ssh_config ~/.vagrant.d/insecure_private_key node1:.ssh/id_rsa
3. Ansibleのインストール
AnsibleはPython 2.6がインストールされているマシンで動作します。
pipで入れる方法もありますが、今回はCentOSなのでyumで入れてみます。
[vagrant@vagrant-centos65 ~]$ sudo yum install -y ansible
Ansibleのインストール作業は以上で完了です。
4. 実際にやってみる
4.1 動作確認
まずは動作確認として、Ansibleで管理対象とするノードに疎通テストをしてみましょう。 Ansibleはhostsという管理ノードのグループ/IPを記述したファイルを読み込んで、そのノードに対して指定した処理を実施します。では、hostsファイルを準備しましょう。グループはtest-serverとします。
[test-server]
192.168.33.12
次に下記のコマンドを打鍵して、nodeBに対して疎通確認します。
[vagrant@vagrant-centos65 ~]$ ansible test-server -i hosts -m ping
192.168.33.12 | success >> {
"changed": false,
"ping": "pong"
}
pong
が帰ってくれば、疎通確認はOKです。
-i
で利用するhostsファイルを指定します。また、/etc/ansible/hosts
に上述のhostsの内容を記述すれば-i
でhostsファイルを指定する必要はありません。また、hostsの中のどのグループに指定の処理を実行するかはansible
の後ろで指定します。
-m
で利用するモジュールを指定します。モジュールはansibleでの何らかの処理(yumでパッケージをインストール等)をする単位を指します。この場合はping
モジュールを利用し、指定したノードに対してsshでの接続確認をします。
[vagrant@vagrant-centos65 ~]$ ansible test-server -i hosts -m ping
よって上のコマンドの意味をまとめると、-i
で指定したhostsファイルの中のtest-serverに対して、疎通確認のモジュールであるpingモジュールを使い、疎通確認をするという意味になります。
4.2 モジュール
Ansibleではモジュールを駆使することで、サーバ構成情報を記述します。モジュールは組み込みのものが多数あり、また自作することも可能です。ここではyumモジュール、commandモジュール、get_urlモジュールを取り上げます。
4.2.1 yumモジュール
yumモジュールはyumでバイナリをインストールするモジュールです。
[vagrant@vagrant-centos65 ~]$ ansible -i hosts 192.168.33.12 -m yum -s -a name=sl
192.168.33.12 | success >> {
"changed": true,
"msg": "",
"rc": 0,
"results": [
"Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\n * base: ftp.iij.ad.jp\n * epel: ftp.iij.ad.jp\n * extras: ftp.iij.ad.jp\n * updates: ftp.iij.ad.jp\nSetting up Install Process\nResolving Dependencies\n--> Running transaction check\n---> Package sl.x86_64 0:3.03-6.el6 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n sl x86_64 3.03-6.el6 epel 11 k\n\nTransaction Summary\n================================================================================\nInstall 1 Package(s)\n\nTotal download size: 11 k\nInstalled size: 14 k\nDownloading Packages:\nRunning rpm_check_debug\nRunning Transaction Test\nTransaction Test Succeeded\nRunning Transaction\n\r Installing : sl-3.03-6.el6.x86_64 1/1 \n\r Verifying : sl-3.03-6.el6.x86_64 1/1 \n\nInstalled:\n sl.x86_64 0:3.03-6.el6 \n\nComplete!\n"
]
}
[vagrant@vagrant-centos65 ~]$ ansible -i hosts 192.168.33.12 -m yum -s -a name=sl
192.168.33.12 | success >> {
"changed": false,
"msg": "",
"rc": 0,
"results": [
"sl-3.03-6.el6.x86_64 providing sl is already installed"
]
}
すでにインストールされていると、もう一度インストールしようとはしません(冪等性)。
4.2.2 commandモジュール
commandモジュールはリモート側で指定したコマンドを実行するモジュールです。
[vagrant@vagrant-centos65 ~]$ ansible -i hosts 192.168.33.12 -m command -a pwd
192.168.33.12 | success | rc=0 >>
/home/vagrant
-a
に実行するコマンドを指定します。-a
はcommandモジュールにかぎらずモジュールに対する引数を指定するためのコマンドです。
4.2.3 get_urlモジュール
get_urlモジュールはリモート側のサーバから、指定したURLのファイルをダウンロードするためのモジュールです。HTTP、HTTPS、FTPに対応しています。
[vagrant@vagrant-centos65 ~]$ ansible -i hosts 192.168.33.12 -m get_url -a 'url=http://www.google.com dest=/home/vagrant'
192.168.33.12 | success >> {
"changed": true,
"dest": "/home/vagrant/index.html",
"gid": 500,
"group": "vagrant",
"md5sum": "0f96747f0d71e58e1c0966d38872b7b7",
"mode": "0664",
"msg": "OK (unknown bytes)",
"owner": "vagrant",
"sha256sum": "",
"size": 17992,
"src": "/tmp/tmpnUBx2x",
"state": "file",
"uid": 500,
"url": "http://www.google.com"
}
これでnodeB(管理されるサーバ)の/home/vagrant
にgoogle先生のトップページがダウンロード出来ました。
5. Playbook
先の節では、コマンドラインでnodeBにモジュールを適応していました。実際には 設定対象のノードとモジュールで記述された構成情報をひとまとめにした Playbook を作成し、適応します。
PlaybookはYAMLで記述します。例えばtest-serverにyumでvimとwgetを入れるPlaybookは下記のとおりです。
---
- hosts: test-server
sudo: yes
tasks:
- name: be sure vim installed
yum: name=vim
- name: be sure wget installed
yum: name=wget
hosts:
に 構成管理されるサーバを指定します。ここでは test-serverを指定しています。sudo: yes
でnodeB側でsudoでコマンドを実行するように指定します。tasks:
以下にサーバ構成情報をモジュールで記述します。-name
はモジュールで実施する個々の処理のコメントです。-name
は必須ではなく同じ内容を次のように書き換えることができます。
---
- hosts: test-server
sudo: yes
tasks:
- yum: name=vim
- yum: name=wget
yumモジュールはnameでインストールするアプリケーションを指定します。入れるバージョンを最新のものにするか等、他にも指定できる引数があるので公式ドキュメントを確認すると良いと思います。
ではこのPlaybookを適応する前に、構文チェックとdry-runをしましょう。
[vagrant@vagrant-centos65 ~]$ ansible-playbook test-playbook.yml --syntax-check
playbook: test-playbook.yml
これで構文チェックが通りました。構文チェックが通らない時は下記のようにエラーが出ます。
[vagrant@vagrant-centos65 ~]$ ansible-playbook test-playbook.yml --syntax-check
ERROR: Syntax Error while loading YAML script, test-playbook.yml
Note: The error may actually appear before this position: line 11, column 1
nekogasuki
次はdry-runをして、実際にansibleが適応できる状態にあるか確認します。コマンドで実行した時と同様に-i hosts
でhostsファイルを指定して、dry-runをします。
[vagrant@vagrant-centos65 ~]$ ansible-playbook test-playbook.yml -i hosts --check
PLAY [test-server] ************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.33.12]
TASK: [be sure vim installed] *************************************************
changed: [192.168.33.12]
TASK: [be sure wget installed] ************************************************
changed: [192.168.33.12]
PLAY RECAP ********************************************************************
192.168.33.12 : ok=3 changed=2 unreachable=0 failed=0
適応しても問題なさそうですね。では適応してみましょう。
[vagrant@vagrant-centos65 ~]$ ansible-playbook test-playbook.yml -i hosts
PLAY [test-server] ************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.33.12]
TASK: [be sure vim installed] *************************************************
changed: [192.168.33.12]
TASK: [be sure wget installed] ************************************************
changed: [192.168.33.12]
PLAY RECAP ********************************************************************
192.168.33.12 : ok=3 changed=2 unreachable=0 failed=0
dry-runのときの末尾につけていた--checkを外せばそのまま実際に適応することになります。これでnodeBにvimとwgetがインストールされました:-)
6.UnixBenchをインストールしてみる
yumモジュール以外を使ってみるために、UnixBenchをインストールするPlaybookを作成してみましょう。具体的にはUnixBenchをgoogle codeからzipを/opt
に落としてきて、解凍し、落としてきたzipファイルを削除します。
---
- hosts:test-server
sudo: yes
vars:
install_path: /opt
tasks:
- name: install dependencies for UnixBench
yum: name=perl-Time-HiRes
- name: download UnixBench
get_url: url=https://byte-unixbench.googlecode.com/files/UnixBench5.1.3.tgz dest=/{{ install_path }}/UnixBench.tar
- name: unpackage UnixBench
command: tar -zxf UnixBench.tar chdir={{ install_path }}
- name: remove UnixBench zip file
command: rm UnixBench.tar chdir={{install_path}}
vars:
でPlaybook内で使う変数を定義します。install_path
という変数に/opt/
を代入します。
tasks:
にUnixBenchを導入方法を記述します。下記の手順になります。
- yumモジュールでUnixBenchに必要なperl-Time-HiResをインストールします。
- get_urlモジュールでzipをダウンロードしてきます。
- commandモジュールで解凍します。
- commandモジュールで落としてきたzipを削除します。
それではインストールしてみましょう。
[vagrant@vagrant-centos65 ~]$ ansible-playbook -i hosts test-playbook.yml
PLAY [test-server] ************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.33.12]
TASK: [install dependencies for UnixBench] ************************************
changed: [192.168.33.12]
TASK: [download UnixBench] ****************************************************
changed: [192.168.33.12]
TASK: [unpackage UnixBench] ***************************************************
changed: [192.168.33.12]
TASK: [remove UnixBench zip file] *********************************************
changed: [192.168.33.12]
PLAY RECAP ********************************************************************
192.168.33.12 : ok=5 changed=4 unreachable=0 failed=0
これでnodeBの/opt/UnixBench
にUnixBenchが配置されている状態になります。
7.まとめ
AnsibleはChefに比べると記述・導入も非常に簡単なので、Infrastructure as Code に興味があればまずAnsibleから始めてみるのがいいと個人的には思います。
今回はツールのダウンロードだけでしたが、apacheのサービスの状態(サービスを有効にする、runlevelを変更する等)、ローカルからのファイルコピーも既存モジュールで記述可能です。こういうことをしたい、ああいうことがしたいというのがあれば公式のドキュメントを漁ってみるのが一番手っ取り早いと思います。
またAnsibleにはベストプラクティスとよばれる公式がおすすめしているPlaybookのフォルダ構成があります。Playbookが肥大化してきたら、参考にしたらよいかと思います。