Безопасный прод-запуск
Dry-run через --check и --diff, точечный --limit, теги, и постепенный rolling update через serial. Как катить изменения, не уронив прод.
Прежде чем нажать Enter
Запустить playbook на 50 прод-серверах вслепую рискованно. Один неверный шаблон, одна лишняя задача — и сервис лежит у всех сразу.
Ansible даёт набор инструментов, чтобы смотреть перед прыжком и ограничивать радиус взрыва. В этом уроке разберём эти инструменты.
--check: dry-run
Флаг --check говорит Ansible: иди по всем задачам, но ничего не меняй.
Вместо реальных действий — отчёт о том, что изменилось бы.
ansible-playbook -i inventory.ini site.yml --check
Это полезно для первичного "а что вообще поменяется?" перед реальным прогоном.
Важная оговорка: некоторые задачи в check-режиме дают неточный результат. Например, если первая задача должна была создать файл, а вторая читает из него - вторая в dry-run увидит, что файла нет, и может репортить неверно.
Управлять поведением конкретной задачи можно через check_mode. Ключ
принудительно фиксирует режим для этой задачи и перебивает то, что
пришло из командной строки:
- name: сбор данных, выполняется по-настоящему даже при --check
command: /usr/local/bin/healthcheck.sh
check_mode: false
- name: только отчёт, никогда ничего не меняет
ansible.builtin.lineinfile:
path: /etc/motd
line: "managed by ansible"
check_mode: true
Тут легко ошибиться в чтении. check_mode: true не значит «задача
только для dry-run и в обычном прогоне пропускается». Задача выполняется
всегда, но всегда в check-режиме: Ansible посчитает и покажет, что
изменилось бы, и ничего не тронет. Обычный ansible-playbook site.yml
её выполнит — просто вхолостую.
Обратный ключ check_mode: false нужен как раз для случая из абзаца
выше: задача, результат которой читают следующие. Такой сбор данных
пускают по-настоящему всегда, иначе весь остальной dry-run посчитает
чушь. Ставить его на что-то, что реально меняет систему, нельзя —
--check перестанет быть безопасным.
--diff: построчный diff
--diff показывает, как изменится содержимое файлов и шаблонов — до и после,
в формате unified diff.
ansible-playbook -i inventory.ini site.yml --diff
Работает и без --check — тогда изменения реальные, но ты видишь их в выводе.
Стандартная связка перед деплоем:
ansible-playbook -i inventory.ini site.yml --check --diff
Сначала смотришь, что изменится, убеждаешься, что всё правильно — потом
запускаешь без --check.
--limit: точечный запуск
По умолчанию play выполняется на всех хостах из hosts:. Флаг --limit
(или -l) сужает до конкретного хоста или группы:
# только один хост
ansible-playbook -i inventory.ini site.yml --limit web-1
# только группа
ansible-playbook -i inventory.ini site.yml --limit webservers
# комбинация: сначала dry-run на одном
ansible-playbook -i inventory.ini site.yml --limit web-1 --check --diff
Удобный сценарий: прогнать --check --diff на одном хосте, убедиться, что
шаблон рендерится правильно, и только потом запускать на всей группе.
Теги
Большой playbook часто не нужен целиком — нужна только часть. Теги позволяют помечать задачи и запускать только нужные.
Тег вешается на задачу, блок или роль:
- name: Deploy application
copy:
src: app.tar.gz
dest: /opt/app/
tags:
- deploy
- name: Run DB migrations
command: /opt/app/migrate.sh
tags:
- deploy
- migrations
- name: Restart nginx
service:
name: nginx
state: restarted
tags:
- nginx
Запуск только задач с тегом:
ansible-playbook -i inventory.ini site.yml --tags deploy
# или сокращённо
ansible-playbook -i inventory.ini site.yml -t deploy
Пропустить задачи с тегом:
ansible-playbook -i inventory.ini site.yml --skip-tags slow
Два специальных тега:
always— задача выполняется всегда, даже если запущено--tags что-то-другоеnever— задача пропускается всегда, если только явно не указать--tags never
--start-at-task: продолжить с места падения
Если playbook упал на середине и ты уже починил проблему, можно не гнать всё с начала:
ansible-playbook -i inventory.ini site.yml --start-at-task "Deploy application"
Ansible пропустит задачи до указанной и начнёт с неё. Имя задачи — точное
совпадение с полем name:.
serial: rolling update
По умолчанию Ansible работает со всеми хостами плея одновременно,
ограничиваясь только количеством параллельных соединений (--forks,
умолчание 5). То есть при 50 хостах он продвигает задачи через все 50
батчами по 5 за раз, но play "завершается", только когда все 50 прошли.
serial: меняет это: хосты разбиваются на пакеты, и play полностью
завершается на одном пакете перед тем как начать следующий.
- name: Rolling deploy
hosts: webservers
serial: 2
tasks:
- name: deploy app
# ...
С serial: 2 Ansible возьмёт 2 хоста, прогонит весь play, потом следующие 2,
и так до конца. Пока обновляются двое — остальные продолжают принимать трафик.
serial принимает:
- целое число:
serial: 1(по одному) - строку-процент:
serial: "25%"(четверть хостов за раз) - список для нарастающих батчей:
serial: [1, 5, "30%"]— сначала 1, потом 5, потом по 30% — удобно для постепенного раскатывания
Компаньон к serial — max_fail_percentage: если в батче упало больше
этого процента хостов, Ansible остановит раскатку не трогая остальные:
- name: Rolling deploy
hosts: webservers
serial: 2
max_fail_percentage: 50
tasks:
- name: deploy app
# ...
--forks vs serial
Частое смешение понятий:
--forks(илиforksвansible.cfg) — сколько SSH-соединений открывать одновременно в рамках текущего батча. По умолчанию 5. Влияет на скорость.serial— сколько хостов входит в один батч. Влияет на то, как много серверов могут быть "в процессе обновления" одновременно.
Простая аналогия: serial: 10 с --forks 5 — берём 10 хостов в батч,
но обрабатываем их параллельно по 5.
Реальный сценарий
Типичный безопасный деплой выглядит так:
- Dry-run на одном хосте — проверяешь, что шаблон правильный:
ansible-playbook -i inventory.ini site.yml --limit web-1 --check --diff
- Если всё нормально — катишь rolling update на все:
ansible-playbook -i inventory.ini site.yml
Если playbook настроен с serial: 2 и max_fail_percentage: 50, то при
падении двух хостов подряд раскатка остановится, не тронув оставшиеся.
Что важно запомнить
--check— dry-run; не меняет ничего, но некоторые задачи могут репортить неточно, если зависят от реального результата предыдущих--diff— построчный diff файлов и шаблонов; стандартная связка--check --diff--limit— ограничить запуск одним хостом или группой--tags/--skip-tags— запустить или пропустить часть задач по меткамserial— размер батча для rolling update; принимает число, процент или списокmax_fail_percentage— порог ошибок в батче для остановки раскатки--forks— параллелизм внутри батча, не размер батча
В следующем уроке — динамический inventory для облаков и коллекции Galaxy.
Самопроверка
Впишите команду / ключевую строку. Регистр и пробелы не важны.
Дрилл · вопросы как на собесе
Проверь себя без подсказок
Сформулируй ответ вслух или письменно, потом раскрой и честно отметь: знал или нет.
Playbook упал на хосте 47 из 200. Что должно произойти с остальными 153 и как настроить поведение явно (`any_errors_fatal`, `max_fail_percentage`, `serial`)?
ANS-028Что делает параметр `serial` и как через Ansible организовать честный rolling update с health-чеками?
ANS-020Performance: forks, pipelining, fact caching, async tasks — как выжать из Ansible на 1000+ хостов.
ANS-025`--check` и `--diff`: что они реально гарантируют, а что — нет?
ANS-026Прошли материал до конца? Отметьте урок пройденным.
Прогресс сохранён в этом браузере
Почистишь историю или откроешь с телефона, и отметки пропадут. Оставь почту, они переедут в аккаунт. Пароль придумывать не нужно.
Готово. теперь в аккаунте: прогресс виден с любого устройства. Мой прогресс