ご利用ガイド 構成管理ツールAnsibleを使ってみよう
目次
今回のテーマは、サーバの構成管理です。サーバのセットアップを自動化して、もっと楽をしましょう。
ConoHaに限らずクラウドサービスでは、仮想サーバを手軽に追加することができます。しかし、実際にサーバを使うにあたっては、いろいろと作業が必要になります。たとえばWebサーバとして使う場合はApacheやnginxをインストールする必要があるでしょうし、データベースとして使う場合は、MySQLをインストールしてテーブルを作成して初期データを流し込んで・・・といった具合です。
こういった初期セットアップのことをプロビジョニングと呼びます。構成管理ツールを使うことで、このプロビジョニングを自動化することができるだけでなく、複数のマシンに対して効率よくプロビジョニングを実行することができるようになります。
構成管理ツールは非常に多くありますが、今回はAnsibleを紹介します。Pythonで書かれたソフトウェアですが、設定はYAMLファイルに書くので、Pythonを覚える必要はありません。また、サーバに何かソフトウェアをインストール必要がなく、SSH接続ができれば使うことができるため、ConoHaでVPSを作成した後にすぐ使うことができます。
Ansible is Simple IT Automation
冪等性
構成管理ツールを使うに当たって、「冪等性」という考え方を知っておくと良いでしょう。「べきとうせい」と読みます。細かい冪等の概念についてはWikipediaをご覧いただくとして、ここではサーバなどに対してスクリプトを実行するときに、一回実行するのと複数回実行するので、同じ結果が保証されることとお考えください。
たとえば、サーバに対してnginxをインストールするスクリプトを作ったとします。最初の実行時はnginxがインストールされますが、二度目はどうなるでしょう? おそらく「すでにnginxがインストール済み」というエラーになり、スクリプトが停止してしまいます。
一回だけ実行するスクリプトであれば、これで問題ないかもしれません。しかし、サーバをセットアップして、その後ずっとそのまま使われることは少ないでしょう。nginxだけでなくMySQLも必要になるかもしれませんし、nginxのバーチャルホストが追加されるかもしれません。さらに負荷対策で同じ設定のサーバを追加したくなったらどうしましょう? 新規でセットアップするサーバと既存サーバで、それぞれ別の設定を行う必要があります。これは非常に面倒です。
冪等性が確保されている場合は単純です。スクリプトを変更して、すべてのサーバに実行するだけで完了します。新規のサーバにはスクリプトの内容がすべて適用され、既存のサーバには差分のみが適用されます。
注意点として、構成管理ツールを使えば必ず冪等性が確保されるわけではありません。あくまで、冪等性の確保はスクリプトを書く側に責任があります。とはいえ、構成管理ツールの多くは、サーバセットアップでよく使う手順を定型化していることが多く、多くの部分をツールが面倒を見てくれます。これは構成管理ツールを使う大きな動機になります。
Ansibleのインストール
ではAnsibleをインストールしてみましょう。Ansibleはクライアントとなる手元のPCにインストールします。
手順はオフィシャルのドキュメントにありますが、メジャーなLinuxディストリビューションでは、パッケージ管理システムでインストールすることができます。また、Mac OSXはHomebrewなどでインストールできます。
Installation – Ansible Documentation
CentOSなど(yum)
# install the epel-release RPM if needed on CentOS, RHEL, or Scientific Linux
$ sudo yum install ansible
Ubuntuなど(apt)
$ sudo apt-get install software-properties-common
$ sudo apt-add-repository ppa:ansible/ansible
$ sudo apt-get update
$ sudo apt-get install ansible
Mac OSX
$ brew update
$ brew install ansible
Windowsは残念ながらCygwinを使うか、仮想化環境でLinuxなどを使うしか方法がないようです。
使ってみよう
では使ってみましょう。このエントリで使用しているAnsibleのバージョンは1.7.2です。
ホストの定義
まずAnsibleでは、操作する対象のホストを定義します。/etc/ansible/hostsファイルを見てみてください。
[webservers]
alpha.example.org
beta.example.org
[dbservers]
db01.intranet.mydomain.net
db02.intranet.mydomain.net
上記は抜粋ですが、中括弧でグループ名を指定し、その下に実際のホスト名やIPアドレスを記述します。グループは、ansibleで操作するときの実行単位になります。このサンプルでは、WebサーバやDBサーバに対して一括して処理を実行することを想定していることになりますね。
実際にユーザが使う場合は、このファイルを直接書き換えるのではなく、カレントディレクトリに適当な名前でホスト定義ファイルを作ります。以下の内容でserversというファイルを作成してください。
[conoha-vps]
157.7.***.***
20141201-ansible/servers – GitHub
(“***”の部分は、お客様のVPSのIPアドレスに変更してください)
このようなホスト情報を定義したファイルを、Ansibleではインベントリファイル(inventory file)と呼んでいます。
単独のコマンドを実行する
ホストの定義が完了したので、これらのホストにコマンドを実行してみましょう。Ansibleにはいくつかコマンドが用意されていますが、まずはansibleコマンドを使ってみます。以下のコマンドを実行してみてください。
ansible conoha-vps -i servers -m command -a "hostname"
VPS上でhostnameコマンドが実行され、その結果が表示されました。引数の意味は以下です。
・ -i: インベントリファイルを指定します。先ほど作成したserversを指定しました。
・ -m: ansibleが実行するモジュールを指定します。ここではサーバ上でコマンドを実行するcommandモジュールを指定しました。モジュールについては後述します。
・ -a: モジュールに対して引数を与えます。commandモジュールの場合は、サーバ上で実行するコマンドになります。
つまり、サーバ上では-aに指定したコマンドが実行されているわけですね。hostnameの部分を変更することで、いろいろなコマンドが実行できます。
複数ホストで実行する
ホストを追加する場合も簡単で、インベントリファイルに追加するだけです。
[conoha-vps]
157.7.***.***
157.7.***.***
...
インベントリファイルにホストを追加して、先ほどのansibleコマンドを実行してみてください。すべてのホストでhostnameコマンドが実行されます。このように、実行する処理と実行対象のホストを分離して管理することができます。
playbookを使う
Ansibleにはplaybookと言う仕組みがあります。YAMLフォーマットで書かれたファイルにサーバに対する操作を定義していき、それをansible-playbookコマンドで実行することで、サーバを常にplaybookで定義した状態にしておくことができます。先ほどansibleコマンドを実行しましたが、あれは単発で終了してしまいます。現実的にはサーバに対するplaybookを作成して、それを使って運用していくことになるでしょう。
Playbooks – Ansible Documentation
書式や機能について、オフィシャルサイトにドキュメントはありますが、非常に多機能なのですべて読むのはなかなか大変です。サンプルを見て実行してもらう方が理解が早いと思います。以下の通り進めてみてください。
まずは、新しくVPSを作成してインベントリファイルにホストのIPアドレスを記述します。ファイル名はserversで良いでしょう。
[conoha-vps]
157.7.***.***
次にplaybookを作成します。以下の内容をそのままsetup.ymlと言うファイル名で保存してください。
- hosts: conoha-vps
remote_user: root
tasks:
- name: install nginx
yum: name=nginx state=latest
notify: restart nginx
- name: allow port 80
lineinfile: dest=/etc/sysconfig/iptables line="-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT" insertafter="^:OUTPUT "
notify: restart iptables
handlers:
- name: restart nginx
service: name=nginx state=restarted
- name: restart iptables
service: name=iptables state=restarted
20141201-ansible/setup.yml – GitHub
このplaybookは、ConoHa標準OSで作成されたVPSに対して、
・ nginxのインストール
・ iptablesの設定ファイルを変更してHTTPのポートを開放
・ iptablesをリスタート
・ nginxを起動
という手順を実行します。
ではお待ちかねansible-playbookを実行してみましょう。
ansible-playbook -i servers setup.yml
-iでインベントリファイルを指定するのは、ansibleコマンドと同じです。第二引数にplaybookファイルを指定すると、その内容が実行されます。結果は以下のようになります。
http://[VPSのアドレス]にアクセスしてみましょう。nginxのデフォルトページが表示されると思います。
黄色でchangedとなっているタスクがサーバ上で変更が行われた箇所で、nginxのインストールやiptablesの変更が実際に行われたことを意味します。VPSの初期状態では、nginxなどはインストールされていないので当然ですね。
もう一度同じコマンドを実行してみましょう
changedではなくokとなりました。既に設定が行われているため、変更処理が行われなかったことを意味します。nginxやiptablesのリスタートも行われていません。Ansibleがサーバの状態を調べ、必要のない変更処理を自動的にスキップしてくれたのです。このようにAnsibleを使うと、冪等性の確保をツール側に任せることができます。
では次に、playbookを以下のように変更してみます。
- hosts: conoha-vps
remote_user: root
tasks:
- name: install nginx
yum: name=nginx state=latest
notify: restart nginx
- name: allow port 80
lineinfile: dest=/etc/sysconfig/iptables line="-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT" insertafter="^:OUTPUT "
notify: restart iptables
- name: install mysql
yum: name=mysql-server state=latest
notify: restart mysql
handlers:
- name: restart nginx
service: name=nginx state=restarted
- name: restart iptables
service: name=iptables state=restarted
- name: restart mysqld
service: name=mysqld state=restarted
MySQLも追加でインストールしてみることにしました。これでもう一度ansible-playbookを実行してみましょう。
無事インストールされました。nginxとiptablesには何も処理は行われていません。playbookの内容とサーバの状態が比較され、変更があった部分のみが適用されています。
playbookの解説
今回使ったplaybookについて解説をします。
# 実行するホストグループを指定します
- hosts: conoha-vps
# サーバ上でコマンド実行する際のユーザを指定します
remote_user: root
# tasksの下にサーバ上で実行する処理を列挙します
tasks:
- name: install nginx
yum: name=nginx state=latest
notify: restart nginx
- name: allow port 80
lineinfile: dest=/etc/sysconfig/iptables line="-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT" insertafter="^:OUTPUT "
notify: restart iptables
handlers:
- name: restart nginx
service: name=nginx state=restarted
- name: restart iptables
service: name=iptables state=restarted
hosts remote_user, tasksについてはコメントを入れたとおりです。実際にサーバ上で処理される内容はtasksエントリの下に定義していきます。
- name: install nginx
yum: name=nginx state=latest
notify: restart nginx
1行目のnameはこの処理につける名前です。ansible-playbookを実行したときに表示されるので、わかりやすい名前をつけると良いでしょう。
2行目はモジュール名です。Ansibleでは様々な処理をモジュールとして用意していて、ここではyumと言うモジュールを使っています。文字通りCentOS系のyumコマンドをサーバ上で実行するものです。モジュールの一覧はドキュメントにあります。本当にたくさんのモジュールがあります。
All Modules – Ansible Documentation
3行目のnotifyは、最下部のhandlersとセットで機能します。handlersはモジュールの処理が行われ、変更があった場合に実行される処理です。典型的にはnginxの設定ファイルを書き換えた後にリスタートするようなケースです。nofityを書いておくと、モジュールの処理で変更があった場合に、ansibleが自動的に対応するhandlersセクションの処理を実行します。このplaybookでも、nginxやiptablesが変更されたときにリスタートを行うようにしています。
おわりに
ansibleは構成管理ツールの中では比較的シンプルで、処理対象のサーバにはSSHログインできれば良いという軽量さが良いところだと思います。また、設定ファイルもYAMLで書けるので直感的です。今回ご紹介した内容はほんの一部でして、たとえば変数を使ったり制御構造を記述したりと、より実践的な使い方もあります。
たとえば、下記のplaybookは筆者がテスト用に作ったもので、ConoHa VPS3台でロードバランサ(HAProxy)とWebサーバ2台をプライベートネットワークで接続する構成を構築するplaybookです。あまり綺麗ではありませんが、ご参考になればと思います。
20141201-ansible/lb-setup – GitHub
ConoHaはVPSを簡単に立ち上げることができますが、Ansibleなどの構成管理ツールを使うことで、その後のプロビジョニングも簡単にすることができます。また、複数台のVPSを運用する場合にも、まとめてプロビジョニングできるのでとても有用です。是非試してみてください。
- 問題は解決できましたか?
-