Spec-Zone.ru › Ansible 2.4

Рекомендованные практики

Вот несколько советов по эффективному использованию Ansible и Ansible playbooks.

Вы можете найти примеры playbooks, иллюстрирующие эти лучшие практики, в нашем репозитории ansible-examples. (ПРИМЕЧАНИЕ: они могут не использовать все функции последней версии, но по-прежнему являются отличной справочной информацией!).

  • Организация контента
    • Структура каталогов
    • Альтернативная структура каталогов
    • Использование динамической инвентаризации с облаками
    • Как различать этапы разработки и производства
    • Переменные групп и хостов
    • Файлы playbooks верхнего уровня разделены по ролям
    • Организация задач и обработчиков для роли
    • Возможности такой организации (примеры)
    • Организация развертывания и конфигурации
  • Разработка и производство
  • Поэтапные обновления
  • Всегда указывайте состояние
  • Группировка по ролям
  • Различия в операционных системах и дистрибутивах
  • Включение Ansible модулей в playbook
  • Отступы и комментарии
  • Всегда называйте задачи
  • Держите просто
  • Система управления версиями
  • Переменные и хранилища

Организация контента

Следующий раздел демонстрирует один из возможных способов организации содержимого playbook.

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

Один из ключевых способов организации содержимого playbook – это функция организации «ролей» Ansible, которая документирована на странице основных playbooks. Вы должны уделить время чтению и пониманию документации по ролям, которая доступна здесь: Роли.

Структура каталогов

Верхний уровень каталога будет содержать файлы и каталоги следующим образом:

production                # inventory file for production servers
staging                   # inventory file for staging environment

group_vars/
   group1                 # here we assign variables to particular groups
   group2                 # ""
host_vars/
   hostname1              # if systems need specific variables, put them here
   hostname2              # ""

library/                  # if any custom modules, put them here (optional)
module_utils/             # if any custom module_utils to support modules, put them here (optional)
filter_plugins/           # if any custom filter plugins, put them here (optional)

site.yml                  # master playbook
webservers.yml            # playbook for webserver tier
dbservers.yml             # playbook for dbserver tier

roles/
    common/               # this hierarchy represents a "role"
        tasks/            #
            main.yml      #  <-- tasks file can include smaller files if warranted
        handlers/         #
            main.yml      #  <-- handlers file
        templates/        #  <-- files for use with the template resource
            ntp.conf.j2   #  <------- templates end in .j2
        files/            #
            bar.txt       #  <-- files for use with the copy resource
            foo.sh        #  <-- script files for use with the script resource
        vars/             #
            main.yml      #  <-- variables associated with this role
        defaults/         #
            main.yml      #  <-- default lower priority variables for this role
        meta/             #
            main.yml      #  <-- role dependencies
        library/          # roles can also include custom modules
        module_utils/     # roles can also include custom module_utils
        lookup_plugins/   # or other types of plugins, like lookup in this case

    webtier/              # same kind of structure as "common" was above, done for the webtier role
    monitoring/           # ""
    fooapp/               # ""

Альтернативная структура каталогов

В качестве альтернативы вы можете разместить каждый файл инвентаризации со своими group_vars/host_vars в отдельном каталоге. Это особенно полезно, если у ваших group_vars/host_vars нет много общего в разных средах. Структура каталогов может выглядеть примерно так:

inventories/
   production/
      hosts               # inventory file for production servers
      group_vars/
         group1           # here we assign variables to particular groups
         group2           # ""
      host_vars/
         hostname1        # if systems need specific variables, put them here
         hostname2        # ""

   staging/
      hosts               # inventory file for staging environment
      group_vars/
         group1           # here we assign variables to particular groups
         group2           # ""
      host_vars/
         stagehost1       # if systems need specific variables, put them here
         stagehost2       # ""

library/
module_utils/
filter_plugins/

site.yml
webservers.yml
dbservers.yml

roles/
    common/
    webtier/
    monitoring/
    fooapp/

