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