Ansible: идемпотентность и роли
Написал сценарий из четырёх задач и прогнал дважды. Первый прогон: «ok=4 changed=4» - сделано всё. Второй прогон, ничего между ними не менялось: «ok=4 changed=1». Три задачи честно поняли, что делать нечего, а одна отчиталась об изменении - и это ровно та задача, где я вызвал обычную команду оболочки.
Стержень: модули умеют проверять текущее состояние и потому идемпотентны, а прямой вызов команды - нет, и он же портит весь отчёт об изменениях.
// Формулировки: «что такое идемпотентность в Ansible?», «почему changed всегда не ноль?», «где граница между Ansible и Terraform?»
Идемпотентность и отчёт
Модуль тут - готовая единица работы, которая умеет и проверить, и сделать. Устроен он так: сначала смотрит фактическое состояние, потом решает, надо ли что-то менять. Создать каталог, положить файл с нужным содержимым, добавить строку в файл - все три задачи на втором прогоне отчитались «без изменений», потому что всё уже было как надо.
А вызов произвольной команды такой проверки не делает - он просто выполняет. Отчёт при этом честно говорит «изменено», хотя ничего не изменилось. В моём замере именно эта одна задача дала «changed=1» на втором прогоне.
// Почему это важнее, чем кажется. Отчёт об изменениях - главный инструмент проверки: прогнали сценарий, увидели ноль изменений, значит, реальность совпадает с описанием. Как только в сценарии появляются задачи, всегда отчитывающиеся об изменении, этот сигнал ломается, и никто больше не смотрит на цифры. Лечится это условиями «когда считать изменённым» и «когда вообще выполнять», а лучше - заменой команды на подходящий модуль.
- идемпотентная задача
- сначала проверяет состояние, потом решает, надо ли действовать
- отчёт об изменениях
- число изменённых задач; ноль означает, что реальность совпала с описанием
Проверочный прогон и порядок
Есть режим, в котором сценарий показывает, что СОБИРАЕТСЯ сделать, ничего не меняя. Проверил: удалил созданный файл и запустил в этом режиме - отчёт показал изменения, а файл на диске так и не появился. Это ближайший аналог просмотра плана в инструментах описания инфраструктуры.
Работает он не всегда честно: задачи с прямым вызовом команд в этом режиме обычно пропускаются, и если следующая задача зависит от их результата, картина получается неполной. В моём прогоне одна задача действительно оказалась пропущена.
// Второе принципиальное отличие от инструментов описания инфраструктуры: здесь порядок задач важен. Сценарий выполняется сверху вниз, зависимости не выводятся сами. И состояния тут нет: инструмент каждый раз спрашивает саму машину. Отсюда плюс - потерять состояние невозможно, и минус - удалить ресурс, убрав его из описания, нельзя: чтобы что-то снести, надо явно написать задачу «убрать».
- проверочный прогон
- режим, показывающий планируемые изменения без их применения
- порядок задач
- выполняются сверху вниз; зависимости не выводятся автоматически
Граница между инструментами
Разделение обычно такое. Инструмент описания инфраструктуры создаёт то, чего не было: сети, машины, кластеры, базы, права. Инструмент настройки приводит в порядок то, что внутри уже созданной машины: пакеты, конфиги, службы, пользователи.
Стык между ними - место, где чаще всего болит. Классические варианты: описание инфраструктуры создаёт машину и запускает настройку через стартовый скрипт; или создаёт, а настройка запускается отдельным шагом конвейера по списку машин из выходных значений.
// И честная оговорка про современную практику: с контейнерами роль инструмента настройки сильно сузилась. Настройка уехала внутрь образа, а машины стали одноразовыми - вместо того чтобы приводить машину в порядок, её просто пересоздают из свежего образа. Инструмент настройки при этом остаётся востребованным там, где машины живут долго: базы на своём железе, сетевое оборудование, машины разработчиков, площадки без контейнеров.
- инструмент настройки
- приводит в нужный вид содержимое уже созданной машины
- одноразовая машина
- её не чинят и не донастраивают, а пересоздают из свежего образа
Как отвечать: «Что такое идемпотентность в Ansible и почему changed никогда не ноль?»
Идемпотентность здесь означает, что задача сначала проверяет фактическое состояние и действует, только если надо. Я прогонял сценарий из четырёх задач дважды: первый раз «изменено 4», второй - «изменено 1», и эта единица - задача с прямым вызовом команды оболочки. Она не умеет проверять состояние и потому всегда отчитывается об изменении. Это и есть ответ на вторую половину вопроса: если в сценарии есть такие задачи, отчёт перестаёт быть сигналом. А отчёт - главный инструмент проверки: прогнал, увидел ноль изменений, значит, реальность совпадает с описанием. Чиню это тремя способами: заменяю команду на подходящий модуль, если он есть; ставлю условие, при котором задача считается изменившей что-то; или условие, при котором она вообще выполняется.
Ответ связывает механику с практической ценностью отчёта и даёт три конкретных способа починки. Именно сломанный отчёт об изменениях и есть настоящая проблема.
На чём валятся
- −Пишут сценарий на прямых вызовах команд и теряют идемпотентность вместе с отчётом.
- −Не проверяют, что второй прогон даёт ноль изменений.
- −Полагаются на проверочный прогон там, где половина задач в нём пропускается.
- −Ждут, что удаление задачи из сценария снесёт созданное. Нужна явная задача на удаление.
- −Пытаются настраивать долгоживущие машины там, где проще пересоздать их из образа.
Проверьте себя
Пять вопросов из банка по этой подтеме. Всего их 7, остальные разбираются в тренажёре.
- Ansible и Terraform часто держат вместе. По какой границе их разводят?A)Ansible для облака, Terraform для железных серверовB)Terraform ведёт учёт ресурсов, Ansible настраивает хостыC)Terraform для приложений, Ansible для сетевого оборудованияD)Ansible применяют в проде, Terraform — только в тестовых средах
показать ответ и разбор
+B)Terraform ведёт учёт ресурсов, Ansible настраивает хосты// разбор: Terraform ведёт учёт: знает, что создал, и потому умеет удалять лишнее и приводить набор ресурсов к описанному. Ansible состояния не хранит — он приезжает на существующие хосты и приводит их конфигурацию к нужной, но не знает, что удалить, если задачу убрали из плейбука. Отсюда типовая связка: инфраструктуру поднимает Terraform, начинку настраивает Ansible, а в неизменяемой модели вторая часть заменяется сборкой образов.
- Плейбук должен накатываться на веб-серверы, но не на серверы БД. Чем это задаётся?A)Инвентарём: группы хостов + hosts на группуB)Условием when на каждой задаче по имени хостаC)Отдельным плейбуком-копией под каждый серверD)Тегами задач, запуская нужные через --tags
показать ответ и разбор
+A)Инвентарём: группы хостов + hosts на группу// разбор: В Ansible область действия задаёт инвентарь: хосты разложены по группам (webservers, dbservers), а в плее указывают hosts: webservers — плейбук идёт только на них. Группы можно комбинировать (webservers:&production), задавать групповые переменные. when-условия по имени хоста и копии плейбуков — хрупкие обходные пути; теги же фильтруют задачи внутри плея, а не выбирают целевые хосты.
- Нужно перезапускать сервис только если задача реально изменила его конфиг. Как это делают в Ansible?A)Ставить restart отдельной задачей после каждого прогонаB)Проверять конфиг модулем shell и рестартить по diffC)Рестартить в начале плейбука на всякий случайD)notify → handler, срабатывает лишь при changed
показать ответ и разбор
+D)notify → handler, срабатывает лишь при changed// разбор: Для «перезапусти, только если поменялось» служат handlers: задача, изменившая конфиг (статус changed), делает notify «restart service», а сам handler выполняется один раз в конце плея и только если его кто-то уведомил. Так рестарт происходит ровно при реальном изменении, сохраняя идемпотентность (повторный прогон без изменений ничего не перезапускает). Безусловный рестарт этот принцип нарушает.
- В плейбуках и переменных есть пароли и ключи. Как хранить их, не открывая в репозитории?A)Держать в отдельном файле vars и не коммитить егоB)Шифровать их ansible-vault, в git лежит зашифрованноеC)Класть пароли в инвентарь открытым текстомD)Кодировать значения base64 перед коммитом
показать ответ и разбор
+B)Шифровать их ansible-vault, в git лежит зашифрованное// разбор: Секреты в Ansible шифруют ansible-vault: отдельные значения (!vault) или целые файлы переменных хранятся в git в зашифрованном виде, а при запуске расшифровываются по паролю/ключу (--ask-vault-pass, vault-id, интеграция с менеджером секретов). Так секреты остаются под контролем версий, но не открыты. Некоммитимые файлы теряются и рассинхронятся, а base64 — это кодировка, а не защита.
- Что такое плейбук (playbook) в Ansible?A)Отчёт о выполненных на серверах командахB)Список серверов с их адресами и группамиC)Готовый образ операционной системы для развёртыванияD)YAML-файл с задачами, которые применяют к указанным хостам
показать ответ и разбор
+D)YAML-файл с задачами, которые применяют к указанным хостам// разбор: Плейбук описывает желаемое состояние набором задач: поставить пакет, положить конфиг, запустить сервис. Список серверов лежит отдельно, в инвентаре — так один и тот же плейбук применяют к разным группам хостов.
дальше
Теорию прочитали. Навык ставится повторением
В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, лимит только на количество вопросов в день.