Эта структура обеспечивает большую гибкость для больших сред, а также полное разделение переменных инвентаризации между различными средами. Недостатком является то, что ее сложнее поддерживать, так как файлов больше.

Использование динамической инвентаризации с облаками

Если вы используете провайдера облачных услуг, вам не следует управлять инвентаризацией в статическом файле. См. Динамическая инвентаризация.

Это относится не только к облакам. Если у вас есть другая система, которая поддерживает канонический список систем в вашей инфраструктуре, использование динамической инвентаризации является отличной идеей в целом.

Как различать этапы разработки и производства

Если вы управляете статической инвентаризацией, часто задаётся вопрос о разграничении различных типов сред. Следующий пример демонстрирует хороший способ сделать это. Аналогичные методы группировки можно адаптировать для динамической инвентаризации (например, рассмотрите применение тега AWS «среда:производство», и вы получите автоматически обнаруженную группу систем с именем «ec2_tag_среда_производство»).

Давайте покажем пример статической инвентаризации. В файле production содержится инвентаризация всех ваших хостов в производственной среде.

Рекомендуется определять группы на основе назначения хоста (роли) и также географического положения или расположения дата-центра (при необходимости):

# file: production

[atlanta-webservers]
www-atl-1.example.com
www-atl-2.example.com

[boston-webservers]
www-bos-1.example.com
www-bos-2.example.com

[atlanta-dbservers]
db-atl-1.example.com
db-atl-2.example.com

[boston-dbservers]
db-bos-1.example.com

# webservers in all geos
[webservers:children]
atlanta-webservers
boston-webservers

# dbservers in all geos
[dbservers:children]
atlanta-dbservers
boston-dbservers

# everything in the atlanta geo
[atlanta:children]
atlanta-webservers
atlanta-dbservers

# everything in the boston geo
[boston:children]
boston-webservers
boston-dbservers

Переменные групп и хостов

Этот раздел расширяет предыдущий пример.

Группы хороши для организации, но это не всё, на что они способны. Вы также можете назначить им переменные! Например, Атланта имеет свои собственные серверы NTP, поэтому при настройке ntp.conf мы должны использовать их. Давайте настроим их сейчас:

---
# file: group_vars/atlanta
ntp: ntp-atlanta.example.com
backup: backup-atlanta.example.com

Переменные не только для географической информации! Возможно, веб-серверы имеют некоторые настройки, которые не имеют смысла для серверов базы данных:

---
# file: group_vars/webservers
apacheMaxRequestsPerChild: 3000
apacheMaxClients: 900

Если у нас есть какие-либо значения по умолчанию или значения, которые являются универсальными, мы поместим их в файл group_vars/all:

---
# file: group_vars/all
ntp: ntp-boston.example.com
backup: backup-boston.example.com

Мы можем определить специфичные для оборудования различия в системах в файле host_vars, но избегайте этого, если это не необходимо:

---
# file: host_vars/db-bos-1.example.com
foo_agent_port: 86
bar_agent_port: 99

Опять же, если мы используем динамические источники инвентаризации, многие динамические группы создаются автоматически. Таким образом, метка «класс:веб-сервер» автоматически загрузит переменные из файла «group_vars/ec2_tag_класс_веб-сервер».

Файлы playbooks верхнего уровня разделены по ролям

В файле site.yml мы импортируем playbook, который определяет всю нашу инфраструктуру. Это очень короткий пример, так как он просто импортирует другие playbooks:

---
# file: site.yml
- import_playbook: webservers.yml
- import_playbook: dbservers.yml

В файле, например, webservers.yml (также на верхнем уровне), мы сопоставляем конфигурацию группы webservers с ролями, выполняемыми группой webservers:

---
# file: webservers.yml
- hosts: webservers
  roles:
    - common
    - webtier

Идея заключается в том, что мы можем выбрать конфигурацию всей нашей инфраструктуры, «запустив» site.yml, или мы можем выбрать подмножество, запустив webservers.yml. Это аналогично параметру «–limit» в ansible, но немного более явно:

ansible-playbook site.yml --limit webservers
ansible-playbook webservers.yml

Организация задач и обработчиков для роли

