ロール

【トピックス】

ロールとは

ここまでの例はプレイを 1 つのプレイブックファイルに書いてきました。この方法ではプレイの内容が長くなり、どこに何が書いてあるのかを探すのが難しくなります。このような状態ではメンテナンスもしづらく、ミスも発生しやすくなります。

この問題の解決策です。

  • タスクを機能単位のグループにまとめてプレイブックファイルと別のファイルに保存します。
  • タスクを機能単位のグループにまとめたものをロールと呼びます。
  • プレイから必要なロールを呼び出し実行します。

ロールは特定の機能だけを持つようにします。複数の機能を持たせると、長いプレイと同じ問題が発生します。特定の機能だけを持つロールは、他のプレイからも部品として呼び出す = 再利用できます。再利用の頻度が高いほど、部品としての精度向上が期待できます。

ちなみに

「ロール」はロールプレイ(役を演じる)のロールと同じ意味です。


ディレクトリ構造

ロールはroles/ディレクトリ内に配置します。以下はAnsible の Best Practices で提示されているディレクトリレイアウトです。網掛けがロールに関する部分です。

production                # inventory file for production servers
staging                   # inventory file for staging environment

group_vars/
   group1.yml             # here we assign variables to particular groups
   group2.yml
host_vars/
   hostname1.yml          # here we assign variables to particular systems
   hostname2.yml

library/                  # if any custom modules, put them here (optional)
module_utils/             # if any custom module_utils to support modules, put them here (optional)
filter_plugins/           # if any custom filter plugins, put them here (optional)

site.yml                  # master playbook
webservers.yml            # playbook for webserver tier
dbservers.yml             # playbook for dbserver tier

roles/
    common/               # this hierarchy represents a "role"
        tasks/            #
            main.yml      #  <-- tasks file can include smaller files if warranted
        handlers/         #
            main.yml      #  <-- handlers file
        templates/        #  <-- files for use with the template resource
            ntp.conf.j2   #  <------- templates end in .j2
        files/            #
            bar.txt       #  <-- files for use with the copy resource
            foo.sh        #  <-- script files for use with the script resource
        vars/             #
            main.yml      #  <-- variables associated with this role
        defaults/         #
            main.yml      #  <-- default lower priority variables for this role
        meta/             #
            main.yml      #  <-- role dependencies
        library/          # roles can also include custom modules
        module_utils/     # roles can also include custom module_utils
        lookup_plugins/   # or other types of plugins, like lookup in this case

    webtier/              # same kind of structure as "common" was above, done for the webtier role
    monitoring/           # ""
    fooapp/               # ""

roles/ディレクトリ直下のディレクトリの名前がそのままロールの名前(ロール名)になります。commonwebtiremonitoringfooappがロール名です。

ロール内のディレクトリ構成やファイル名などは基本的に共通です。

tasks/            #
    main.yml      #  <-- tasks file can include smaller files if warranted
handlers/         #
    main.yml      #  <-- handlers file
templates/        #  <-- files for use with the template resource
    ntp.conf.j2   #  <------- templates end in .j2
files/            #
    bar.txt       #  <-- files for use with the copy resource
    foo.sh        #  <-- script files for use with the script resource
vars/             #
    main.yml      #  <-- variables associated with this role
defaults/         #
    main.yml      #  <-- default lower priority variables for this role
meta/             #
    main.yml      #  <-- role dependencies
library/          # roles can also include custom modules
module_utils/     # roles can also include custom module_utils
lookup_plugins/   # or other types of plugins, like lookup in this case

この中でtasks/ディレクトリおよびその中のmain.ymlだけが必須です。他のディレクトリやファイルは必要に応じて作成・配置します。主なディレクトリの内容です。

tasks
ロールで実行するタスクをmain.ymlファイルに記述する。
handlers
tasks/ディレクトリのmain.yml内のタスクのnotifyディレクティブで呼び出されるhandlersセクション内のタスクをmain.ymlファイルに記述する。
templates
templateモジュールで使用する jinja2 形式のテンプレートファイルを配置する。
files
copyモジュールなどで使用するファイルを配置する。
vars
ロール内で使用する変数をmain.ymlファイルに記述する。

注釈

ロール内のtemplates/ディレクトリやfiles/ディレクトリ内のファイルを指定するときパスの指定は不要です。直接ファイル名を指定します。


ロールの作成

