Tasks и handlers

Тема дорожной карты · Ansible

Задачи — это отдельные единицы работы в play Ansible: каждая задача вызывает модуль с конкретными аргументами и выполняется по порядку на каждом целевом хосте. Handler — это особая категория задач, выполняемых только при явном срабатывании через директиву notify; они запускаются один раз в конце play независимо от того, сколько задач их уведомило. Классический пример — задача обновления конфигурационного файла, уведомляющая handler Restart nginx: если файл конфигурации изменился (задача сообщает changed), handler срабатывает и перезапускает службу; если файл уже был правильным (задача сообщает ok), handler не вызывается, предотвращая ненужные перезапуски службы. Несколько задач могут уведомлять один и тот же handler, а handler выполняются в том порядке, в котором они определены в секции handlers:, а не в порядке их уведомления — важное отличие, когда порядок handler имеет значение для зависимостей служб.

Как это работает

Tasks и handlers — стандартная единица: YAML-файл со списком play; у каждого play — hosts, tasks, опционально pre_tasks/post_tasks/handlers/vars/roles. Задачи бегут последовательно per host; handlers — в конце play, только при триггере (notify). Strategy управляет параллелизмом: linear (дефолт — ждёт медленный), free (каждый хост так быстро, как может). Tags позволяют гонять подмножества (--tags backup); --start-at-task возобновляет после сбоя.

Когда применять

Всегда оборачивайте связанные операции в плейбук — даже если начинаете с одной задачи, растёт. pre_tasks — для setup, который должен идти первым; handlers — для идиомы "перезапустить X, если конфиг изменился"; tags — для частичных запусков. serial: 1 или serial: 25% — для постепенной выкатки (canary). Тестируйте --check --diff в CI против staging-inventory.

Типичные ошибки

Ловушки Tasks и handlers: длинные плейбуки без tags (нужно гонять всё для теста одной секции); ignore_errors: true повсюду (тихие сбои); нет block + rescue + always для error handling; баги отступов YAML (используйте линтер — ansible-lint); become: true на уровне play, когда нужен root только для одной задачи.

Связанные понятия

Полезные ресурсы