Ниже приведён пример файла задач, который объясняет, как работает роль. Наша общая роль здесь просто настраивает NTP, но она может делать больше, если мы захотим:

---
# file: roles/common/tasks/main.yml

- name: be sure ntp is installed
  yum: name=ntp state=installed
  tags: ntp

- name: be sure ntp is configured
  template: src=ntp.conf.j2 dest=/etc/ntp.conf
  notify:
    - restart ntpd
  tags: ntp

- name: be sure ntpd is running and enabled
  service: name=ntpd state=started enabled=yes
  tags: ntp

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

---
# file: roles/common/handlers/main.yml
- name: restart ntpd
  service: name=ntpd state=restarted

См. Роли для получения дополнительной информации.

Возможности такой организации (примеры)

Мы поделились нашей основной структурой организации.

Какие случаи использования предоставляет эта структура? Много! Если я хочу переконфигурировать всю свою инфраструктуру, это просто:

ansible-playbook -i production site.yml

А как насчёт переконфигурации NTP на всех системах? Легко:

ansible-playbook -i production site.yml --tags ntp

А как насчёт переконфигурации только моих веб-серверов?:

ansible-playbook -i production webservers.yml

А как насчёт только моих веб-серверов в Бостоне?:

ansible-playbook -i production webservers.yml --limit boston

А как насчёт только первых 10, а затем следующих 10?:

ansible-playbook -i production webservers.yml --limit boston[1:10]
ansible-playbook -i production webservers.yml --limit boston[11:20]

И, конечно же, возможны и простые разовые задания.:

ansible boston -i production -m ping
ansible boston -i production -m command -a '/sbin/reboot'

И есть несколько полезных команд, которые стоит знать (по крайней мере, в 1.1 и выше):

# confirm what task names would be run if I ran this command and said "just ntp tasks"
ansible-playbook -i production webservers.yml --tags ntp --list-tasks

# confirm what hostnames might be communicated with if I said "limit to boston"
ansible-playbook -i production webservers.yml --limit boston --list-hosts

Организация развертывания и конфигурации

Вышеприведённая настройка моделирует типичную топологию конфигурации. При выполнении многоуровневых развертываний будут дополнительные playbooks, которые перемещаются между уровнями для развертывания приложения. В этом случае «site.yml» может быть дополнен playbooks, такими как «deploy_exampledotcom.yml», но общие концепции по-прежнему могут применяться.

Рассматривайте «playbooks» как метафору спорта – вам не обязательно использовать одну схему для взаимодействия со всей вашей инфраструктурой всё время – вы можете иметь ситуационные схемы, которые вы используете в разное время и для разных целей.

Ansible позволяет развертывать и настраивать с помощью одного и того же инструмента, поэтому вы, скорее всего, будете повторно использовать группы и просто сохраните конфигурацию ОС в отдельных playbooks от развертывания приложения.

Разработка и производство

Как упоминалось выше, хорошим способом разделения сред разработки (или тестирования) и производства является использование отдельного файла инвентаризации для разработки и производства. Таким образом, вы выбираете, что вы нацеливаетесь с помощью -i. Сохранение всего в одном файле может привести к неожиданностям!

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

Поэтапные обновления

Поймите ключевое слово «serial». При обновлении группы веб-серверов вам действительно нужно использовать его для контроля количества машин, обновляемых одновременно в партии.

См. Делегирование, поэтапные обновления и локальные действия.

Всегда указывайте состояние

Параметр «state» является необязательным для многих модулей. Независимо от того, «state=present» или «state=absent», всегда лучше указывать этот параметр в ваших playbooks, чтобы сделать его понятным, особенно потому, что некоторые модули поддерживают дополнительные состояния.

Группировка по ролям

Мы немного повторяемся с этим советом, но его стоит повторить. Система может входить в несколько групп. См. Инвентаризация и Шаблоны. Наличие групп с именами, такими как webservers и dbservers, повторяется в примерах, потому что это очень мощная концепция.

