common roleを書き忘れないよう管理するのが辛くなってきた。role側で『自分より先にこのroleを実行してほしい』と宣言できれば、Playbookを書く人が依存を意識せずに済むのに」Ansibleを本格運用するとこういった設計課題が出てきます。その答えが
meta/main.yml の dependencies ブロックです。roleが自分の依存を宣言することで、Playbookから webapp とだけ書けば common → nginx → webapp の実行順序が自動保証されます。この記事では、ansible role in roleの実装方法として
meta/main.yml の dependencies の基本構文、呼び出し順序の制御、重複排除の仕組みを実行ログを交えて解説します。実行環境はRHEL 9.4 / Rocky Linux 9.4です。この記事のポイント
・meta/main.ymlのdependenciesで依存roleをrole側から宣言できる
・依存roleは宣言した順序で、本体roleより必ず先に実行される
・Ansibleは同一roleの重複実行をデフォルトで自動排除する
・allow_duplicates: trueで変数を変えた複数回実行が可能になる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
roleが別のroleを呼ぶ設計が必要になる場面
複数のroleを持つAnsibleプロジェクトでは、多くのroleが同じ「前提条件」を必要とします。たとえば次のような状況です。・common role: タイムゾーン設定・必須パッケージインストール・ログローテーション設定を行う
・nginx role: Nginxをインストールして設定する(前提: commonが適用済み)
・webapp role: アプリケーションをデプロイする(前提: nginxが起動中)
この依存関係をPlaybook側で管理すると次のようになります。
# Playbook側で依存を管理する方式(書き忘れリスクあり) - hosts: webservers roles: - role: common # 忘れやすい - role: nginx # 忘れやすい - role: webapp
common や nginx を追加し忘れる可能性があることです。Playbookが増えるほど漏れのリスクが高まります。meta/main.yml の dependencies を使えば、「このroleを使うなら先にこのroleを実行してほしい」という宣言をrole側に持たせられます。Playbook側は呼び出したいrole名だけ書けばよくなり、依存の書き忘れを構造的に防げます。meta/main.ymlのdependenciesの書き方
1. role名だけで依存を指定する(最小構成)
最もシンプルな書き方は、依存role名を列挙する形式です。# roles/webapp/meta/main.yml --- dependencies: - role: common - role: nginx
webapp roleを呼び出すと common → nginx → webapp の順で実行されます。Playbook側に common や nginx を列挙する必要はありません。meta/main.yml にはGalaxy公開用のメタ情報(galaxy_info)も書けますが、ローカル開発では dependencies だけで構いません。依存roleが不要な末端roleは dependencies: [] と明示的に書いておくと意図が伝わりやすくなります。2. 変数をオーバーライドして依存roleに渡す
依存roleに対して変数を渡したい場合は、role: の下に vars: ブロックを追加します。# roles/webapp/meta/main.yml --- dependencies: - role: common - role: nginx vars: nginx_port: 8080 nginx_worker_processes: 2
vars: で渡した変数はroleの defaults/main.yml の値をオーバーライドします。ただし host_vars・group_vars・Playbookのvarsセクションで設定した変数よりは優先順位が低くなります。変数の優先順位が意図と合わない場合は、group_vars 側で上書きして調整するのが実務的なアプローチです。3. whenで条件付き依存を定義する
環境によって依存roleを実行するかどうかを切り替えたい場合はwhen を使います。# roles/webapp/meta/main.yml --- dependencies: - role: common - role: selinux_config when: ansible_selinux.status == "enabled" - role: nginx
when が false と評価された依存roleはスキップされます。ただし when の評価時点で参照する変数が未定義だとエラーになるため、ansible_selinux のようにファクト収集で確実に定義される変数を使うのが安全です。dependenciesで決まるrole実行順序の仕組み
Ansibleはroleを処理する際、依存関係を再帰的に解決してから本体のroleを実行します。処理の流れは次のとおりです。1. Playbook が
webapp roleを要求する2. Ansibleが
webapp/meta/main.yml を読み込み dependencies リストを取得する3. 最初の依存
common を処理 → common/meta/main.yml を読み込む(依存なし)→ commonを実行4. 次の依存
nginx を処理 → nginx/meta/main.yml を読み込む(依存なし)→ nginxを実行5. webappを実行
dependenciesリストは上から順に処理されるため、順序に意味がある場合は先に実行すべきroleを上に書きます。
依存が深くネストしている場合(roleC → roleB → roleA のチェーン)は深さ優先(DFS)で解決されます。つまり最深部(roleA)から実行され、roleB、roleCの順になります。
# ネストした依存の解決順序の例 # roleC/meta/main.yml dependencies: - role: roleB # roleB/meta/main.yml dependencies: - role: roleA # PlaybookでroleCを指定した場合の実行順序 # 1. roleA(roleBの依存) # 2. roleB(roleCの依存) # 3. roleC(Playbookで指定)
実践例|webappがcommonとnginxを依存として呼ぶPlaybook構成
1. ディレクトリ構成
roles/ ├── common/ │ ├── tasks/ │ │ └── main.yml │ └── meta/ │ └── main.yml # dependencies: [](依存なし) ├── nginx/ │ ├── tasks/ │ │ └── main.yml │ ├── defaults/ │ │ └── main.yml # nginx_port: 80 │ ├── handlers/ │ │ └── main.yml │ └── meta/ │ └── main.yml # dependencies: [common] └── webapp/ ├── tasks/ │ └── main.yml └── meta/ └── main.yml # dependencies: [nginx]
2. 各roleのmeta/main.yml
# roles/common/meta/main.yml --- dependencies: [] # roles/nginx/meta/main.yml --- dependencies: - role: common # roles/webapp/meta/main.yml --- dependencies: - role: nginx vars: nginx_port: 80
3. Playbookの記述
Playbook側はwebapp roleだけを記述します。common や nginx を書く必要はありません。# site.yml --- - hosts: webservers become: true roles: - role: webapp
4. 実行ログで呼び出し順序を確認する
ansible-playbook -i inventory site.yml -v を実行すると、TASKラベルにrole名が含まれ実行順序が確認できます。PLAY [webservers] ************************************************************ TASK [Gathering Facts] ******************************************************* ok: [web01.example.com] TASK [common : タイムゾーンをAsia/Tokyoに設定する] ************************************ changed: [web01.example.com] TASK [common : 必須パッケージをインストールする] ************************************** changed: [web01.example.com] TASK [nginx : Nginxをインストールする] ******************************************** changed: [web01.example.com] TASK [nginx : Nginx設定ファイルを配置する] ******************************************* changed: [web01.example.com] TASK [webapp : アプリケーションをデプロイする] ****************************************** changed: [web01.example.com] PLAY RECAP ******************************************************************* web01.example.com : ok=6 changed=5 unreachable=0 failed=0
common → nginx → webapp の順に実行されていることが確認できます。Playbook側には webapp しか書いていないにもかかわらず、依存が自動的に解決されています。重複排除の仕組みとallow_duplicates
Ansibleはデフォルトで同じroleが同じホストに対して複数回実行されることを防ぐ「重複排除」を行います。たとえば
nginx roleと redis roleがどちらも common roleに依存している場合、common は最初の1回だけ実行されます。# nginx/meta/main.yml dependencies: - role: common # redis/meta/main.yml dependencies: - role: common # site.yml - hosts: app_servers roles: - role: nginx - role: redis # 実行順序: common(1回のみ)→ nginx → redis # 2回目のcommonは重複排除によりスキップされる
nginx_vhost roleを繰り返し呼びたい場合です。そのような場合は
allow_duplicates: true を設定します。# roles/nginx_vhost/meta/main.yml --- allow_duplicates: true dependencies: []
# webapp/meta/main.yml(nginx_vhostをVirtualHost数だけ呼ぶ例) --- dependencies: - role: nginx_vhost vars: vhost_name: app1 vhost_port: 80 - role: nginx_vhost vars: vhost_name: app2 vhost_port: 8080
allow_duplicates: false(デフォルト)の場合、2番目の nginx_vhost は「すでに実行済み」としてスキップされます。変数が違っていても判断基準はrole名のみであるため注意が必要です。よくある落とし穴とエラー対処法
1. 循環依存(roleAとroleBが互いに依存している)
症状: roleAがroleBに依存し、roleBがroleAに依存すると、Ansibleはエラーを出して停止します。ERROR! A circular dependency was detected for role: roleA
common)に切り出し、roleA と roleB が両方そのroleに依存する設計に変えます。重複排除が働くため common は1回だけ実行されます。2. 変数を変えても同じroleが2回目にスキップされる
症状: 同じrole名で変数を変えて複数回依存定義しても、2回目以降がスキップされる。対処: 繰り返し実行が必要なroleの
meta/main.yml に allow_duplicates: true を追加します。ただし冪等性の設計に注意し、変数が変わることで実際に異なる処理になることを確認してから設定しましょう。3. dependenciesのwhenに未定義変数を使う
症状:when 条件の評価時点で変数がまだ定義されておらず、エラーまたは意図しない評価になる。対処:
when にはファクト変数(gather_facts が収集するもの)か、インベントリや group_vars で確実に定義されている変数だけを使います。Playbookの vars や set_fact で設定した変数は依存解決の時点では使えない場合があるため要注意です。4. meta/main.ymlの場所またはYAMLインデントが誤っている
症状:meta/main.yml を作成したつもりだが、期待した依存roleが実行されない。# 正しいパス roles/webapp/meta/main.yml # YAMLの正しいインデント(スペース2つ) --- dependencies: - role: common # スペース2つでインデント vars: nginx_port: 80 # スペース6つ(2+4) # 構文チェックで事前確認 ansible-playbook --syntax-check site.yml
--syntax-check で事前に検出できます。meta/main.yml が存在しない場合はそのroleに依存は設定されていないものとして扱われます。本記事のまとめ
| やりたいこと | 設定方法 |
|---|---|
| roleが別のroleを依存として宣言する | roles/xxx/meta/main.yml の dependencies: ブロック |
| 依存roleに変数を渡す | 依存定義内の vars: nginx_port: 80 形式 |
| 同一roleを複数回実行する | meta/main.yml に allow_duplicates: true を追加 |
| 依存roleを条件付きで実行する | 依存定義内に when: ansible_xxx == "..." を追加 |
| 実行順序を確認する | ansible-playbook -v の実行ログでTASKラベルを確認 |
| 構文エラーを事前に検出する | ansible-playbook --syntax-check site.yml |
meta/main.yml の dependencies を使いこなすことで、「このroleを使うなら○○を事前に適用する」という暗黙の前提をPlaybook側ではなくrole自体に閉じ込められます。Playbookから webapp とだけ書けば common → nginx → webapp の順序が自動保証される設計は、チーム開発での書き忘れや実行順序ミスを構造的に防ぎます。重複排除の仕組みを理解した上で
allow_duplicates を適切に使い、循環依存を避ける設計を心がけることが、メンテナブルなansible role in role設計の基本です。
Ansible実践ハンズオンの詳細を見る >>
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:Ansibleのhostsファイル設計|INI形式とYAML形式の書き分け・グループ入れ子・ホスト範囲指定の実践
- この記事の属するカテゴリ:Ansibleへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます