![](https://habrastorage.org/getpro/habr/upload_files/138/aae/6d0/138aae6d04e92c85ca23168706e7e5ad.png)
Ansible — один из наиболее часто используемых программных инструментов с открытым исходным кодом для управления конфигурацией, предоставления программного обеспечения и развертывания приложений в облачных и локальных средах. В этой статье мы поделимся Practices по настройке Ansible, предложим интересные подходы для эффективной работы с внутренними компонентами продукта.
Базовые Best Practices
Выбирайте YAML вместо JSON: Хотя Ansible позволяет использовать синтаксис JSON, с YAML читать файлы и проекты гораздо легче.
Используйте одинаковые пробелы: Чтобы красиво разделить объекты и улучшить читаемость, оставьте пустую строку между блоками, задачами или другими компонентами.
Используйте последовательную стратегию тегирования: Тегирование — это мощная функция в Ansible, поскольку она позволяет группировать задачи и детальнее ими управлять. Теги дают нам возможность добавлять тонкие элементы управления выполнением задач.
Добавляйте комментарии: Если вы считаете, что это необходимо, не стесняйтесь использовать комментарии, объясняющие цель и причину возникновения задач, переменных и так далее.
Используйте стратегию с последовательным именованием: Прежде, чем приступить к настройке своих проектов в Ansible, подумайте о применении последовательной стратегии именования для задач, плейбуков, переменных, ролей и модулей.
Определите руководство по стилю: Следуйте букве руководства — оно поможет последовательно выполнять задачи. Если вы ищете вдохновение, посмотрите на это руководство по стилю от OpenShift.
Будьте проще: Ansible предоставляет множество опций и расширенных возможностей, но это не значит, что мы должны использовать их все в один момент времени. Найдите те инструменты Ansible, которые подходят для вашего случая, и попытайтесь максимально упростите свой проект. Например, начните с простого плейбука и файла инвентаризации, а более сложные инструменты или рефакторинг добавьте позже.
Храните свои проекты в системе контроля версий (VCS): Сохраняйте файлы Ansible в репозитории кода и регулярно фиксируйте новые изменения.
Не храните конфиденциальные значения в обычном тексте: Для секретов и конфиденциальных значений используйте Ansible Vault для шифрования переменных и файлов и защиты любой конфиденциальной информации.
Тестируйте проекты: Используйте инструменты типа Ansible Lint и добавляйте этапы тестирования в конвейеры CI/CD для ваших репозиториев Ansible. Для тестирования ролей Ansible рекомендуем взглянуть на Molecule. Для тестирования вводимых данных или проверки пользовательских выражений можно использовать модуль assert.
Организуйте каталоги
Посмотрите, как выглядит хорошо организованная структура каталогов Ansible:
inventory/
production # inventory file for production servers
staging # inventory file for staging environment
testing # inventory file for testing environment
group_vars/
group1.yml # variables for particular groups
group2.yml
host_vars/
host1.yml # variables for particular systems
host2.yml
library/ # Store here any custom modules (optional)
module_utils/ # Store here any custom module_utils to support modules (optional)
filter_plugins/ # Store here any filter plugins (optional)
master.yml # master playbook
webservers.yml # playbook for webserver tier
dbservers.yml # playbook for dbserver tier
roles/
example_role/ # 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 jinja2
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
monitoring/ # same kind of structure as "common" was above, done for the monitoring role
Best Practices инвентаризации
Best Practices
Используйте группы инвентаризации: Группируйте узлы на основе общих атрибутов, которые они могут разделять — расположение, цель, роли, среда.
Делайте отдельную инвентаризацию для каждой среды: Определите отдельный файл инвентаризации для каждой среды — производственной, промежуточной, тестовой и так далее, чтобы изолировать их друг от друга и избежать ошибок, связанных с неправильным выбором среды.
Проводите динамическую инвентаризацию: При работе с облачными провайдерами или быстро меняющимися средами ведение статических инвентаризаций может стать сложной задачей.
Используйте динамическую группировку во время работы: Мы можем создавать динамические группы с помощью модуля `group_by` на основе заданного атрибута — к примеру, на основе их операционной системы — и выполнять различные задачи на каждом из них без определения таких групп в инвентаризации.
- name: Gather facts from all hosts
hosts: all
tasks:
- name: Classify hosts depending on their OS distribution
group_by:
key: OS_{{ ansible_facts['distribution'] }}
# Only for the Ubuntu hosts
- hosts: OS_Ubuntu
tasks:
- # tasks that only happen on Ubuntu go here
# Only for the CentOS hosts
- hosts: OS_CentOS
tasks:
- # tasks that only happen on CentOS go here
Best Practices для плейбуков и сценариев
Всегда указывайте статус задач: Чтобы сделать ваши задачи более понятными, задавайте параметр state, даже если это не требуется из-за значения по умолчанию.
Размещайте каждый аргумент задачи в отдельной строке: Это помогает сделать файлы Ansible более удобными для чтения. Рассмотрим несколько примеров:
Это рабочий, но плохо читаемый вариант:
- name: Add the user {{ username }}
ansible.builtin.user: name={{ username }} state=present uid=999999 generate_ssh_key=yes
become: yes
Вместо этого вы можете использовать данный синтаксис: он улучшает читабельность и понятность задач и их аргументов:
- name: Add the user {{ username }}
ansible.builtin.user:
name: "{{ username }}"
state: present
uid: 999999
generate_ssh_key: yes
become: yes
Используйте плейбуки верхнего уровня для оркестровки плейбуков нижнего уровня: Вы можете логически сгруппировать задачи, сценарии и роли в низкоуровневых плейбуках и использовать плейбуки верхнего уровня для требуемой вам оркестровки.
Группируйте задачи с помощью блочного синтаксиса: Задачи, которые связаны друг с другом и имеют общие атрибуты или теги, могут быть сгруппированы с помощью функции blok. Еще одним преимуществом этой опции является более простой задач, находящихся в одном блоке.
- name: Install, configure, and start an Nginx web server
block:
- name: Update and upgrade apt
ansible.builtin.apt:
update_cache: yes
cache_valid_time: 3600
upgrade: yes
- name: "Install Nginx"
ansible.builtin.apt:
name: nginx
state: present
- name: Copy the Nginx configuration file to the host
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/sites-available/default
- name: Create link to the new config to enable it
file:
dest: /etc/nginx/sites-enabled/default
src: /etc/nginx/sites-available/default
state: link
- name: Create Nginx directory
ansible.builtin.file:
path: /home/ubuntu/nginx
state: directory
- name: Copy index.html to the Nginx directory
copy:
src: files/index.html
dest: /home/ubuntu/nginx/index.html
notify: Restart the Nginx service
when: ansible_facts['distribution'] == 'Ubuntu'
tags: nginx
become: true
become_user: root
Используйте контроллеры для запущенных задач: Контроллеры позволяют выполнить задачу после внесенных изменений. Контроллер будет запущен, когда произойдут изменения в файле index.html
из приведенного выше примера.
handlers:
- name: Restart the Nginx service
service:
name: nginx
state: restarted
become: true
become_user: root
Best Practices для переменных
Переменные позволяют пользователям параметризовать различные компоненты Ansible и хранить значения, которые мы можем повторно использовать.
Всегда задавайте значения по умолчанию для ваших переменных: Установите значения по умолчанию для всех групп в group_vars/all
. Для каждой роли установите переменные по умолчанию в roles/<role_name>/defaults.main.yml
.
Используйте каталоги groups_vars и host_vars: Чтобы файл инвентаризации был максимально аккуратным и лаконичным, устанавливайте переменные групп и хостов в каталогах groups_vars
и host_vars
.
Ссылайтесь на роль в переменных в качестве префикса: Старайтесь быть четкими при определении имен переменных для ролей.
nginx_port: 80
apache_port: 8080
Best Practices для модулей
Храните локальные модули рядом с плейбуками: Используйте каталог ./library
каждого проекта Ansible для хранения соответствующих пользовательских модулей. Плейбуки, которые имеют каталог ./library
относительно своего пути, могут напрямую ссылаться на любые модули внутри него.
Не используйте модули command и shell: Рекомендуем использовать их только тогда, когда нет другого выбора. Вместо этого выбирайте специализированные модули, которые обеспечивают отказоустойчивость и необходимую обработку ошибок.
Указывайте аргументы модуля, когда это имеет смысл: Во многих аргументах модулей значения по умолчанию могут быть опущены. Для удобства можно указать некоторые из этих аргументов, например, для определения статуса плейбука.
Отдавайте предпочтение многозадачности в модуле, а не циклам: Наиболее эффективным способом определения списка однотипных задач типа установки пакетов является использование нескольких задач в одном модуле.
- name: Install Docker dependencies
ansible.builtin.apt:
name:
- curl
- ca-certificates
- gnupg
- lsb-release
state: latest
Документируйте и тестируйте пользовательские модули: Каждый пользовательский модуль должен содержать примеры, записанные настройки и описание полученных ответов. Новые модули следует тщательно тестировать перед выпуском. Вы можете создать плейбуки для тестирования пользовательских модулей и проверки различных сценариев для тестов.
Best Practices для ролей
Следуйте структуре каталога ролей Ansible Galaxy: Используйте команду ansible-galaxy init <role_name>
для создания стандартного каталога ролей.
![](https://habrastorage.org/getpro/habr/upload_files/a68/07a/51f/a6807a51fae02d308e90704a6185d96d.png)
Сохраняйте назначение ролей: Каждая роль должна иметь отдельную ответственность и отдельную функциональность. Разделяйте роли на основе различных функциональных возможностей или технических областей задач.
Ограничивайте зависимости между ролями: Избегая большого количества зависимостей в ваших ролях, вы поддерживать их слабосвязанными, разрабатывать их независимо друг от друга и использовать их без заморочек со сложными зависимостями между ними.
Отдавайте предпочтение модулям import_role или include_role: Чтобы лучше контролировать порядок выполнения ролей и задач, используйте модули import_role
или include_role
, а не классические роли.
Будьте осторожны в отношении Ansible Galaxy Roles: При загрузке и использовании содержимого и ролей из Galaxy проверяйте содержимое файлов и выбирайте роли от надежных авторов.
Храните используемые роли Galaxy локально: Чтобы не зависеть от внешнего репозитория Ansible Galaxy, вы можете хранить любые роли из Galaxy в своих репозиториях кода и управлять ими как частью проекта.
Best Practices для развертывания среды
Сначала протестируйте изменения в staging: Это отличный способ убедиться в том, что изменения приведут к ожидаемому результату, а не к новым проблемам.
Ограничьте выполнение задач заданными узлами: Если вы хотите запустить плейбук на определенном хосте, вы можете использовать флаг --limit
. Если вам нужно запустить только определенные задачи из плейбука на основе тегов, вы можете определить, какие теги будут выполняться, с помощью флага --tags
.
Проверьте, какие задачи будут запущены перед выполнением: Вы можете использовать флаг --list-tasks
для подтверждения того, какие задачи будут запущены без их фактического выполнения. Вы можете использовать флаг --list-hosts
: так вы убедитесь в том, на какие хосты повлияет плейбук, но при этом не запустить его.
Убедитесь в том, что вы собрались менять, но при этом не запускайте обновления: Используйте флаг --check
для прогнозирования изменений, которые могут произойти. Объедините его с флагом --diff
, чтобы показать различия в измененных файлах.
Начните с конкретной задачи: Используйте флаг --start-at-task
, чтобы плейбук начал работать с выбранной вами задачи.
Используйте Rolling Updates для контроля количества целевых машин: По умолчанию Ansible пытается запустить программу параллельно на всех хостах. Чтобы добиться непрерывных обновлений, вы можете использовать ключевое слово serial. Используя это ключевое слово, вы можете определить, на скольких хостах изменения могут выполняться параллельно.
Управляйте стратегией выполнения (запуска) playbook: По умолчанию Ansible завершает выполнение каждой задачи на всех хостах перед переходом к следующей задаче. Если вы хотите выбрать другую стратегию выполнения, ознакомьтесь с этой документацией.
От редакции
С инструментами Ansible мы подробно знакомимся на курсе DevOps Upgrade — интенсивном курсе для тех, кто хочет стать DevOps-инженером. Поток стартует с практическими заданиями и поддержкой от спикеров курса стартует уже 15 мая — узнать подробнее о программе и присоединиться к группе вы можете на нашем сайте.