web グループの管理対象ホスト用に次のプレイを作成します。

  1. Apache の最新版をインストールする。すでに Apache がインストール済みのときは最新版に更新する。
  2. ファイアウォールの http ポートを開放する。
  3. Apache の最新版をインストールまたは更新したときは Apache のサービスを再起動する。
  4. バーチャルホスト用の設定ファイルをコピーする。
  5. バーチャルホストのコンテンツ用のディレクトリ/var/www/vhost_htmlを作成する。
  6. 元ドメイン用のindex.htmlファイルをコピーする。
  7. バーチャルホスト用のindex.htmlファイルをコピーする。

インベントリファイル

インベントリファイル hosts.yml の内容です。

---
all:
  vars:
    ansible_user: vagrant
  hosts:
    node1:
      ansible_host: 192.168.1.161
      ansible_ssh_private_key_file: ~/.ssh/node1_key
  children:
    web:
      hosts:
        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

必要なディレクトリの作成

要件にあわせて必要なディレクトリを作成します。

  • ロール名:apache
  • ロール apache 内に必要なディレクトリ:taskshandlerstemplates
[vagrant@ansible ansible-files]$ mkdir roles/
[vagrant@ansible ansible-files]$ cd roles/
[vagrant@ansible roles]$ mkdir apache/
[vagrant@ansible roles]$ cd apache/
[vagrant@ansible apache]$ mkdir tasks/
[vagrant@ansible apache]$ mkdir handlers/
[vagrant@ansible apache]$ mkdir templates/
[vagrant@ansible apache]$

ディレクトリ作成後の状態です。

[vagrant@ansible ansible-files]$ tree
.
├── hosts.yml
└── roles
    └── apache
        ├── handlers
        ├── tasks
        └── templates

5 directories, 1 file
[vagrant@ansible ansible-files]$

テンプレートファイルの作成

templatesディレクトリ内に管理対象ホストにコピーするテンプレートファイル( index.html )を作成します。

用途 ファイル名
親ドメイン default-index.j2
バーチャルドメイン virtual-index.j2

ファイル作成後の状態です。

[vagrant@ansible ansible-files]$ tree
.
├── hosts.yml
└── roles
    └── apache
        ├── handlers
        ├── tasks
        └── templates
            ├── default-index.j2
            └── virtual-index.j2

5 directories, 3 files
[vagrant@ansible ansible-files]$

roles/apache/templates/default-index.j2

<html>
<body>
This is the page for the parent domain {{ ansible_facts['hostname'] }}.<br>
</body>
</html>

roles/apache/templates/virtual-index.j2

<html>
<body>
Virtual Domain : {{ ansible_facts['hostname'] }}<br>
</body>
</html>

バーチャルホスト用設定ファイルの作成

templatesディレクトリ内にバーチャルホスト用の設定ファイルを作成します。

ファイル作成後の状態です。

[vagrant@ansible ansible-files]$ tree
.
├── hosts.yml
└── roles
    └── apache
        ├── handlers
        ├── tasks
        └── templates
            ├── default-index.j2
            ├── vhost.j2
            └── virtual-index.j2

5 directories, 4 files
[vagrant@ansible ansible-files]$

roles/apache/templates/vhost.j2

<VirtualHost *:80>
  DocumentRoot /var/www/html
  ServerName {{ ansible_facts['hostname'] }}
</VirtualHost>

<VirtualHost *:80>
  DocumentRoot /var/www/vhost_html
  ServerName virtual-{{ ansible_facts['hostname'] }}
</VirtualHost>

タスクの作成

まず、メインとなるプレイブックファイル apache.yml を作成します。import_roleモジュールを使用してロールを呼び出します。

---
- name: Deploy web server
  hosts: web
  become: yes

  tasks:
  - name: Display start message
    debug:
      msg: "Beginning web server configuration."
  - name: Deploy Apache Server
    import_role:
      name: apache
  - name: Display end message
    debug:
      msg: "Web server has been configured."

次にロール apache のタスクをroles/apache/tasks/main.ymlファイルに記述します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
---
- name: Install/Update Apache
  yum:
    name: httpd
    state: latest
  notify: restart httpd service
- name: Open http port
  firewalld:
    service: http
    permanent: yes
    state: enabled
- name: Copy virtual host configuration
  template:
    src: vhost.j2
    dest: /etc/httpd/conf.d/vhost.conf
    owner: root
    group: root
    mode: 0644
  notify: restart httpd service
- name: Create a directory for the contents of the virtual host
  file:
    path: /var/www/vhost_html/
    state: directory
- name: Copy the index.html file for the original domain.
  template:
    src: default-index.j2
    dest: /var/www/html/index.html
