再利用可能な自動化をロールにまとめる

AnsibleBeginner
オンラインで実践に進む

はじめに

ロールは、動作する自動化の単位をまとめ、利用側が実装を複製せずにデータを指定できるようにします。公開デフォルト値を持つロールを作成し、ホスト別ページを生成して、設定の検証と再読み込み動作をロール内に保持し、2 つのインベントリグループで再利用します。実際の管理対象ファイルと HTTP 応答で、ロールが実際に呼び出されることを検証します。

デフォルト値を持つロールを作成して呼び出す

このステップでは、Web サイトの自動化をロールに移し、再利用可能なデフォルト入力を使う短い Playbook で呼び出します。

ロールは、標準ディレクトリの下に、関連するタスク、デフォルト変数、テンプレート、ハンドラーをまとめます。tasks/main.yml がタスクのエントリーポイントで、defaults/main.yml は利用側が上書きできる低優先度の値を提供します。テンプレートソースは templates に置き、後で handlers/main.yml に変更に応じたサービス操作を記述します。

準備済みインベントリは、sites 親グループの下で web1 を canary、web2 を stable に配置しています。nginx は前提としてインストール済みです。グループを調べます。

cd /home/labex/project
ansible-inventory --graph

mkdir -p でロールのディレクトリを作成します。複数のパス引数により、指定した各ディレクトリが作成されます。

mkdir -p roles/managed_site/tasks roles/managed_site/defaults roles/managed_site/templates roles/managed_site/handlers

目的を明確にするため、ロールの公開変数には site_ 接頭辞を付けます。利用側が共通で使えるデフォルト値から始めます。

cat > roles/managed_site/defaults/main.yml <<'YAML'
site_environment: training
site_port: 8080
site_maintenance: false
YAML

ページテンプレートは、ロール入力と、各対象の名前および収集したディストリビューションを使います。

cat > roles/managed_site/templates/page.txt.j2 <<'JINJA'
host={{ inventory_hostname }}
environment={{ site_environment }}
distribution={{ ansible_facts.distribution }}
JINJA

ロールのタスクエントリーポイントを作成します。ロール内の src: page.txt.j2 は、そのロールの templates ディレクトリ以下で解決されます。コピー先は、引き続き管理対象の絶対パスです。

cat > roles/managed_site/tasks/main.yml <<'YAML'
- name: Prepare the role-managed website directory
  ansible.builtin.file:
    path: /var/www/role-site
    state: directory
    owner: root
    group: root
    mode: "0755"

- name: Render the role-managed page
  ansible.builtin.template:
    src: page.txt.j2
    dest: /var/www/role-site/index.html
    owner: root
    group: root
    mode: "0644"
YAML

roles キーワードでロールを呼び出します。外側の Play が対象を選択し、ファクトを収集して become を要求し、ロールは再利用可能なタスクを提供します。

cat > site.yml <<'YAML'
- name: Apply the managed site role with defaults
  hosts: sites
  gather_facts: true
  become: true
  roles:
    - managed_site
YAML

利用側 Playbook を通じて、ロールを検証して実行します。

ansible-playbook site.yml --syntax-check
ansible-playbook site.yml

ロールが作成した実際のページを調べます。

ansible sites -m ansible.builtin.command -a 'cat /var/www/role-site/index.html'

両方に、デフォルト値の environment=training と、自身のホスト名、distribution=Ubuntu が表示されるはずです。ロールのディレクトリを作るだけでは、ロールは実行されず、これらの管理対象ファイルも作成されません。

再利用可能なロール内にテンプレートとハンドラーを保持する

このステップでは、候補検証と独自の再読み込みハンドラーも含め、ロールで Web サイトを設定・稼働させます。

完全な nginx テンプレートを、ページソースの隣に置きます。ロールの site_ 入力、以前に練習した upper フィルター、ブール分岐を使います。

cat > roles/managed_site/templates/nginx.conf.j2 <<'JINJA'
events {}
http {
    server_tokens off;
    server {
        listen {{ site_port }};
        root /var/www/role-site;
        index index.html;
        add_header X-Environment "{{ site_environment | upper }}" always;
{% if site_maintenance %}
        add_header X-Maintenance "enabled" always;
{% else %}
        add_header X-Maintenance "disabled" always;
{% endif %}
    }
}
JINJA

