プレイブック

アドホックコマンドは簡単なオペレーションではとても役に立ちます。しかし、サーバーのデプロイなどの複雑なシナリオには適していません。複雑なシナリオには「プレイブック」を使用します。


プレイブックの基本

プレイブックの構成要素です。

タスク
  • アドホックコマンドに該当します。
  • モジュールにオプションを渡して実行します。
プレイ
  • 1 つ以上のタスクが集まったものです。
  • タスクの実行順序は記述順です。
プレイブック
  • 1 つ以上のプレイの集合体です。
  • プレイの実行順序は記述順です。
  • 管理対象ホストでプレイブックを実行すると、管理対象ホストは「あるべき状態」になります。
プレイブックファイル
  • プレイブックが書かれたファイルのことです。

プレイブックは YAML 形式で記述します。基本的なルールは以下のとおりです。

  • "---" から始まります。
  • インデントは半角空白 2 文字です。タブ文字は使用できません。

プレイ内の重要なキーワード(ディレクティブ)です。

name:
プレイやタスクの名前を指定します。
hosts:
プレイを適用する管理対象ホストをホストパターンで指定します。
tasks:
モジュールを呼び出し、モジュールにオプションの値を渡して実行します。
become:
プレイまたはタスクの実行時に権限昇格します。

プレイはべき等性を保つようにすべきです。管理対象ホストでプレイを実行して「あるべき状態」になった後は、再度プレイを実行しても状態が変更されないようにすべきです。


プレイブックの作成

インベントリ内の web グループに含まれる管理対象ホスト上に次の 3 ステップで Apache Web Server を構築するプレイを作成します。

  1. Apache ( httpd パッケージ)のインストール
  2. httpd サービスの起動
  3. index.html の配置

作成準備

プレイを作成する準備として、ホームディレクトリ内に各ファイルの格納用にansible-filesディレクトリを作成します。

[vagrant@ansible ~]$ cd
[vagrant@ansible ~]$ pwd
/home/vagrant
[vagrant@ansible ~]$ mkdir ./ansible-files/
[vagrant@ansible ~]$ cd ./ansible-files/
[vagrant@ansible ansible-files]$ pwd
/home/vagrant/ansible-files
[vagrant@ansible ansible-files]$

次に、「アドホックコマンド」で作成したインベントリファイルをansible-filesディレクトリに移動します。

[vagrant@ansible ansible-files]$ mv ../hosts.yml ./
[vagrant@ansible ansible-files]$ ls -l
total 4
-rw-rw-r--. 1 vagrant vagrant 414 Apr 19 15:30 hosts.yml
[vagrant@ansible ansible-files]$

移動したインベントリファイルの内容です。

---
all:
  vars:
    ansible_user: vagrant
  hosts:
    node1:
      ansible_host: 192.168.1.161
      ansible_ssh_private_key_file: ~/.ssh/node1_key
    node2:
      ansible_host: 192.168.1.162
      ansible_ssh_private_key_file: ~/.ssh/node2_key
    node3:
        ansible_host: 192.168.1.163
        ansible_ssh_private_key_file: ~/.ssh/node3_key
  children:
    web:
      hosts:
        node2:
        node3:

targets セクション

vi コマンドなどでapache.ymlファイルを作成し、プレイの定義部分を記述します。この定義部分を targets セクションと呼びます。

1
2
3
4
---
- name: Apache server installed
  hosts: web
  become: yes
1 行目
・プレイの開始です。
2 行目
・このプレイの名前を "Apache server installed" に設定しました。
3 行目
・管理対象をホストパターンで指定します。
・今回は管理対象に web グループを指定しました。
4 行目
・プレイ全体を権限昇格して実行することを宣言しました。

tasks セクション

次にタスクを定義します。タスクを定義する部分を tasks セクションと呼びます。 tasks セクションはキーワードtasks:から始まります。

まず、Apache のインストール部分です

1
2
3
4
5
  tasks:
  - name: latest Apache version installed
    yum:
      name: httpd
      state: latest

どのモジュールも同じような形式で定義します。

1 行目
・ tasks セクションの開始です。
2 行目
・ このタスクの名前を "latest Apache version installed" に設定しました。
3 行目
・ タスクで使用するモジュールの宣言です。
・ Apache のパッケージをインストールするので yum モジュールを使用します。
4 ~ 5 行目
・ モジュールの引数を定義します。
・ 今回は yum モジュールの引数を name オプションと state オプションで渡しています。

