Одна пьеса на десять серверов быстро превращается в копипаст: у каждого хоста свои пути, порты и версии пакетов. Ansible предлагает роли — переиспользуемые блоки задач с переменными, шаблонами и обработчиками. Освоив роли и приоритеты переменных, вы перестаёте копировать YAML и начинаете собирать инфраструктуру из понятных деталей.

Анатомия роли

Роль — это каталог с предсказуемой структурой. Задачи лежат в tasks/main.yml, значения по умолчанию в defaults/main.yml, обязательные переменные в vars/main.yml, шаблоны в templates, файлы в files, обработчики в handlers. Метаданные и зависимости описывает meta/main.yml.

Такое разделение не формальность. defaults удобно переопределять в инвентаре, а vars внутри роли имеют высокий приоритет и защищают критичные значения от случайной замены. Шаблоны и файлы ищутся относительно роли, поэтому роли можно переносить между проектами без правки путей.

Создание скелета

Не пишите структуру руками: генератор создаст каталоги и заготовки. Дальше остаётся наполнить задачи и убрать лишние файлы.

ansible-galaxy init roles/nginx
tree roles/nginx
ansible-galaxy role list
ansible-galaxy collection list

Имя роли лучше держать в нижнем регистре через подчёркивания: дефисы допустимы, но ломают часть инструментов. В репозитории храните роли отдельно от пьес, а версию фиксируйте тегом. Если роль используется в нескольких проектах, вынесите её в собственный репозиторий и подключайте через requirements.yml.

defaults, vars и приоритеты

Главная путаница в Ansible — откуда взялось значение переменной. Приоритетов много, но запомнить нужно несколько уровней. Ниже — от слабого к сильному в упрощённом виде.

  • defaults роли — самые слабые, предназначены для переопределения.
  • group_vars и host_vars из инвентаря.
  • vars роли и vars пьесы.
  • Параметры задачи, include_role и extra-vars.

extra-vars побеждает почти всё, поэтому используйте его для разовых запусков, а не для постоянной конфигурации. Значения из vars роли не переопределяются инвентарём — это частая причина «почему мой порт не применился». Всё, что должно настраиваться снаружи, держите в defaults.

ansible-inventory --host web1
ansible web1 -m ansible.builtin.debug -a "var=nginx_port"
ansible-playbook site.yml -e nginx_port=8080 --check

Команда ansible-inventory показывает итоговые переменные хоста с учётом групп. Это быстрее, чем искать по десяти файлам. Если значение неожиданное, проверьте, не задано ли оно в нескольких group_vars одновременно.

group_vars и host_vars

Общие настройки кладите в group_vars/all.yml, различия среды — в group_vars/production.yml, особенности машины — в host_vars/web1.yml. Инвентарь при этом остаётся списком хостов, а не свалкой параметров.

inventory/
  production.ini
  group_vars/all.yml
  group_vars/production.yml
  host_vars/web1.yml

Для секретов используйте ansible-vault, а не открытые YAML. Зашифрованный файл можно хранить в репозитории, ключ — в менеджере секретов или переменной окружения. Не коммитьте пароль в group_vars только потому, что «репозиторий приватный»: доступ к нему получают не только администраторы.

ansible-vault create group_vars/production/vault.yml
ansible-vault edit group_vars/production/vault.yml
ansible-playbook site.yml --ask-vault-pass

include_role и tasks_from

Роль не обязана быть монолитом. Разбейте её на файлы и вызывайте нужный набор задач через tasks_from. Это удобно для частичных операций: установить пакеты отдельно от настройки.

- name: Настроить nginx
  ansible.builtin.include_role:
    name: nginx
    tasks_from: configure.yml
  vars:
    nginx_worker_processes: 4

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

Зависимости и requirements.yml

Зависимости роли описываются в meta/main.yml и устанавливаются до её задач. Внешние роли и коллекции фиксируйте по версиям, иначе завтрашний прогон принесёт другой код.

ansible-galaxy role install -r requirements.yml -p roles
ansible-galaxy collection install -r requirements.yml -p collections
ansible-galaxy role install geerlingguy.nginx -p roles

Файл requirements.yml храните рядом с пьесой. Для коллекций указывайте source и version, для ролей — name и version. Обновление зависимости — отдельный коммит с прогоном тестов, а не фоновая операция в CI. Каталог collections добавьте в .gitignore, если он собирается на месте.

Handlers и идемпотентность

Обработчик запускается только при изменении и один раз за прогон, даже если его уведомили несколько задач. Это экономит время и предотвращает лишние перезапуски.

- name: Шаблон конфигурации
  ansible.builtin.template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
    mode: "0644"
  notify: Reload nginx

- name: Reload nginx
  ansible.builtin.service:
    name: nginx
    state: reloaded

Проверяйте конфигурацию до перезагрузки: добавьте задачу с command и changed_when: false, которая вызывает nginx -t. Иначе синтаксическая ошибка в шаблоне уронит сайт. Идемпотентность проверяется повторным прогоном: второй запуск не должен показывать changed у задач, которые не меняют систему.

Шаблоны и фильтры

Jinja2 закрывает большинство случаев без сложной логики. Значения по умолчанию задавайте через default, списки объединяйте через combine, а отсутствие переменной обрабатывайте явно.

{{ nginx_port | default(80) }}
{{ ansible_facts['distribution'] | lower }}
{{ nginx_upstreams | combine({'api': '10.0.0.5:8080'}, recursive=True) }}
{{ users | map(attribute='name') | join(', ') }}

Не злоупотребляйте условиями в шаблоне: если ветвлений больше двух, вынесите их в отдельные файлы или переменные. Проверяйте результат через —check —diff: diff покажет, что именно изменится в файле, и часто выявляет лишние пробелы и права.

Проверка и тесты

Минимальный набор — синтаксическая проверка, линтер и прогон в режиме проверки. Этого достаточно, чтобы поймать большинство опечаток до продакшена.

ansible-playbook site.yml --syntax-check
ansible-lint roles/nginx
ansible-playbook site.yml --check --diff --limit web1
ansible-playbook site.yml --list-tasks --tags nginx

Для сложных ролей добавьте Molecule с контейнером или виртуальной машиной. Тест должен проверять результат, а не только отсутствие ошибок: запущенный сервис, открытый порт, созданный файл. Прогон на чистом хосте выявляет скрытые зависимости от предыдущих запусков.

Чек-лист

  • Настраиваемые значения в defaults, критичные — в vars.
  • Секреты зашифрованы ansible-vault, ключ не в репозитории.
  • Версии ролей и коллекций зафиксированы.
  • Повторный прогон не даёт changed без причины.
  • Конфигурация проверяется до reload сервиса.
  • Есть —check, линтер и тест на чистом хосте.

Итог

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

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте