Ansible とは構成管理ツールです。主に、サーバー関連のセットアップ作業、アプリケーションのデプロイ作業の自動化・コード化を目的として利用されます。

Ansible の特徴や利点の紹介などは他に譲ることとし、ここでは Ansible の基本的な使い方について記載します。

Ansible はどう動くのか

実際に触っていく前に、Ansible がいかにして動作しているかを簡単に解説します。

Ansible は大きく

  • インベントリファイル
  • playbook
  • モジュール

の 3 つの要素から成り立っています。

インベントリファイルとは、セットアップ対象マシン (以下、ゲスト) の IP アドレスが羅列されたファイルです。グループ化などもサポートします。Ansible はイベントリファイルに書かれたゲストに対してのみ働きかけます。

playbook とは、Ansible がゲストに対して実行するタスクを羅列したファイル群です。実際にはタスクだけでなく、ゲストに転送するファイルや、そのテンプレート、変数定義なども含みます。おそらく Ansible を使っていて、もっとも触ることになるのは playbook です。

モジュールとは、Ansible がゲスト上で実行する実行ファイルです。実行ファイルはゲスト上で実行できさえすればよく、どんなプログラミング言語で実装していてもよいことになっています1。Ansible は playbook で指定されたモジュールをゲストに転送し、ゲスト上で実行して、そのモジュールの出力をホスト上でハンドルします。

インストール

Ansible は Python で書かれた構成管理ツールです。実行には Python 処理系 (バージョン 2.6 以上) が必要になります。また、Ansible を実行するホストとしては、Windows はサポートされていません。MacOSX や Linux などの *nix 系 OS が必要です。

Python とそのパッケージ管理ツールである pip はインストールされているものとして、以下のコマンドを実行することで Ansible をインストールできます:

$ pip install ansible

必要に応じて sudo をつけてください。

本稿では以下のバージョンを対象としています:

$ ansible --version
ansible 2.0.0.2

実行対象の準備

冒頭で述べた通り Ansible はサーバーのセットアップ作業などを自動化・コード化する目的として利用されるツールです。実行にはセットアップ対象のマシンが必要になります。ホストマシンそのものをセットアップ対象とすることもできますが、今回は別マシンを用意することとします。

VirtualBox などを用いて用意してください。OS は CentOS のバージョン 6 系を想定します。

インベントリファイルの準備

まずはインベントリファイルを準備します。ini ファイル風の形式を採っています。

$ cat <<EOF >hosts
[develop]
192.168.50.50
EOF

IP アドレスは環境に合わせて修正してください。接続確認をやってみます。

$ ansible all -i hosts -m ping

hosts に記述されたすべてのゲストに対し、ping モジュールを実行しています。ping モジュールはその名の通り、ゲストとの疎通確認を行うだけのモジュールです。次のような出力が得られれば成功です。

192.168.50.50 | success >> {
    "changed": false, 
    "ping": "pong"
}

このような出力が得られない場合は、-u オプションや -k オプションなどを試してみてください。

playbook を書く

playbook は YAML 形式で書きます。単一のファイルに書いたり、いくつかのフォルダに分けて書いたり、配置方法にはいくつかバリエーションがあります。まずは単一のファイルに書く形式を採ることにします。

以下の playbook では、構成管理ツール界の hello, world にあたる、Apache のインストールを行っています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
---
- hosts: all
  gather_facts: no
  become: yes
  tasks:
    - name: be sure httpd is installed
      yum: name=httpd state=installed

    - name: be sure httpd is configured
      template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf backup=true
      notify: restart httpd

    - name: httpd service state
      service: name=httpd state=running enabled=yes

  handlers:
    - name: restart httpd
      service: name=httpd state=restarted

1行目の --- は YAML 文書の区切りを表します。2 上記の hosts から tasks のような定義を1ファイル内に複数書きたいとき、それらを --- で区切るような形で利用します。

2行目の hosts は、イベントリファイルに定義されているゲストのうち、どのホストを対象とするかを指定する項目です。ここでは all としているので、全ゲストが対象となります。

3行目の gather_facts は、playbook の実行時にゲストの情報を収拾するかどうかを指定する項目です。デフォルトは「収拾する」です。ここでは no としており、「収拾しない」ようにしています。gather_facts による情報収集はそれなりに時間がかかるので、不要な場合には no としておくのがよいでしょう。

