Ansibleのベストプラクティスページ: http://docs.ansible.com/ansible/playbooks_best_practices.html#top-level-playbooks-are-separated-by-role マスターがプレイブックsite.ymlには、他のトップレベルのプレイブックwebservers.ymlとdbservers.ymlがいくつか含まれています。それらのプレイブックには、それぞれ共通の役割が含まれています。すべてのグループを1つのホストで実行している一部のインベントリファイル。グループごとにホストがある別のインベントリファイル。グループが1つのホスト上にある場合、site.ymlを実行すると、共通の役割が2回実行されていることがわかります。1つはwebservers.yml用、もう1つはdbservers.yml用です。
これを回避するための解決策は何ですか? webservers.ymlとdbservers.ymlから共通の役割を取得でき、代わりにsite.yml内に、共通の役割を持つ両方を対象とするタスクがあると思います。しかし、共通のWebサーバーまたはDBサーバーを個別にプロビジョニングすることはできません。
ロールディレクトリのmeta
ファイルを使用してロールの依存関係を決定します。ロールの依存関係により、ロールを使用するときに他のロールを自動的に取り込むことができます。ロールの依存関係は、ロールディレクトリに含まれるmeta /main.ymlファイルに保存されます。
ロールの依存関係は、常にそれらを含むロールの前に実行され、再帰的です。デフォルトでは、ロールは依存関係として1回だけ追加できます。別のロールも依存関係としてリストしている場合、再度実行されることはありません。この動作は、allow_duplicates:yesをmeta /main.ymlファイルに追加することでオーバーライドできます。
@ user1087973タグを使用していますか?タグを使用している場合、異なるタグを持つ共通の役割は異なると見なされます。
例えば :
role_common
role1:ホストSRVtag_role_1はrole_commonに依存します
ロール2:ホストSRVtag_role_2はrole_commonに依存します
タグが原因で異なると見なされるため、共通の役割は2回実行されます
--list-tasks
を見てみると、
タグを使用する代わりの適切な解決策は、異なるymlファイルを使用して、それをsite.ymlに含めることです。
これが役立つことを願っています
他の人と同じように、私はこの問題を抱えていました。役割がべき等であっても、実行に時間がかかるため、一度だけ実行したい場合があります。
@ Vor と同様のアプローチを使用しましたが、ファイルを作成する代わりに facts を選択します。
リマインダー:
ファクトは、Ansibleの実行中にプレイ間で存続しますが、ファクトキャッシュを使用しても、実行間で保存されません。
site.yml
---
- hosts: all
roles: [common]
- include: db.yml
- include: web.yml
db.yml
---
- hosts: db
roles:
- { role: common, when: isdef_common_role is not defined }
- db
web.yml
---
- hosts: web
roles:
- { role: common, when: isdef_common_role is not defined }
- web
roles/common/tasks/main.yml
---
- debug: 'msg="{{ inventory_hostname }} common"'
- set_fact: isdef_common_role=1
これは確かに少し冗長ですが(毎回条件付きインクルードを作成する必要があるため)、次の利点があります。
ansible-playbook site.yml
、ansible-playbook site.yml -l common
、ansible-playbook site.yml -l db
、ansible-playbook db.yml
、...){ role: common, when: isdef_common_role is not defined }
を繰り返したくない場合は、以下を使用して条件を共通の役割に入れることができます。
site.yml
:変更なし
db.yml
、web.yml
:削除役割から条件付き
roles/common/tasks/main.yml
---
- include: tasks.yml
when: isdef_common_role is not defined
- set_fact: isdef_common_role=1
roles/common/tasks/tasks.yml
---
- debug: 'msg="{{ inventory_hostname }} common"'
私のアプローチは、プレイブックにプレイブックを含めないことです。少なくともそうする場合は、1つのジョブでロールが複数回実行されることになります。
複数のプレイブックに含める必要があるものはすべてロールに変換され、そのロールは多くのプレイブックに含めることができます。一連の役割が重複して含まれているプレイブックが複数ある場合は、それらの役割を1つの役割に結合して、他の役割にのみ依存するようにして、その重複を回避できます。
私のアプローチは、役割ごとにサーバー上にlock
ファイルを作成することです。これは非常にうまく機能します。
たとえば、私にはcommon
という役割があり、それが私のtasks/main.yml
は次のようになります:
- name: check lock file exist
stat: path=/tmp/ansible-common-role
ignore_errors: true
register: lock_file
- name: install apt packages
apt: name={{ item }} state=present
with_items:
- python-setuptools
when: lock_file.stat.exists == false
.....
# other tasks with
# when: lock_file.stat.exists == false
.....
- name: Create lock file
file: path=/tmp/ansible-common-role state=touch
when: lock_file.stat.exists == false
上記の例でわかるように、プレイブックがすでに実行されている場合、プレイブックはすべてのタスクをスキップします。
Ansibleに記載されているように ドキュメント :
Ansibleは、ロールで定義されたパラメーターが定義ごとに異ならない場合、複数回定義されている場合でも、ロールの実行を1回だけ許可します。
(...)
ロールを複数回実行するには、次の2つのオプションがあります。
1。各ロール定義で異なるパラメーターを渡します。
2。ロールのmeta/main.ymlファイルにallow_duplicates:trueを追加します。
動的vs.静的 コンテンツの再利用の明確な側面も考慮してください: 包含およびインポート
プレイブックはインベントリアイテムベースで実行され、そのすべての役割スキーマとコードの再利用は、そのインフラストラクチャをコードとして整理し、保守を容易にすることを目的としていることに注意してください。また、実行ごとに、タスクは同じホストで有効になり、べき等の結果を生成することになっています。
とはいえ、最初は同じグループのタスク(つまりロール)を2回実行することは意味がありません。その後の実行では、(べき等性のために)実際的な効果はありません。
例外は、ロールの呼び出しに異なるパラメーター(変数、タグなど)がある場合です。したがって、実行の実際の違いは、べき等性に影響を与え、多少異なる結果につながる可能性があります。そのような場合、同じグループのタスクを複数回実行することは理にかなっています。それが起こります。
経験則として、特に静的コンテンツに関しては、実行されるすべてのコードは、単一の自己完結型のプレイブックのようであり(2つ以上の「子」プレイブックで構成される「サイト」プレイブックでも)、それでもスコープはグローバルです。
Add_Hostを使用して、次のような一時グループを作成することもできます。
1. target: webservers--> add hosts to group "common_roles"
2. target: dbservers --> add hosts to gruop "common_roles"
3. Target: common_roles --> execute whatever common roles you need
4. regular group by group execution.