ADG Оставить заявку
Блог Автоматизация 4 мин чтения

Ansible roles: разбили монолитный playbook на три роли и не пожалели

Ansible 1.7 выходит с улучшенными roles и Galaxy. Рассказываем как перешли от плоских playbook-файлов к структуре ролей и что из этого получилось на практике.

Контекст момента

Ansible 1.7 выходит в августе 2014, добавляя улучшенные roles и galaxy

В январе писали про идемпотентность и базовую структуру playbook-ов - тогда всё ещё жило в трёх плоских файлах: base.yml, web.yml, db.yml. Подход работал, пока клиентов было немного и серверы были примерно похожи друг на друга. К середине года картина усложнилась: три проекта на сопровождении, у каждого свой набор компонентов, и плоские файлы начали превращаться в лапшу.

Ansible 1.7 вот-вот выходит с переработанными roles и нормальной поддержкой Galaxy. Это стало поводом разобраться с тем, что накопилось.

Что не так с плоскими playbook-ами

Конкретная проблема была такая. В base.yml жили задачи для всего: настройка NTP, добавление пользователей, установка Zabbix-агента, базовый rsyslog-конфиг. Всё вместе, в одном файле, переменные вперемешку. Когда понадобилось добавить мониторинг на новый сервер без веб-части - пришлось либо запускать весь base.yml целиком, либо копировать нужные таски в отдельный файл. Копирование - это дорожка к тому, что одна и та же задача живёт в двух местах и рано или поздно расходится.

К тому же в какой-то момент обнаружили, что NTP настраивается у нас тремя разными способами в разных playbook-ах - просто потому что каждый раз кто-то писал заново, не оглядываясь назад. Такое в git-истории видно только если специально искать.

Как выглядит структура ролей

Перешли на такую схему:

roles/
  webserver/
    tasks/main.yml
    handlers/main.yml
    templates/
    defaults/main.yml
  dbserver/
    tasks/main.yml
    handlers/main.yml
    templates/
    defaults/main.yml
  monitoring-agent/
    tasks/main.yml
    defaults/main.yml

Три роли: webserver, dbserver, monitoring-agent. Playbook верхнего уровня превратился в декларацию - какой хост какие роли получает:

- hosts: webservers
  roles:
    - webserver
    - monitoring-agent

- hosts: dbservers
  roles:
    - dbserver
    - monitoring-agent

Читается сразу. Новый человек открывает файл и за минуту понимает что на каких серверах крутится.

Galaxy и роль NTP

Отдельная история с NTP. Синхронизация времени - задача простая, но с нюансами: разные дистрибутивы, разные пакеты (ntpd vs chrony в CentOS 7), шаблон конфига с пулами серверов, handlers для перезапуска. Мы писали это трижды в разных вариациях на разных проектах.

В Galaxy нашлась готовая роль настройки NTP с нормальной поддержкой и RedHat, и Debian. Проверили, что роль делает ровно то что нужно, зафиксировали версию в requirements.yml и применили сразу на трёх проектах. Обновление конфига NTP теперь - правка переменных в одном месте, не в трёх разных файлах.

Важная оговорка: Galaxy-роль перед использованием надо читать. Попадались роли, которые делали что-то лишнее или агрессивно перетирали конфиги, которые мы настраиваем отдельно. Слепое ansible-galaxy install без просмотра tasks - риск.

Что стало лучше

Переиспользование без копирования. monitoring-agent применяется и к веб-серверам, и к базам данных, и к будущим машинам - без дублирования кода.

Переменные в одном месте. defaults/main.yml роли содержит все параметры с разумными значениями по умолчанию. Клиент-специфичные переменные переопределяются в инвентаре. Нет больше ситуации когда не понятно откуда берётся какой-то zabbix_server_ip.

Handlers не конфликтуют. В плоском playbook handlers жили в одной куче. При ролях каждая роль тащит свои handlers - нет риска что handler от nginx случайно перезапустит что-то не то при запуске db-задач.

Понятный diff. Когда всё в одном файле, git diff при изменении NTP-конфига выглядит как изменение строки где-то в середине 300-строчного файла. Когда роль отдельная - diff аккуратно показывает что изменилось в roles/ntp/templates/ntp.conf.j2.

Где трёт

Структура каталогов сложнее. Новый человек, который видит Ansible первый раз, теряется: куда смотреть, где что искать. Плоский base.yml в этом смысле понятнее - открыл один файл, всё видно. С ролями приходится объяснять логику организации.

Зависимости между ролями через meta/main.yml - мощно, но работает неочевидно. Если роль A зависит от роли B, Ansible применит B автоматически. Это удобно, пока зависимости линейные. Когда начинается граф - нужно следить внимательно.

Galaxy как репозиторий невелик: специализированные роли найти сложно, а качество того что есть - разное. Для базовых вещей (NTP, users, common packages) хватает, для чего-то специфичного приходится писать самим.

В итоге

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

Galaxy уже сейчас закрывает базовые инфраструктурные задачи. Три проекта с одной NTP-ролью вместо трёх независимых реализаций - это уже окупает время на изучение инструмента.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.