生成された設定を置き換え前に検証し、nginx を明示的に started に保つロールタスクを追記します。変更された設定は、ロールの名前付きハンドラーに通知します。

cat >> roles/managed_site/tasks/main.yml <<'YAML'

- name: Render and validate the role-managed nginx configuration
  ansible.builtin.template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: "0644"
    validate: /usr/sbin/nginx -t -c %s
  notify: Reload managed site

- name: Keep the role-managed service running
  ansible.builtin.service:
    name: nginx
    state: started
YAML

各利用側 Playbook に複製せず、ロールのハンドラーエントリーポイントにハンドラーを記述します。

cat > roles/managed_site/handlers/main.yml <<'YAML'
- name: Reload managed site
  ansible.builtin.service:
    name: nginx
    state: reloaded
YAML

利用側 Playbook は変えずに実行します。ロールが配置の完全な動作を提供するようになりました。

ansible-playbook site.yml

両ホストが、デフォルトのポート 8080 で自身のサイトを起動するはずです。各対象を、それぞれのループバック接続先で調べます。

ansible sites -m ansible.builtin.command -a 'curl --fail --silent --show-error -i http://127.0.0.1:8080/'

各本文は自身のホストと environment=training を識別するはずです。ヘッダーには X-Environment: TRAINING と X-Maintenance: disabled が含まれるはずです。出力は、コントローラーだけの実演ではなく、ロールで設定した稼働サービスから得られます。

グループ変数の上書きで同じロールを再利用する

このステップでは、再利用可能なデフォルトやタスクファイルを編集せずに、同じロールを 2 つのグループのコンテキストに適用します。

ロールのデフォルトは、意図的に低い優先度にしてあります。インベントリのグループ変数は、同じ実装を維持しながら、これらの公開入力を上書きできます。defaults/main.yml は変更せず、各グループの利用側データを作成してください。

cat > group_vars/canary.yml <<'YAML'
site_environment: development
site_port: 8081
site_maintenance: true
YAML
cat > group_vars/stable.yml <<'YAML'
site_environment: production
site_port: 8082
site_maintenance: false
YAML

利用側 Playbook を、同じ managed_site ロールを呼び出す 2 つの Play に置き換えます。各グループは、自身について解決された入力を受け取ります。環境ごとにロールディレクトリを複製しないでください。

cat > site.yml <<'YAML'
- name: Apply the shared role to canary
  hosts: canary
  gather_facts: true
  become: true
  roles:
    - managed_site

- name: Apply the shared role to stable
  hosts: stable
  gather_facts: true
  become: true
  roles:
    - managed_site
YAML

両コンテキストを検証し、適用します。

ansible-playbook site.yml --syntax-check
ansible-playbook site.yml

両環境は、ロール内のハンドラーで変更済み設定を読み込むはずです。新しく設定したポートで、実際の接続先を調べます。

ansible canary -m ansible.builtin.command -a 'curl --fail --silent --show-error -i http://127.0.0.1:8081/'
ansible stable -m ansible.builtin.command -a 'curl --fail --silent --show-error -i http://127.0.0.1:8082/'

Canary は web1 と development を識別し、DEVELOPMENT/enabled ヘッダーを持つはずです。Stable は web2 と production を識別し、PRODUCTION/disabled ヘッダーを持つはずです。これらの違いはグループ入力から生じ、1 つの共通ロールが、引き続きデフォルト、タスク、テンプレート、ハンドラーを保持します。

同じ利用側 Playbook を繰り返します。

ansible-playbook site.yml

recap の両行が changed=0、unreachable=0、failed=0 を報告し、ハンドラーは実行予定に入らないはずです。再利用可能なロールは、呼び出され、正しく収束した管理対象状態を生成する必要があります。ディレクトリのひな形だけでは配置にはなりません。

まとめ

デフォルト、タスク、テンプレート、ハンドラーを、実際に呼び出した 1 つのロールに整理しました。低優先度のデフォルトは利用側の上書きを可能にし、2 つのインベントリグループが同じ実装を再利用して、異なる実サービスを生成しました。候補検証、変更に応じた再読み込み、変更のない繰り返し実行も、再利用可能な単位の一部として維持されました。