- name: Copy the index.html file for the virtual host.
  template:
    src: virtual-index.j2
    dest: /var/www/vhost_html/index.html
  • 2 ~ 6 行目 → Apache の最新版をインストールする。すでに Apache がインストール済みのときは最新版に更新する。
  • 7 ~ 11 行目 → ファイアウォールの http ポートを開放する。
  • 12 ~ 19 行目 → バーチャルホスト用の設定ファイルをコピーする。
  • 20 ~ 23 行目 → バーチャルホストのコンテンツ用のディレクトリ/var/www/vhost_htmlを作成する。
  • 24 ~ 27 行目 → 元ドメイン用のindex.htmlファイルをコピーする。
  • 28 ~ 31 行目 → バーチャルホスト用のindex.htmlファイルをコピーする。

最後にroles/apache/handlers/main.ymlファイルに上記のタスクから呼び出される handlers を記述します。

---
- name: Apache service restart
  systemd:
    name: httpd.service
    state: restarted
    enabled: yes
  listen: restart httpd service
  • roles/apache/handlers/main.yml→ Apache の最新版をインストールまたは更新したときは Apache のサービスを再起動する。

各ファイルの作成後の状態です。

[vagrant@ansible ansible-files]$ tree
.
├── apache.yml
├── hosts.yml
└── roles
    └── apache
        ├── handlers
        │   └── main.yml
        ├── tasks
        │   └── main.yml
        └── templates
            ├── default-index.j2
            ├── vhost.j2
            └── virtual-index.j2

5 directories, 7 files
[vagrant@ansible ansible-files]$

実行ログです。

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

PLAY [Deploy web server] ************************************************************************************************************************************

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

TASK [Display start message] ********************************************************************************************************************************
ok: [node3] => {
    "msg": "Beginning web server configuration."
}
ok: [node2] => {
    "msg": "Beginning web server configuration."
}

TASK [apache : Install/Update Apache] ***********************************************************************************************************************
changed: [node3]
changed: [node2]

TASK [apache : Open http port] ******************************************************************************************************************************
changed: [node3]
changed: [node2]

TASK [apache : Copy virtual host configuration] *************************************************************************************************************
changed: [node2]
changed: [node3]

TASK [apache : Create a directory for the contents of the virtual host] *************************************************************************************
changed: [node2]
changed: [node3]

TASK [apache : Copy the index.html file for the original domain.] *******************************************************************************************
changed: [node3]
changed: [node2]

TASK [apache : Copy the index.html file for the virtual host.] **********************************************************************************************
changed: [node3]
changed: [node2]

TASK [Display end message] **********************************************************************************************************************************
ok: [node3] => {
    "msg": "Web server has been configured."
}
ok: [node2] => {
    "msg": "Web server has been configured."
}

RUNNING HANDLER [apache : Apache service restart] ***********************************************************************************************************
changed: [node2]
changed: [node3]

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

[vagrant@ansible ansible-files]$

べき等性が保たれているか確認するため、もう一度実行したときのログです。すべて ok になっており、べき等性が保たれています。

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

PLAY [Deploy web server] ************************************************************************************************************************************

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

TASK [Display start message] ********************************************************************************************************************************
ok: [node3] => {
    "msg": "Beginning web server configuration."
}
ok: [node2] => {
    "msg": "Beginning web server configuration."
}

TASK [apache : Install/Update Apache] ***********************************************************************************************************************
ok: [node3]
ok: [node2]

TASK [apache : Open http port] ******************************************************************************************************************************
ok: [node2]
ok: [node3]

TASK [apache : Copy virtual host configuration] *************************************************************************************************************
ok: [node3]
ok: [node2]

TASK [apache : Create a directory for the contents of the virtual host] *************************************************************************************
ok: [node3]
ok: [node2]

TASK [apache : Copy the index.html file for the original domain.] *******************************************************************************************
ok: [node3]
ok: [node2]

TASK [apache : Copy the index.html file for the virtual host.] **********************************************************************************************
ok: [node3]
ok: [node2]

TASK [Display end message] **********************************************************************************************************************************
ok: [node3] => {
    "msg": "Web server has been configured."
}
ok: [node2] => {
    "msg": "Web server has been configured."
}

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

[vagrant@ansible ansible-files]$

実行確認

名前解決のため C:\Windows\System32\drivers\etc\hosts ファイルに次の内容を追記します。

192.168.1.162       node2
192.168.1.162       virtual-node2
192.168.1.163       node3
192.168.1.163       virtual-node3

親ドメインのページ表示

../_images/role1.png ../_images/role3.png

バーチャルホストのページ表示

../_images/role2.png ../_images/role4.png

注釈

実行確認後は C:\Windows\System32\drivers\etc\hosts ファイルに追記した 4 行は削除してください。