Найти в Дзене
Infra as Code по-русски

Handlers в Ansible: умный перезапуск сервисов

Анотация Если у тебя в плейбуках после каждой правки конфига идёт ещё одна таска service: restarted, а nginx в логах дёргается по десять раз за запуск — значит, пора познакомиться с handlers. В этой статье разберём, что такое handler, как notify связывает его с тасками и почему сервис перезапускается ровно один раз, даже если его «дёрнули» сразу несколько задач. Зачем вообще нужны handlers Типичная история: у тебя есть несколько задач, которые правят конфиги nginx; после каждой ты на всякий случай делаешь service: name=nginx state=restarted; если меняется два файла — nginx перезапускается два раза подряд. Это лишняя нагрузка, лишние риски и просто неаккуратно.
Handlers помогают сделать перезапуск сервисов «умным»: только когда реально что-то поменялось, и один раз за запуск плейбука. Что такое handler в Ansible Handler — это такая же задача, как обычная, но живёт она в отдельном блоке handlers: и выполняется только по сигналу (notify). Простейший пример: Что здесь происходит: в task
Оглавление

Анотация

Если у тебя в плейбуках после каждой правки конфига идёт ещё одна таска service: restarted, а nginx в логах дёргается по десять раз за запуск — значит, пора познакомиться с handlers. В этой статье разберём, что такое handler, как notify связывает его с тасками и почему сервис перезапускается ровно один раз, даже если его «дёрнули» сразу несколько задач.

Зачем вообще нужны handlers

Типичная история:

  • у тебя есть несколько задач, которые правят конфиги nginx;
  • после каждой ты на всякий случай делаешь service: name=nginx state=restarted;
  • если меняется два файла — nginx перезапускается два раза подряд.

Это лишняя нагрузка, лишние риски и просто неаккуратно.

Handlers помогают сделать перезапуск сервисов «умным»: только когда реально что-то поменялось, и один раз за запуск плейбука.

Что такое handler в Ansible

Handler — это такая же задача, как обычная, но живёт она в отдельном блоке handlers: и выполняется только по сигналу (notify).

Простейший пример:

-2

Что здесь происходит:

  • в tasks мы кладём шаблон конфига;
  • в этой же таске пишем notify: Restart nginx;
  • в handlers описываем задачу с таким же name, которая перезапускает nginx.

Если файл реально изменился — Ansible «запомнит», что нужно вызвать handler Restart nginx.

Если файл такой же, как был, — handler не сработает вообще.

Как notify связывает таску и handler

Всё держится на одном простом правиле:

Название в notify должно совпадать с name у handler.
-3

Важно понять две вещи:

  1. Handler вызывается только при изменении.

    Модуль template сам определяет, изменился ли файл. Если да — таска в статусе
    changed, и notify срабатывает. Если нет — статус ok, handler не нужен.
  2. Можно нотифать несколько handlers.

    notify может быть списком:
Тогда сработают оба handler (но тоже по одному разу каждый).
Тогда сработают оба handler (но тоже по одному разу каждый).

Почему handler вызывается один раз, даже если его нотифнули несколько тасок

Рассмотрим пример:

-5

Если обе задачи что-то изменили, то логика Ansible такая:

  1. Первая таска изменила файл → ставим Restart nginx в очередь handlers.
  2. Вторая таска тоже изменила файл → handler уже в очереди, добавлять второй раз не нужно.
  3. В конце плейбука Ansible запускает каждый handler ровно один раз.

Итог: два изменённых конфига → один аккуратный перезапуск nginx.

Так меньше рисков поймать ошибки на старте, меньше «дёрганий» сервиса и логика плейбуков становится чище.

Пошаговый пример: template + notify + handler

Шаг 1. Готовим шаблон конфига

Пусть у нас есть простой шаблон templates/nginx.conf.j2:

-6

Шаг 2. Пишем таску с notify

-7

Если в шаблоне или переменных что-то поменялось — файл на сервере тоже поменяется, таска станет changed, и handler поставится в очередь.

Шаг 3. Описываем handler перезапуска

-8

Теперь при изменении конфига Ansible:

  1. обновит файл;
  2. в конце плейбука выполнит handler Restart nginx.

Если запустить плейбук второй раз без изменений — увидишь:

  • таска template в статусе ok;
  • handler даже не будет упомянут — ему нечего делать.

Типичные ошибки и быстрые фиксы

1. Опечатка в имени handler

-9

и

-10

Для Ansible это два разных имени.

Handler просто не найдётся и не выполнится.

Как фиксить:

держать единый стиль, лучше копировать
name целиком, а не печатать с нуля.

2. Handler не срабатывает, потому что таска всегда ok

Если ты вручную переопределил changed_when: false, handler никогда не вызовется:

-11

Ansible думает, что изменений нет → и не вызывает handler.

Как фиксить:

использовать
changed_when только осознанно. Если ты говоришь Ansible «ничего не изменилось», он тебе верит.

3. Перезапуск нужен раньше конца плейбука

По умолчанию handlers выполняются в конце плейбука (или роли).

Если тебе нужно перезапустить сервис сразу после серии задач — используй:

-12

Пример:

-13

Тут nginx перезапустится до health-check.

4. Вместо restart иногда лучше reload

Перезапуск (state: restarted) полностью гасит сервис и поднимает его заново.

Иногда достаточно reloaded, чтобы перечитать конфиги без полной остановки.

-14
-15

Почему это работает

  • Ansible чётко разделяет «обычные» таски и handlers: первые выполняются всегда, вторые — только по сигналу.
  • Модуль в таске (например, template) сам решает, было ли изменение. Это позволяет не перезапускать сервис без необходимости.
  • Все уведомления (notify) по одному и тому же имени складываются в очередь, но handler выполняется один раз — это экономит время и снижает риски.
  • Порядок «таскиnotifyhandlers в конце» делает сценарий предсказуемым и повторяемым: один запуск плейбука даёт один и тот же результат.

Что мы сделали в этой статье

  • Разобрали, что такое handler в Ansible и чем он отличается от обычной таски.
  • Посмотрели, как notify связывает задачи и handlers по имени.
  • Поняли, почему handler выполняется один раз, даже если его нотифнули несколько задач.
  • Собрали типичный паттерн: template → notify: Restart nginx → handler с service: state=restarted.
  • Разобрали несколько типичных ошибок и как их быстро исправить.

Сделать прямо сейчас (чеклист)

  1. Найди плейбук, где несколько задач правят конфиги одного сервиса и каждая сама его перезапускает.
  2. Вынеси перезапуск в handler в блоке handlers:
  3. В тасках вместо отдельных service поставь notify: Restart <service>
  4. Запусти плейбук два раза подряд и посмотри вывод: при втором запуске handler не должен выполняться.
  5. Для сервисов, где достаточно перечитать конфиг, замени restarted на reloaded.

CTA

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

Пиши в комментариях:

  • есть ли у тебя сейчас «лишние» перезапуски;
  • какой сервис ты хочешь «обложить» handlers в первую очередь.

    Можем вместе разобрать твой плейбук и превратить хаос перезапусков в аккуратную схему.