it-swarm.com.ru

Ansible лучшие практики не повторяют общую роль

На странице лучших практик Ansible: http://docs.ansible.com/ansible/playbooks_best_practices.html#top-level-playbooks-are-separated-by-role он показывает пример, где мастер playbook site.yml включает в себя несколько других высокоуровневых playbooks webservers.yml и dbservers.yml. В этих пьесах каждый из них включает общую роль. Некоторые файлы инвентаризации у меня все мои группы работают на одном хосте. Еще один файл инвентаризации у меня есть хост на группу. В случае, когда когда-либо группа находится на одном хосте, если я запускаю site.yml, вы можете видеть, что общую роль играют дважды: один для webservers.yml и один для dbservers.yml.

Какое решение избежать этого? Я предполагаю, что вы можете удалить общую роль из webservers.yml и dbservers.yml, и вместо этого в site.yml есть задача, которая нацелена на обе роли с общей ролью. Но тогда я не могу индивидуально обеспечить веб-сервер или dbserver общим.

10
user1087973

Я определяю ролевые зависимости с помощью файлов meta в моей директории ролей. Ролевые зависимости позволяют вам автоматически использовать другие роли при использовании роли. Зависимости ролей хранятся в файле meta/main.yml, который находится в каталоге ролей.

Зависимости ролей всегда выполняются перед включающей их ролью и являются рекурсивными. По умолчанию роли также могут быть добавлены в качестве зависимости только один раз - если другая роль также перечисляет ее как зависимость, она не будет запускаться снова. Это поведение можно изменить, добавив allow_duplicates: yes в файл meta/main.yml.

см. Пример в документации Ansible.

6
Brian Knight

@ user1087973 Вы используете теги? Если вы используете теги, общая роль с разными тегами считается разной:

Например :

role_common

роль1: хост SRV tag_role_1 зависит от role_common

роль 2: хост SRV tag_role_2 зависит от role_common

Ваша общая роль будет выполнена дважды, потому что она считается отличной из-за тегов

Посмотрите с --list-tasks, и вы увидите, что

Правильное решение вместо использования тегов - использовать разные файлы yml и включить их в ваш site.yml.

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

Надеюсь, что это может помочь

3
Eldinea

Мой подход заключается в том, чтобы не включать playbooks в playbooks. По крайней мере, в этом случае роль будет выполняться несколько раз в одном задании.

Все, что мне нужно включить в более чем одну книгу, преобразуется в роль, и эта роль может быть включена во многие книги. Если я получу несколько книг с дублирующими сериями ролей, я смогу объединить эти роли в одну роль, которая просто зависит от других ролей, чтобы избежать такого дублирования.

2
Peter Lyons

Как и у других, у меня была эта проблема, и даже если роль идемпотентна, для ее выполнения требуется время, поэтому мы можем захотеть выполнить ее только один раз.

Я использовал похожий подход, чем @ Vor , но я выбираю факты вместо создания файлов.

Напоминание:

Факты сохраняются между играми во время запуска 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"'
2
bufh

Мой подход заключается в создании файла 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

Вы также можете создать временную группу, используя 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