Это позволяет playbooks нацеливаться на машины на основе роли, а также назначать переменные, специфичные для роли, с помощью системы переменных групп.

См. Роли.

Различия в операционных системах и дистрибутивах

При работе с параметрами, которые различаются между различными операционными системами, отличным способом обработки этого является использование модуля group_by.

Это создаёт динамическую группу хостов, соответствующих определённым критериям, даже если эта группа не определена в файле инвентаризации:

---

# talk to all hosts just so we can learn about them
- hosts: all
  tasks:
     - group_by: key=os_{{ ansible_distribution }}

# now just on the CentOS hosts...

- hosts: os_CentOS
  gather_facts: False
  tasks:
     - # tasks that only happen on CentOS go here

Это добавит все системы в динамическую группу на основе имени операционной системы.

Если необходимы настройки, специфичные для группы, это также можно сделать. Например:

---
# file: group_vars/all
asdf: 10

---
# file: group_vars/os_CentOS
asdf: 42

В приведенном выше примере машины CentOS получают значение «42» для asdf, а другие машины — «10». Это можно использовать не только для установки переменных, но и для применения определённых ролей только к определённым системам.

В качестве альтернативы, если необходимы только переменные:

- hosts: all
  tasks:
    - include_vars: "os_{{ ansible_distribution }}.yml"
    - debug: var=asdf

Это позволит получить переменные на основе имени ОС.

Упаковывание модулей Ansible с playbook

Если у playbook есть директория ./library относительно его YAML-файла, эта директория может использоваться для добавления модулей Ansible, которые автоматически будут включены в путь модулей Ansible. Это отличный способ сохранять модули, связанные с playbook, вместе. Это показано в примере структуры директорий в начале этого раздела.

Пробелы и комментарии

Рекомендуется использовать достаточное количество пробелов для разделения элементов и комментарии (которые начинаются с «#»).

Всегда дайте названия задачам

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

Держите просто

Когда вы можете сделать что-то просто, делайте это просто. Не пытайтесь использовать все возможности Ansible одновременно. Используйте то, что работает для вас. Например, вам, вероятно, не понадобятся vars, vars_files, vars_prompt и --extra-vars одновременно, используя при этом внешний файл инвентаризации.

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

Система контроля версий

Используйте систему контроля версий. Храните свои playbook и файлы инвентаризации в git (или другой системе контроля версий) и делайте коммиты при внесении изменений в них. Таким образом, у вас будет история изменений, описывающая, когда и почему вы изменили правила, которые автоматизируют вашу инфраструктуру.

Переменные и хранилища

Для общего обслуживания часто проще использовать grep, или аналогичные инструменты, для поиска переменных в вашей настройке Ansible. Поскольку хранилища скрывают эти переменные, лучше всего работать с уровнем косвенности. При выполнении playbook Ansible находит переменные в незашифрованном файле, а все конфиденциальные переменные берутся из зашифрованного файла.

Лучший подход для этого — начать с подкаталога group_vars/, названного в честь группы. Внутри этого подкаталога создайте два файла, названные vars и vault. Внутри файла vars определите все необходимые переменные, включая любые конфиденциальные. Затем скопируйте все конфиденциальные переменные в файл vault и добавьте префикс vault_ к этим переменным. Вам следует настроить переменные в файле vars для указания на соответствующие переменные vault_ с использованием синтаксиса jinja2 и убедиться, что файл vault зашифрован с помощью vault.

Данный лучший подход не ограничен количеством файлов переменных и хранилищ или их именами.

См. также

Синтаксис YAML
Узнайте о синтаксисе YAML
Playbook
Обзор основных возможностей playbook
О модулях
Узнайте о доступных модулях
Разработка модулей
Узнайте, как расширить Ansible, написав свои собственные модули
Шаблоны
Узнайте, как выбрать хосты
Директория примеров GitHub
Полные файлы playbook из исходного кода проекта github
Список рассылки
Вопросы? Помощь? Идеи? Обратитесь к списку рассылки на Google Groups

© 2012–2018 Michael DeHaan
© 2018–2019 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/2.4/playbooks_best_practices.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API