web-dev-qa-db-ja.com

Ansibleのベストプラクティスは共通の役割を繰り返さない

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サーバーを個別にプロビジョニングすることはできません。

13
user1087973

ロールディレクトリのmetaファイルを使用してロールの依存関係を決定します。ロールの依存関係により、ロールを使用するときに他のロールを自動的に取り込むことができます。ロールの依存関係は、ロールディレクトリに含まれるmeta /main.ymlファイルに保存されます。

ロールの依存関係は、常にそれらを含むロールの前に実行され、再帰的です。デフォルトでは、ロールは依存関係として1回だけ追加できます。別のロールも依存関係としてリストしている場合、再度実行されることはありません。この動作は、allow_duplicates:yesをmeta /main.ymlファイルに追加することでオーバーライドできます。

Ansibleドキュメントの例を参照してください。

7
Brian Knight

@ user1087973タグを使用していますか?タグを使用している場合、異なるタグを持つ共通の役割は異なると見なされます。

例えば ​​:

role_common

role1:ホストSRVtag_role_1はrole_commonに依存します

ロール2:ホストSRVtag_role_2はrole_commonに依存します

タグが原因で異なると見なされるため、共通の役割は2回実行されます

--list-tasksを見てみると、

タグを使用する代わりの適切な解決策は、異なるymlファイルを使用して、それをsite.ymlに含めることです。

http://docs.ansible.com/ansible/playbooks_best_practices.html#top-level-playbooks-are-separated-by-role

これが役立つことを願っています

3
Eldinea

他の人と同じように、私はこの問題を抱えていました。役割がべき等であっても、実行に時間がかかるため、一度だけ実行したい場合があります。

@ 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.ymlansible-playbook site.yml -l commonansible-playbook site.yml -l dbansible-playbook db.yml、...)
  • コモンの実行を繰り返すかどうかを決めることができます

{ role: common, when: isdef_common_role is not defined }を繰り返したくない場合は、以下を使用して条件を共通の役割に入れることができます。

site.yml:変更なし

db.ymlweb.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"'
3
bufh

私のアプローチは、プレイブックにプレイブックを含めないことです。少なくともそうする場合は、1つのジョブでロールが複数回実行されることになります。

複数のプレイブックに含める必要があるものはすべてロールに変換され、そのロールは多くのプレイブックに含めることができます。一連の役割が重複して含まれているプレイブックが複数ある場合は、それらの役割を1つの役割に結合して、他の役割にのみ依存するようにして、その重複を回避できます。

2
Peter Lyons

私のアプローチは、役割ごとにサーバー上に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

上記の例でわかるように、プレイブックがすでに実行されている場合、プレイブックはすべてのタスクをスキップします。

1
Vor

Ansibleに記載されているように ドキュメント

Ansibleは、ロールで定義されたパラメーターが定義ごとに異ならない場合、複数回定義されている場合でも、ロールの実行を1回だけ許可します。

(...)

ロールを複数回実行するには、次の2つのオプションがあります。
1。各ロール定義で異なるパラメーターを渡します。
2。ロールのmeta/main.ymlファイルにallow_duplicates:trueを追加します。

動的vs.静的 コンテンツの再利用の明確な側面も考慮してください: 包含およびインポート

プレイブックはインベントリアイテムベースで実行され、そのすべての役割スキーマとコードの再利用は、そのインフラストラクチャをコードとして整理し、保守を容易にすることを目的としていることに注意してください。また、実行ごとに、タスクは同じホストで有効になり、べき等の結果を生成することになっています。

とはいえ、最初は同じグループのタスク(つまりロール)を2回実行することは意味がありません。その後の実行では、(べき等性のために)実際的な効果はありません。

例外は、ロールの呼び出しに異なるパラメーター(変数、タグなど)がある場合です。したがって、実行の実際の違いは、べき等性に影響を与え、多少異なる結果につながる可能性があります。そのような場合、同じグループのタスクを複数回実行することは理にかなっています。それが起こります。

経験則として、特に静的コンテンツに関しては、実行されるすべてのコードは、単一の自己完結型のプレイブックのようであり(2つ以上の「子」プレイブックで構成される「サイト」プレイブックでも)、それでもスコープはグローバルです。

0
Alan Rezende

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.
0
Trondh