yumモジュールのオプションです。

name:
  • インストールや削除するパッケージ名を指定します。
state:
  • present:指定したパッケージをインストールした状態にします。
  • latest :指定したパッケージの最新版をインストールした状態にします。
  • absent :指定したパッケージを削除した状態にします。

次に httpd サービスを起動します。

1
2
3
4
5
  - name: Apache enabled and running
    systemd:
      name: httpd.service
      state: started
      enabled: yes

CentOS7/RHEL7 からサービスの管理用に systemd が導入されました(従来の service も使用できる場合があります)。 Ansible でもそれに対応してsystemdモジュールが追加されたので、それを使用します。書き方は Apache のインストールと同じ形式です。

systemd モジュールのオプションの説明です。

name:
  • 起動や停止などするサービス名を指定します。
state:
  • started :サービスを開始した状態にします。
  • stopped :サービスを停止した状態にします。
  • restarted:サービスの状態に関係なく、サービスを再起動した状態にします。
  • reloaded :サービスの状態に菅家なく、サービスをリロードした状態にします。
enabled:
  • yesを指定すると、ホストの起動時に指定したサービスを自動起動します。

最後に表示する Web ページを管理対象にコピーします。

1
2
3
4
  - name: copy index.html
    template:
      src: ~/ansible-files/index.j2
      dest: /var/www/html/index.html

ファイルのコピーにはcopyモジュールとtemplateモジュールが使用できます。今回はtemplateモジュールを使用します。

templateモジュールのオプションの説明です。

src:
  • コピー元のパス(ファイル)を指定します
  • コピー元のファイルには変数を埋め込むことができます。
dest:
  • コピー先のパス(ファイル)を指定します。

コピー元のindex.j2ファイルの内容です。

Hello, Ansible world.<br>
Powerd by {{ inventory_hostname }}<br>

プレイ全体です。

---
- name: Apache server installed
  hosts: web
  become: yes

  tasks:
  - name: latest Apache version installed
    yum:
      name: httpd
      state: latest
  - name: Apache enabled and running
    systemd:
      name: httpd.service
      state: started
      enabled: yes
  - name: copy index.html
    template:
      src: ~/ansible-files/index.j2
      dest: /var/www/html/index.html

プレイブックの実行

ansible-playbookコマンドでプレイブックを実行します。以下のオプションはansibleコマンドと同じです。

-i, --inventory, --inventory-file
 インベントリファイルを指定します。
--list-hosts インベントリ内で実行対象になる管理対象ホストを確認します。

次のオプションも使用できます。

--syntax-check プレイブック内のプレイの構文をチェックします。

プレイブックを実行する前に、まず構文に誤りがないかチェックします。

[vagrant@ansible ansible-files]$ ansible-playbook -i hosts.yml --syntax-check apache.yml

playbook: apache.yml
[vagrant@ansible ansible-files]$

構文に誤りがないことを確認したら、次に実行対象になる管理対象ホストを確認します。今回は node2 と node3 が実行対象です。

[vagrant@ansible ansible-files]$ ansible-playbook -i hosts.yml --list-hosts apache.yml

playbook: apache.yml

  play #1 (web): Apache server installed        TAGS: []
    pattern: [u'web']
    hosts (2):
      node3
      node2
[vagrant@ansible ansible-files]$

次にプレイブックを実行します。

[vagrant@ansible ansible-files]$ ansible-playbook -i hosts.yml apache.yml

PLAY [Apache server installed] ******************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [node3]
ok: [node2]

TASK [latest Apache version installed] **********************************************************************************************************************
changed: [node2]
changed: [node3]

TASK [Apache enabled and running] ***************************************************************************************************************************
changed: [node2]
changed: [node3]

TASK [copy index.html] **************************************************************************************************************************************
changed: [node3]
changed: [node2]

PLAY RECAP **************************************************************************************************************************************************
node2                      : ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
node3                      : ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

[vagrant@ansible ansible-files]$

プレイブックの実行の成否は PLAY RECAP で確認します。実行対象の管理対象ホストごとに、実行状況のサマリが表示されます。

ok
  • 実行が成功したタスクの数です。
  • 管理対象ホストが変更されたか否かに関係なくカウントされます。
changed
  • 管理対象ホストを変更したタスクの数です。
unreachable
  • 管理対象ホストに接続できなかったタスクの数です。
failed
  • タスクの実行に失敗した数です。
