はじめに
ロールは、動作する自動化の単位をまとめ、利用側が実装を複製せずにデータを指定できるようにします。公開デフォルト値を持つロールを作成し、ホスト別ページを生成して、設定の検証と再読み込み動作をロール内に保持し、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 つのインベントリグループが同じ実装を再利用して、異なる実サービスを生成しました。候補検証、変更に応じた再読み込み、変更のない繰り返し実行も、再利用可能な単位の一部として維持されました。


