Ansibleとは?
Ansibleは、サーバに対する設定を、
再利用性の高いコードで記述するためのツールです。
ChefやPuppetが同様のツールとして挙げられます。
(こうした一連のツールを、プロビジョニングツール、と云うそうです。)
###Ansibleの特徴
####1. YAMLで記述する
モジュールなどはPythonやその他言語を利用することになりますが、
基本的にはYAMLという、データ形式を利用します。
Rubyで記述していくChefなどと比較すると、
(複雑な事をする場合を除いては)
可読性が高く、記述量が少なくて済みます。
YAMLでの記述
---
- hosts: webservers
become: True
tasks:
- name: install Apache
yum: name=httpd
####2. プッシュ型
設定を反映したいタイミングで、
対象サーバにSSHで接続し、設定を反映していきます。
他の形式では、プル型があります。Chefはこちらに分類されます。
プル型では、プロビジョニングツールでは、
定期的に対象サーバが、中央サーバに対して変更を取得しに行き、
差分があれば実行する形をとっています。
プル型に対しての優位な点は、SSHで接続できる環境であれば、
変更対象のサーバには何も入れる必要がないことです。
####3. 最低限のことをするだけなら、非常にシンプル
最低限のことをするだけなら、
接続先を定義するインベントリというファイルと、
変更手順が記述されたPlaybookの2つで事足ります。
##チュートリアル
基本的な使い方を一通り試してみましょう。
設定内容は、Vagrantを利用して複数の仮想環境を作成し、
それぞれの環境に対してNginxをインストールする、というものです。
###実行環境
利用しているマシンは、"MacOS X El Capitan"です。
また、作業ディレクトリは、
ホームディレクトリ直下にansible
という名前のディレクトリです。
[you@local] $ cd ~
[you@local] $ mkdir ansible
[you@local] $ cd ansible
最終的には、ansibleディレクトリの内部は、以下の様になります。
ansible
├── Vagrantfile
├── ansible.cfg
├── hosts
└── nginx.yml
###Vagrantでの環境構築
変更を反映するために、Vagrantを利用します。
今回は、80番ポートが開放された仮想環境を2つ作成します。
####1. VirtualBoxのインストール
下記のリンクからダウンロードして、インストールしてください。
https://www.virtualbox.org/
####2. Vagrantのインストール
Vagrantをインストールします。
私の環境はMacOSでhomebrewを導入しているので、
brewでインストールしました。
brew install vagrant
もちろん、他のインストール方法をとっても構いません。
####3.Vagrantで仮想環境を立ち上げる
VagrantFileを設置し、仮想環境を立ち上げます。
まず、初期化します。
[you@local] $ vagrant init bento/centos-6.7
VagrantFileを、下記の内容に変更します。
# -*- mode:ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
config.ssh.insert_key = false
config.vm.define "webserver1" do |webserver1|
webserver1.vm.hostname = "webserver1"
webserver1.vm.box = "bento/centos-6.7"
webserver1.vm.network "private_network", ip: "192.168.11.21"
end
config.vm.define "webserver2" do |webserver2|
webserver2.vm.hostname = "webserver2"
webserver2.vm.box = "bento/centos-6.7"
webserver2.vm.network "private_network", ip: "192.168.11.22"
end
end
仮想環境を立ち上げます。
[you@local] $ vagrant up
仮想環境が作成できたら、sshでの接続方法の確認の為、下記のコマンドを実行します
[you@local] $ vagrant ssh-config
私の環境だと、下記のような内容になりました
Host webserver1
HostName 127.0.0.1
User vagrant
Port 2222
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
PasswordAuthentication no
IdentityFile /Users/you/.vagrant.d/insecure_private_key
IdentitiesOnly yes
LogLevel FATAL
Host webserver2
HostName 127.0.0.1
User vagrant
Port 2200
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
PasswordAuthentication no
IdentityFile /Users/you/.vagrant.d/insecure_private_key
IdentitiesOnly yes
LogLevel FATAL
###Ansibleのインストール
ansibleをインストールします。
Macを利用していて、Homebrewを導入しているなら、下記のコマンドでインストール可能です。
[you@local] $ brew install ansible
あるいは、Pythonのパッケージマネージャ pip が利用可能であればインストールできます。
[you@local] $ sudo pip install ansible
###インベントリ
インベントリは、反映先サーバの一覧です。
一般的には、hostsという名前で利用されるようです。
早速、hostsを作成してみましょう
[you@local] $ vi hosts
[webservers]
192.168.11.21
192.168.11.22
[webservers:vars]
ansible_ssh_user=vagrant
ansible_ssh_private_key_file=~/.vagrant.d/insecure_private_key
webserversというグループに、先ほど作成した仮想環境のIPアドレスを登録し、
webserversのグループに適用する変数として、
- ansible_ssh_user
- ansible_ssh_private_key_file
の2つに値を設定しています。
この2つの変数は、ansibleがSSH接続時に利用するものです。
他にも、 - ansible_ssh_host
- ansible_ssh_port
- ansible_ssh_pass
- ansible_connection
などの変数が利用され、それぞれデフォルトの値を持っています。
###とにかく、疎通を確認してテンションをあげよう
ここで、実際にansibleで通信できるか、一度試してみましょう。
[you@local] $ ansible webservers -i hosts -m ping
-iのオプションで、インベントリ(hosts)を指定します。
-mのオプションで、利用するモジュールを指定しています。
pingは、sshでの疎通を確認するためのモジュールです。
最初の接続では、
The authenticity of host '192.168.11.21 (192.168.11.21)' can't be established.
といった表示がでるかと思います。
続けて、yesとタイプしてください。
私の環境では、このように出力されました。
192.168.11.21 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.11.22 | SUCCESS => {
"changed": false,
"ping": "pong"
}
これで、疎通の確認は完了です。
###ついでに、ansible.cnfも書いておく
ansible.cnfを記述しておくと、インベントリへの記述を減らしたり、
コマンドで記述する内容を減らすことができます。
まず、インベントリを編集します。
[webservers]
192.168.11.21
192.168.11.22
varsの内容を削除しました。
続けて、ansible.cnfを作成します。
[defaults]
hostfile=hosts
remote_user=vagrant
private_key_file=~/.vagrant.d/insecure_private_key
ansible.cfgのなかで、
- hostfile(インベントリ)
- remote_user(ansible_ssh_user)
- private_key_file(ansible_ssh_private_key_file)
以上3点を指定しています。
今回は、インベントリを指定せず実行します。
[you@local] $ ansible webservers -m ping
同様の内容が返却されれば、ansible.cfgの設置は成功です。
###Playbookでnginxをインストール
準備だけで結構かかっちゃいましたが、
ここでやっと、Playbook(環境構築)の記述です。
冒頭で述べましたが、環境構築をYAML形式で記述します。
nginx.ymlというPlaybookを作成します。
---
- hosts: webservers
become: True
tasks:
- name: install nginx repo
yum: name=http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present
- name: install nginx
yum: name=nginx
- name: restart nginx
service: name=nginx state=restarted
基本的なYAMLの基本的な読み方は、Wikipediaあたりを参考にしてください。
内容を一行ずつみていきます
nginx.yml | 説明 |
---|---|
hosts: webservers |
hostの指定。今回はグループ名webservers |
become: True |
sudoerとして実行 |
tasks: |
実行するタスクを順に並べた辞書 |
name: install nginx repo |
ひとつ目のタスクの名前。Nginxのレポジトリをインストール |
yum: name=http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present |
yumモジュールを使ったタスクの内容。記載のURLからYUMレポジトリをインストール。 |
name: install nginx |
Nginxをインストールする旨の名前 |
yum: name=nginx |
YUMモジュールを利用してNginxをインストール |
name: restart nginx |
Nginxを再起動する旨の名前 |
service: name=nginx state=restarted |
Serviceモジュールを利用してNginxを再起動 |
では、このPlaybookを実行してみましょう。
Playbookの実行には、ansible-playbook
コマンドを利用します。
[you@local] $ ansible-playbook nginx.yml
Playbookの中で、変更対象のhostsを指定しているため、コマンドの引数はymlファイルのみです。
実行結果は以下のようになります。
TASK [setup] *******************************************************************
ok: [192.168.11.22]
ok: [192.168.11.21]
TASK [install nginx repo] ******************************************************
changed: [192.168.11.22]
changed: [192.168.11.21]
TASK [install nginx] ***********************************************************
changed: [192.168.11.21]
changed: [192.168.11.22]
TASK [restart nginx] ***********************************************************
changed: [192.168.11.21]
changed: [192.168.11.22]
PLAY RECAP *********************************************************************
192.168.11.21 : ok=4 changed=3 unreachable=0 failed=0
192.168.11.22 : ok=4 changed=3 unreachable=0 failed=0
試しに、ブラウザで反映先にアクセスしてみてください。
http://192.168.11.21
Nginxが正しくインストールされていることがわかるかと思います。
もういちど先ほどのansible-playbook
コマンドを実行すると、どうなるでしょうか。
PLAY [webservers] **************************************************************
TASK [setup] *******************************************************************
ok: [192.168.11.21]
ok: [192.168.11.22]
TASK [install nginx repo] ******************************************************
ok: [192.168.11.22]
ok: [192.168.11.21]
TASK [install nginx] ***********************************************************
ok: [192.168.11.21]
ok: [192.168.11.22]
TASK [restart nginx] ***********************************************************
changed: [192.168.11.22]
changed: [192.168.11.21]
PLAY RECAP *********************************************************************
192.168.11.21 : ok=4 changed=1 unreachable=0 failed=0
192.168.11.22 : ok=4 changed=1 unreachable=0 failed=0
install nginx repo
とinstall nginx
のステータスが、changed
からok
になりました。
これは、YUMモジュールが、インストールがされているかどうかを確認して、インストールされている場合、
OKを返すのみで、実際にインストールを実行していない事を指しています。
何度もインストールすることは、予期しないバグやダウンタイムに繋がります。
それを避けるため、モジュールが勝手にそうしてくれているわけです。
###ハンドラ
しかしながら、nginxの再起動のタスク(restart nginx)は、
それ以上でもそれ以下でもなく、ただただ再起動するだけのタスクであり、
2回目以降の実行でも、再起動後、changedとなっています。
これは、(ごく一瞬ではありますが)ダウンタイムにつながります。
これを避けるために、ハンドラという仕組みがあります。
これは、指定したタスクが終了した場合にのみ実行する変更です。
実際に使ってみるために、nginx.ymlを編集しましょう
---
- hosts: webservers
become: True
tasks:
- name: install nginx repo
yum: name=http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present
- name: install nginx
yum: name=nginx
notify: restart nginx
handlers:
- name: restart nginx
service: name=nginx state=restarted
変更したのは、install nginx
の箇所にnotifyを追加し、内容をrestart nginx
としたこと、
restart nginx
のタスクを、tasks
とは別のhandlers
に移動させたことです。
これは、install nginx
のタスクで、実際に変更が起きた場合にのみ、
handlers
内のrestart nginx
を実行することを意味しています。
実際に、先ほど同様にansible-playbook nginx.yml
のコマンドを叩いてみると、
結果は下の様になるかと思います。
PLAY [webservers] **************************************************************
TASK [setup] *******************************************************************
ok: [192.168.11.21]
ok: [192.168.11.22]
TASK [install nginx repo] ******************************************************
ok: [192.168.11.21]
ok: [192.168.11.22]
TASK [install nginx] ***********************************************************
ok: [192.168.11.21]
ok: [192.168.11.22]
PLAY RECAP *********************************************************************
192.168.11.21 : ok=3 changed=0 unreachable=0 failed=0
192.168.11.22 : ok=3 changed=0 unreachable=0 failed=0
restart nginx
のタスクは実行されなくなりました。
では、本当にNginxがインストールされた場合に、Nginxを再起動するのでしょうか。
確認するために、Vagrantの仮想環境を作りなおしてみましょう。
[you@local] $ vagrant destroy
[you@local] $ vagrant up
仮想環境が再び立ち上がったら、もう一度、ansible-playbook nginx.yml
のコマンドを叩いてみます。
[you@local] $ ansible-playbook nginx.yml
PLAY [webservers] **************************************************************
TASK [setup] *******************************************************************
ok: [192.168.11.22]
ok: [192.168.11.21]
TASK [install nginx repo] ******************************************************
changed: [192.168.11.21]
changed: [192.168.11.22]
TASK [install nginx] ***********************************************************
changed: [192.168.11.21]
changed: [192.168.11.22]
RUNNING HANDLER [restart nginx] ************************************************
changed: [192.168.11.21]
changed: [192.168.11.22]
PLAY RECAP *********************************************************************
192.168.11.21 : ok=4 changed=3 unreachable=0 failed=0
192.168.11.22 : ok=4 changed=3 unreachable=0 failed=0
restart nginx
が実行されています!成功です!
##終わりに
他にもいろいろなTipsがありますが、基本的な利用の流れは以上かと思います。
一通り、実際に試したコードと手順で説明したつもりですが、
もし、なにか足りない箇所があれば、どんどん突っ込んでくださればとおもいます。
Gitなどと組み合わせて、人に優しいインフラ構築を目指していきましょう!
##参考書籍
- Lorin Hochstein (2016) 初めての Ansible Sky株式会社 玉川 竜司 訳 オライリー・ジャパン
- 新原 雅史 (2016) サーバ/インフラエンジニア養成読本 DevOps 編 特集1: 最速攻略! Ansible 2 によるサーバ構築 技術評論社