4行目の become は、各タスクをホストとは別のアカウントで実行するかどうかを指定します。要は sudo コマンドを使って root としてコマンドを実行したい (など) に指定します。3 サーバーのセットアップ作業では、パッケージのインストールや設定ファイルの変更など、sudo コマンドを使うことが多くなります。ここでは yes を指定し、各タスクを sudo コマンドを通して実行するようにしています。

5行目以降が、実際にゲスト上で実行されるタスクの一覧になります。再掲します。

 5
 6
 7
 8
 9
10
11
12
13
14
  tasks:
    - name: be sure httpd is installed
      yum: name=httpd state=installed

    - name: be sure httpd is configured
      template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf backup=true
      notify: restart httpd

    - name: httpd service state
      service: name=httpd state=running enabled=yes

最初のタスクでは、yum モジュールを使って httpd パッケージをインストールしています。期待する状態は state=installed であり、すでに httpd がインストールされていれば何もしません。

2番目のタスクでは、ホスト上にある httpd.conf.j2 をゲストの /etc/httpd/conf/httpd.conf にアップロードしています。backup=yes としており、転送前のファイルのバックアップがゲスト上に保存されます (同じフォルダ上に、日付付きのファイル名として保存されます)。

モジュールの名前が copy などではなく template となっているのは、転送元のファイルはあくまでテンプレートであり、テンプレートから生成したファイルをアップロードしているからです。Ansible はテンプレートエンジンとして Jinja2 を採用しています。例えば httpd.conf.j2 に

...
DocumentRoot {{ document_root }}
...

のような記述があれば、playbook 上で定義された変数 document_root によって {{ document_root }} の部分が置き換えられたうえで、ゲストに転送されます。

notify: restart httpd は、後述の handlers に対する命令です。「このタスク (be sure httpd is configured) によってゲストに変更が生じた場合、restart httpd という名前のついた handler を実行せよ」という意味になります。つまり、「httpd.conf に変更があったら httpd を再起動せよ」ということになります。

3番目のタスクでは、httpd サービスが OS 起動後に自動起動されるよう、サービスを有効化しています。

httpd.conf.j2 を適当に (ただし構文エラーなどがないように) 準備して、実行してみます。手元では次のような実行結果になりました。

$ ansible-playbook playbook.yml -i hosts -u vagrant -k
SSH password:

PLAY [all] ********************************************************************

TASK: [be sure httpd is installed] ******************************************** 
changed: [192.168.50.50]

TASK: [be sure httpd is configured] ******************************************* 
changed: [192.168.50.50]

TASK: [httpd service state] *************************************************** 
changed: [192.168.50.50]

NOTIFIED: [restart httpd] ***************************************************** 
changed: [192.168.50.50]

PLAY RECAP ******************************************************************** 
192.168.50.50              : ok=4    changed=3    unreachable=0    failed=0

ゲストにログインし、httpd.conf のバックアップが取られているか確認してみます。

$ ls -l /etc/httpd/conf/
total 88
-rw-r--r-- 1 root root 34418 Aug 29 07:29 httpd.conf
-rw-r--r-- 1 root root 34419 Aug 18 05:57 httpd.conf.2015-08-29@07:29~
-rw-r--r-- 1 root root 13139 Aug 24 17:53 magic

httpd.conf.2015-08-29@07:29~ という名前でバックアップが残っているようです。

次のステップ

Ansible の基本的な使い方を追ってきました。次のステップとしては、

  • playbook の構造化
  • vault を使った秘密情報の難読化
  • モジュールの実装

辺りになるかと思います。Ansible には他にも機能がたくさんあります。詳しくはドキュメントを参照してください。


  1. Ansible の公式モジュールは、すべて Python で実装されています。 

  2. YAML では文書の前にディレクティブを書くことができることになっており、 --- はディレクティブと文書、および文書と文書を区切るための記号です。最初の文書を始める際にも必要なので、1 行目に書いています。詳しくは YAML のドキュメント を参照してください。 

  3. 2.0 から sudo は非推奨となり、become が推奨されるようになりました。sudosudo コマンドに直接依存していたのに対し、become では become_method を用いてバックエンドのコマンドを指定することができるようになっています。まぁ話は分かるんですが、become: yes より sudo: yes のほうが分かりやすいと、私は思いますけどね。ちなみに sudo も残ってる ので、使おうと思えば使えます。