Spec-Zone.ru › Ansible 2.8

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

Ниже приведены некоторые советы по эффективному использованию Ansible и Ansible playbooks.

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

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

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

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

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

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

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

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

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

group_vars/
   group1.yml             # here we assign variables to particular groups
   group2.yml
host_vars/
   hostname1.yml          # here we assign variables to particular systems
   hostname2.yml

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.yml       # here we assign variables to particular groups
         group2.yml
      host_vars/
         hostname1.yml    # here we assign variables to particular systems
         hostname2.yml

   staging/
      hosts               # inventory file for staging environment
      group_vars/
         group1.yml       # here we assign variables to particular groups
         group2.yml
      host_vars/
         stagehost1.yml   # here we assign variables to particular systems
         stagehost2.yml

library/
module_utils/
filter_plugins/

site.yml
webservers.yml
dbservers.yml

roles/
    common/
    webtier/
    monitoring/
    fooapp/

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

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

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

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

Различия между этапами разработки (staging) и производства (production)

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

Давайте рассмотрим пример статической инвентаризации. Ниже в файле 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

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

Разделение 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: present
  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[0:9]
ansible-playbook -i production webservers.yml --limit boston[10:19]

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

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

И есть несколько полезных команд, которые стоит знать:

# 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 от развертывания приложения.

Различия между этапами разработки (staging) и производства (production)

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

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

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

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

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

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

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

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

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

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

См. Роли.

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

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

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

---

 - name: talk to all hosts just so we can learn about them
   hosts: all
   tasks:
     - name: Classify hosts depending on their OS distribution
       group_by:
         key: os_{{ ansible_facts['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:
    - name: Set OS distribution dependant variables
      include_vars: "os_{{ ansible_facts['distribution'] }}.yml"
    - debug:
        var: asdf

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

Связывание модулей Ansible с playbook

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

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

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

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

Можно опустить «name» для заданной задачи, хотя рекомендуется предоставить описание того, почему что-то делается. Это имя отображается при запуске 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.8/user_guide/playbooks_best_practices.html

Spec-Zone.ru

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