skipped
  • 実行がスキップされた(飛ばされた)タスクの数です。
rescued
  • block 内でエラーが発生したが、 rescure ブロックで処理を継続した数です。
ignored
  • タスクの実行は失敗したが、その失敗が無視されたタスクの数です。

通常のプレイブックでは ok / changed / skipped だけカウントされていたら、そのプレイブックの実行は成功です。

もう一度、プレイブックを実行します。

[vagrant@ansible ansible-files]$ ansible-playbook -i hosts.yml apache.yml

PLAY [Apache server installed] ******************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [node3]
ok: [node2]

TASK [latest Apache version installed] **********************************************************************************************************************
ok: [node3]
ok: [node2]

TASK [Apache enabled and running] ***************************************************************************************************************************
ok: [node3]
ok: [node2]

TASK [copy index.html] **************************************************************************************************************************************
ok: [node3]
ok: [node2]

PLAY RECAP **************************************************************************************************************************************************
node2                      : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
node3                      : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

[vagrant@ansible ansible-files]$

PLAY RECAP の結果が OK だけです。すでに管理対象ホストが「あるべき状態」になっているところにプレイブックを再度実行したので何も変わりませんでした。このように、アドホックコマンドと同様にプレイブックでもべき等性は保たれています。


実行結果の確認

プレイブックの実行結果を確認します。
まず、配置した index.html が表示されるかブラウザーで確認します。
../_images/2020-04-20_21h21_31.png ../_images/2020-04-20_21h21_38.png

Powerd by の後に管理対象ホスト名が表示されており、正しく index.html が配置されたことが確認できました。

次に管理対象ホストにログインし、次の状態を確認します。

  • Apahce がインストールされていること。
  • httpd サービスが起動していること。
[vagrant@ansible ansible-files]$ ssh 192.168.1.162 -l vagrant -i ~/.ssh/node2_key
Last login: Mon Apr 20 21:08:54 2020 from 192.168.1.151
[vagrant@node2 ~]$ yum list installed httpd
Loaded plugins: fastestmirror
Determining fastest mirrors
 * base: ftp.riken.jp
 * extras: ftp.riken.jp
 * updates: ftp.riken.jp
Installed Packages
httpd.x86_64                                                            2.4.6-90.el7.centos                                                             @base
[vagrant@node2 ~]$ rpm -qi httpd
Name        : httpd
Version     : 2.4.6
Release     : 90.el7.centos
Architecture: x86_64
Install Date: Mon 20 Apr 2020 08:57:21 PM JST
Group       : System Environment/Daemons
Size        : 9817301
License     : ASL 2.0
Signature   : RSA/SHA256, Fri 23 Aug 2019 06:25:32 AM JST, Key ID 24c6a8a7f4a80eb5
Source RPM  : httpd-2.4.6-90.el7.centos.src.rpm
Build Date  : Thu 08 Aug 2019 08:43:53 PM JST
Build Host  : x86-01.bsys.centos.org
Relocations : (not relocatable)
Packager    : CentOS BuildSystem <http://bugs.centos.org>
Vendor      : CentOS
URL         : http://httpd.apache.org/
Summary     : Apache HTTP Server
Description :
The Apache HTTP Server is a powerful, efficient, and extensible
web server.
[vagrant@node2 ~]$ systemctl status httpd.service
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2020-04-20 20:57:24 JST; 38min ago
     Docs: man:httpd(8)
           man:apachectl(8)
 Main PID: 3746 (httpd)
   Status: "Total requests: 6; Current requests/sec: 0; Current traffic:   0 B/sec"
   CGroup: /system.slice/httpd.service
           ├─3746 /usr/sbin/httpd -DFOREGROUND
           ├─3747 /usr/sbin/httpd -DFOREGROUND
           ├─3748 /usr/sbin/httpd -DFOREGROUND
           ├─3749 /usr/sbin/httpd -DFOREGROUND
           ├─3750 /usr/sbin/httpd -DFOREGROUND
           ├─3751 /usr/sbin/httpd -DFOREGROUND
           └─3875 /usr/sbin/httpd -DFOREGROUND
[vagrant@node2 ~]$ logout
Connection to 192.168.1.162 closed.
[vagrant@ansible ansible-files]$
[vagrant@ansible ansible-files]$ ssh 192.168.1.163 -l vagrant -i ~/.ssh/node3_key
Last login: Mon Apr 20 21:08:54 2020 from 192.168.1.151
[vagrant@node3 ~]$ yum list installed httpd
Loaded plugins: fastestmirror
Determining fastest mirrors
 * base: ftp-srv2.kddilabs.jp
 * extras: ftp-srv2.kddilabs.jp
 * updates: ftp-srv2.kddilabs.jp
