2015-09-25 4 views
9

На странице примеров передовых практик: 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 с общим.

ответ

1

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

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

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 

Как вы можете видеть на примере выше, Playbook будет пропускать все задачи, если он уже бежал.

3

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

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

See an example in the Ansible documentation.

+1

Мне нравится этот подход, и, кажется, делает больше смысла для меня. Однако, когда я на самом деле пытаюсь реализовать это, он не работает. Моя общая роль все еще выполняется несколько раз. Я явно попытался установить allow_duplicates: no без эффекта. Похоже, есть другие люди с этой же проблемой? https://github.com/ansible/ansible/issues/5971 – user1087973

0

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

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

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

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

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

Пример

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"' 
3

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

Например:

role_common

role1: хозяин 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

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

 Смежные вопросы

  • Нет связанных вопросов^_^