Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Ansible: управление конфигурациями серверов

Ansible на практике: плейбуки, роли и идемпотентная настройка серверов

Как настроить серверы воспроизводимо с Ansible: инвентори, плейбуки и задачи, идемпотентность, роли и Galaxy, секреты через Vault, проверка конфигурационного дрейфа — рабочая методика.

Прямой ответ

Ansible решает задачу «сервер создан — что на нём должно быть установлено и настроено», и решает идемпотентно: плейбук можно прогнать сто раз, и со второго раза он ничего не меняет («ok» вместо «changed»). Устройство минимально: инвентори (список хостов и групп), плейбук (YAML со списком задач), модули (apt, copy, template, systemd, user — каждый отвечает за один тип действия и умеет проверять текущее состояние). Агент на серверах не нужен — только SSH и Python на управляемой стороне. Ключевое отличие от «скрипта настройки»: задача описывает целевое состояние («пакет установлен», «файл лежит с этими правами», «сервис запущен и в autostart»), а не команды («apt-get install»), — отсюда воспроизводимость, проверяемость и безопасный повторный запуск. Пара с Terraform стандартна: Terraform создаёт инфраструктуру, Ansible настраивает то, что внутри (разделение).

Анатомия: инвентори, плейбук, модули

Инвентори (inventory/hosts.ini или YAML) — хосты по группам ([web], [db]) с переменными групп и хостов; для облачных хостов — динамические инвентори-плагины (список берётся из API облака). Плейбук — список plays («на хостах группы web выполнить задачи») из tasks; каждая задача — имя (человекочитаемое, по нему читают вывод) + вызов модуля с аргументами. Рабочие модули первого месяца: apt/package (пакеты с state: present/latest), copy/template (файлы; template — Jinja2-подстановки из переменных), systemd/service (состояние сервиса: started/enabled/restarted), user/authorized_key (доступы), lineinfile/blockinfile (точечные правки конфигов), command/shell (последнее средство — неидемпотентно по природе, требует creates:/changed_when:). Запуск — ansible-playbook -i inventory site.yml --limit web --check (check-режим — «что изменилось бы», diff-флаг покажет диффы файлов).

Идемпотентность: свойство, ради которого всё затевалось

Идемпотентная задача — повторный прогон не меняет состояние. Модули состояний идемпотентны по построению (apt «present» на установленном пакете — no-op); ломают свойство command/shell (выполняются всегда) и задачи без условий. Дисциплина: shell-задачи закрывать идемпотентностью вручную — creates: /path/флаг-файл (не выполнять, если результат уже есть), changed_when: false (задача читает, а не меняет — пометить), when: для условных действий. Практический тест плейбука — второй прогон должен быть полностью зелёным (ноль changed); любой «changed» на втором прогоне — задача написана командами вместо состояний. Это же свойство делает безопасным раскатку: плейбук, прерванный на середине, просто запускается заново — доводит до целевого состояния без «половины скрипта».

Роли и структура проекта

Рост плейбука лечится ролями — стандартной раскладкой (roles/nginx/tasks/main.yml, .../templates/, .../handlers/, .../defaults/): роль — переиспользуемая единица «настроить nginx», подключаемая к любым хостам. Handlers — отдельный механизм: задача-уведомление (notify: restart nginx) срабатывает один раз в конце прогона, только если что-то реально изменилось (правильный способ «перезапустить после правки конфига», а не рестарт на каждый прогон). Переменные — иерархия (defaults роли → групповые → хостовые → extra-vars), приоритеты документированы и стоит их знать, чтобы не искать «откуда взялось значение». Galaxy/Ansible Galaxy — готовые роли сообщества (качество разное: читать код роли до применения — она выполняется с root-правами на ваших серверах). Разумный баланс — свои роли для типовых сервисов проекта + проверенные community-роли для стандартного (firewall, ntp).

Секреты: Vault и переменные

Пароли, ключи и сертификаты в плейбуках не хранят: ansible-vault шифрует файлы переменных (зашифрованный YAML коммитится в git, расшифровка — паролем при запуске --ask-vault-pass или из CI-секрета). Альтернативы: переменные из внешнего секрет-хранилища (lookup-плагины к Vault/SOPS), инъекция через CI. Правила те же, что для любых секретов (гайд): ничего чувствительного в git открытым, доступ к vault-паролю ограничен, ротация возможна. Отдельная ловушка — секреты в выводе: задачи с no_log: true скрывают значения из логов (нужно для задач, передающих пароли).

Практический сценарий: reproducible-сервер приложения

Полный цикл: Terraform поднял VM с Ubuntu и открыл порты; дальше работает Ansible. Базовая роль common: пользователь deploy с SSH-ключом (authorized_key из переменной), sudo без пароля, базовые пакеты, таймзона, unattended-upgrades, firewall (ufw: 22, 80, 443). Роль app: зависимости рантайма, каталог приложения, systemd-юнит из шаблона (юниты и их устройство — в статье про systemd), state: started, enabled. Роль nginx: конфиг reverse-proxy из шаблона, handler на рестарт. Деплой новой версии — отдельный короткий плейбук: git pull в каталог (или копирование артефакта), миграции, systemd: state: restarted для сервиса — и весь прогон идемпотентен, прерываем и повторяем. Проверка дрейфа — периодический --check --diff по проду (кто-то правил конфиг руками — дифф покажет; находка лечится переносом правки в шаблон, а не «оставим как есть»). Итог: новый сервер идентичен старому за один прогон, и «настройка сервера» из tribal knowledge превратилась в репозиторий.

FAQ

Ansible или Chef/Puppet/Salt? Ansible выигрывает порогом входа (YAML+SSH, агентов нет) и достаточен в подавляющем большинстве случаев; агентные системы оправданы в очень больших парках с постоянным энфорсментом состояния. Для команды разработчиков вопрос почти всегда закрыт в пользу Ansible.

Можно ли без инвентори-файла, на localhost? Да — плейбуки на localhost годятся для настройки своей машины (dotfiles-подход) и тестирования ролей; но основная ценность — парк серверов, и там инвентори обязателен.

Как тестировать роли? Молекула (molecule) — стандарт: поднимает контейнер/VM, прогоняет роль, проверяет результат тестами (testinfra); минимум — прогон роли на одноразовом контейнере в CI и второй прогон на идемпотентность (ноль changed).

Что делать, когда плейбук «на 2000 строк»? Дробить на роли по сервисам, выносить переменные в group_vars, общие куски — в отдельные роли-зависимости; плейбук верхнего уровня должен читаться как оглавление (список ролей по группам хостов), а не как простыня задач.

Источники: документация Ansible (playbooks, vault) — ссылки в шапке.