Installed Packages
httpd.x86_64                                                            2.4.6-90.el7.centos                                                             @base
[vagrant@node3 ~]$ rpm -qi httpd
Name        : httpd
Version     : 2.4.6
Release     : 90.el7.centos
Architecture: x86_64
Install Date: Mon 20 Apr 2020 08:57:21 PM JST
Group       : System Environment/Daemons
Size        : 9817301
License     : ASL 2.0
Signature   : RSA/SHA256, Fri 23 Aug 2019 06:25:32 AM JST, Key ID 24c6a8a7f4a80eb5
Source RPM  : httpd-2.4.6-90.el7.centos.src.rpm
Build Date  : Thu 08 Aug 2019 08:43:53 PM JST
Build Host  : x86-01.bsys.centos.org
Relocations : (not relocatable)
Packager    : CentOS BuildSystem <http://bugs.centos.org>
Vendor      : CentOS
URL         : http://httpd.apache.org/
Summary     : Apache HTTP Server
Description :
The Apache HTTP Server is a powerful, efficient, and extensible
web server.
[vagrant@node3 ~]$ systemctl status httpd.service
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2020-04-20 20:57:24 JST; 39min ago
     Docs: man:httpd(8)
           man:apachectl(8)
 Main PID: 3742 (httpd)
   Status: "Total requests: 4; Current requests/sec: 0; Current traffic:   0 B/sec"
   CGroup: /system.slice/httpd.service
           ├─3742 /usr/sbin/httpd -DFOREGROUND
           ├─3743 /usr/sbin/httpd -DFOREGROUND
           ├─3744 /usr/sbin/httpd -DFOREGROUND
           ├─3745 /usr/sbin/httpd -DFOREGROUND
           ├─3746 /usr/sbin/httpd -DFOREGROUND
           ├─3747 /usr/sbin/httpd -DFOREGROUND
           └─3873 /usr/sbin/httpd -DFOREGROUND
[vagrant@node3 ~]$ logout
Connection to 192.168.1.163 closed.
[vagrant@ansible ansible-files]$

管理対象ホストを再起動します。

C:\vagrant\ansible-study>vagrant reload node2
==> node2: Attempting graceful shutdown of VM...
==> node2: Checking if box 'centos/7' version '1905.1' is up to date...
==> node2: Clearing any previously set forwarded ports...
==> node2: Fixed port collision for 22 => 2222. Now on port 2201.
==> node2: Clearing any previously set network interfaces...
==> node2: Preparing network interfaces based on configuration...
    node2: Adapter 1: nat
    node2: Adapter 2: bridged
==> node2: Forwarding ports...
    node2: 22 (guest) => 2201 (host) (adapter 1)
==> node2: Running 'pre-boot' VM customizations...
==> node2: Booting VM...
==> node2: Waiting for machine to boot. This may take a few minutes...
    node2: SSH address: 127.0.0.1:2201
    node2: SSH username: vagrant
    node2: SSH auth method: private key
==> node2: Machine booted and ready!
[node2] GuestAdditions 6.1.6 running --- OK.
==> node2: Checking for guest additions in VM...
==> node2: Setting hostname...
==> node2: Configuring and enabling network interfaces...
==> node2: Rsyncing folder: /cygdrive/c/vagrant/ansible-study/ => /vagrant
==> node2: Machine already provisioned. Run `vagrant provision` or use the `--provision`
==> node2: flag to force provisioning. Provisioners marked to run always will still run.

C:\vagrant\ansible-study>vagrant reload node3
==> node3: Attempting graceful shutdown of VM...
==> node3: Checking if box 'centos/7' version '1905.1' is up to date...
==> node3: Clearing any previously set forwarded ports...
==> node3: Fixed port collision for 22 => 2222. Now on port 2202.
==> node3: Clearing any previously set network interfaces...
==> node3: Preparing network interfaces based on configuration...
    node3: Adapter 1: nat
    node3: Adapter 2: bridged
==> node3: Forwarding ports...
    node3: 22 (guest) => 2202 (host) (adapter 1)
==> node3: Running 'pre-boot' VM customizations...
==> node3: Booting VM...
==> node3: Waiting for machine to boot. This may take a few minutes...
    node3: SSH address: 127.0.0.1:2202
    node3: SSH username: vagrant
    node3: SSH auth method: private key
==> node3: Machine booted and ready!
[node3] GuestAdditions 6.1.6 running --- OK.
==> node3: Checking for guest additions in VM...
==> node3: Setting hostname...
==> node3: Configuring and enabling network interfaces...
==> node3: Rsyncing folder: /cygdrive/c/vagrant/ansible-study/ => /vagrant
==> node3: Machine already provisioned. Run `vagrant provision` or use the `--provision`
==> node3: flag to force provisioning. Provisioners marked to run always will still run.

C:\vagrant\ansible-study>

同じ手順で動作確認します。

../_images/2020-04-20_21h44_35.png ../_images/2020-04-20_21h44_43.png
[vagrant@ansible ansible-files]$ ssh 192.168.1.162 -l vagrant -i ~/.ssh/node2_key
Last login: Mon Apr 20 21:35:08 2020 from 192.168.1.151
[vagrant@node2 ~]$ yum list installed httpd
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.riken.jp
 * extras: ftp.riken.jp
 * updates: ftp.riken.jp
Installed Packages
httpd.x86_64                                                            2.4.6-90.el7.centos                                                             @base
[vagrant@node2 ~]$ systemctl status httpd.service
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2020-04-20 21:39:54 JST; 8min ago
     Docs: man:httpd(8)
           man:apachectl(8)
 Main PID: 834 (httpd)
   Status: "Total requests: 1; Current requests/sec: 0; Current traffic:   0 B/sec"
   CGroup: /system.slice/httpd.service
           ├─ 834 /usr/sbin/httpd -DFOREGROUND
           ├─ 856 /usr/sbin/httpd -DFOREGROUND
           ├─ 857 /usr/sbin/httpd -DFOREGROUND
           ├─ 858 /usr/sbin/httpd -DFOREGROUND
           ├─ 859 /usr/sbin/httpd -DFOREGROUND
           ├─ 860 /usr/sbin/httpd -DFOREGROUND
           └─2600 /usr/sbin/httpd -DFOREGROUND
[vagrant@node2 ~]$ logout
Connection to 192.168.1.162 closed.
[vagrant@ansible ansible-files]$
[vagrant@ansible ansible-files]$ ssh 192.168.1.163 -l vagrant -i ~/.ssh/node3_key
Last login: Mon Apr 20 21:36:53 2020 from 192.168.1.151
[vagrant@node3 ~]$ yum list installed httpd
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp-srv2.kddilabs.jp
 * extras: ftp-srv2.kddilabs.jp
 * updates: ftp-srv2.kddilabs.jp
Installed Packages
httpd.x86_64                                                            2.4.6-90.el7.centos                                                             @base
[vagrant@node3 ~]$ systemctl status httpd.service
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2020-04-20 21:40:54 JST; 7min ago
     Docs: man:httpd(8)
           man:apachectl(8)
 Main PID: 833 (httpd)
   Status: "Total requests: 1; Current requests/sec: 0; Current traffic:   0 B/sec"
   CGroup: /system.slice/httpd.service
           ├─ 833 /usr/sbin/httpd -DFOREGROUND
           ├─ 857 /usr/sbin/httpd -DFOREGROUND
           ├─ 858 /usr/sbin/httpd -DFOREGROUND
           ├─ 859 /usr/sbin/httpd -DFOREGROUND
           ├─ 861 /usr/sbin/httpd -DFOREGROUND
           ├─ 862 /usr/sbin/httpd -DFOREGROUND
           └─2603 /usr/sbin/httpd -DFOREGROUND
[vagrant@node3 ~]$ logout
Connection to 192.168.1.163 closed.
[vagrant@ansible ansible-files]$

再起動後もサービスが正常に起動していることを確認できました。


プレイブックの演習

  1. すべての管理対象ホストに対してプレイが実行できるよう変更してください。

ヒント

targets セクションを変更します。

  1. 変更したプレイを実行し、ブラウザで動作を確認してください。

解答

変更後のプレイの内容です。

---
- name: Apache server installed
  hosts: all
  become: yes

  tasks:
  - name: latest Apache version installed
    yum:
      name: httpd
      state: latest
  - name: Apache enabled and running
    systemd:
      name: httpd.service
      state: started
      enabled: yes
  - name: copy index.html
    template:
      src: ~/ansible-files/index.j2
      dest: /var/www/html/index.html