EDA в GA: переводим мониторинг Zabbix на автоматическое восстановление через AAP 2.4
Red Hat перевёл Event-Driven Ansible в GA в составе AAP 2.4. Описываем архитектуру интеграции с Zabbix: rulebook, decision environment и remediation-плейбук в продакшне.
Ansible Automation Platform 2.4 - Event-Driven Ansible переведён в GA, встроенный Private Automation Hub
Red Hat на этой неделе официально объявила о выходе Ansible Automation Platform 2.4 - точнее, о переводе Event-Driven Ansible из технического превью в статус GA. Для тех, кто уже работает с EDA, это прежде всего сигнал: поддерживаемый продукт с нормальным SLA от вендора, можно идти к заказчикам без оговорок. Второе значимое изменение - встроенный Private Automation Hub, который закрывает давнюю боль с дистрибуцией коллекций в изолированных контурах.
Мы с EDA работаем не первый раз, но статус GA изменил разговор с несколькими заказчиками: то, что раньше шло как "попробуем", теперь переходит в категорию штатного инструментария. Сейчас на одном из проектов мы строим полноценную схему автоматического восстановления инцидентов через EDA и Zabbix. Архитектура сложилась - делимся.
Что изменилось с выходом GA
В первую очередь - стабильность eda-server при длительной работе. В превью у нас бывало, что активация тихо останавливалась после нескольких дней работы, и это обнаруживалось не сразу. С GA-версией ситуация другая: healthcheck-контроллер реально работает, и если процесс падает - его перезапускают автоматически с записью в историю. Это первая базовая вещь, без которой продакшн невозможен.
Private Automation Hub прямо в поставке AAP 2.4 - важно для изолированных сред. Раньше нужно было ставить его отдельно или изобретать другие способы доставки коллекций в air-gapped контур. Теперь Hub входит в инсталлятор, и Decision Environment для EDA можно строить на базе образов из локального реестра без лишних движений.
UI для EDA подтянулся, хотя отлаживать новый rulebook всё равно удобнее через ansible-rulebook --verbose локально. Интерфейс хорош для наблюдения за работающей активацией, не для написания правил.
Архитектура: Zabbix - EDA - AWX Controller
Схема, которую мы развернули на проекте:
flowchart LR
Z["Zabbix Server"] -->|webhook action| EDA["EDA Controller\nactivation"]
EDA -->|rulebook match| AWX["AWX / Controller"]
AWX -->|job template| HOST["Управляемый хост"]
AWX -->|ack + note| Z
Zabbix настраивается на отправку webhook при срабатывании триггера. Это стандартная Media Type в Zabbix - ничего кастомного, просто HTTP POST с JSON-телом на endpoint EDA. EDA слушает на выделенном порту через ansible.eda.webhook source, разбирает событие по условиям rulebook и при совпадении запускает job template в AWX Controller. Плейбук отрабатывает на хосте, AWX возвращает статус обратно - через Zabbix API подтверждает триггер и оставляет заметку в событии.
Ничего принципиально нового - схема проверена ещё в 2023 году на SIEM-сценариях. Но здесь несколько конкретных решений, которые стоит зафиксировать.
Rulebook: как устроены правила
Главный принцип - не все триггеры Zabbix должны запускать автоматику. Мы используем кастомный тег eda_action на стороне Zabbix: триггер без этого тега EDA игнорирует полностью.
sources:
- ansible.eda.webhook:
host: 0.0.0.0
port: 5010
rules:
- name: Remediate tagged service problem
condition: >
event.payload.trigger.status == "PROBLEM" and
event.payload.trigger.severity in ["Average", "High", "Disaster"] and
event.payload.trigger.tags.eda_action is defined
throttle:
once_within: 10 minutes
group_by_attributes:
- event.payload.host.host
- event.payload.trigger.id
action:
run_job_template:
name: "remediate-{{ event.payload.trigger.tags.eda_action }}"
organization: "Default"
job_args:
extra_vars:
zabbix_host: "{{ event.payload.host.host }}"
trigger_id: "{{ event.payload.trigger.id }}"
event_id: "{{ event.payload.event.id }}"
Тег eda_action содержит имя суффикса job template. Если тег eda_action: nginx-restart, запускается template remediate-nginx-restart. Это позволяет добавлять новые сценарии без правки rulebook: достаточно создать job template в AWX и проставить тег на триггер в Zabbix.
throttle с группировкой по хосту и ID триггера - обязательная вещь. Zabbix при продолжающейся проблеме может слать повторные уведомления каждые несколько минут. Без throttle плейбук запустится несколько раз подряд на один и тот же инцидент.
Decision Environment: что туда кладём
Decision Environment - это контейнерный образ с Python-зависимостями и коллекциями, которые нужны rulebook-у. Минимальный набор для нашего сценария: ansible.eda и никаких лишних коллекций. Всё остальное - в execution environment AWX, где уже запускается плейбук.
Образ собираем через ansible-builder и кладём в Private Automation Hub. Decision Environment версионирован отдельно от execution environment - это важно: изменение rulebook не должно требовать пересборки всего EE.
Remediation-плейбук: принципы
Несколько правил, к которым мы пришли на практике:
Плейбук должен быть идемпотентным без оговорок. Автоматика запускает его без человека. Если сервис уже поднялся сам к моменту запуска плейбука - systemd: state: started просто проверит это и уйдёт без изменений. Никаких shell-команд типа systemctl restart через command - только модули Ansible с встроенной идемпотентностью.
Плейбук завершает работу с явным статусом. В конце мы всегда вызываем Zabbix API: либо подтверждаем событие и оставляем заметку «восстановлено автоматически», либо оставляем событие открытым с заметкой «автоматика не справилась - нужен человек». Второй сценарий не менее важен первого: дежурный должен видеть, что автоматика пробовала, что именно, и почему не сработало.
Ограничение --limit по хосту. Job template настроен с ask_limit_on_launch: false и лимит передаётся через extra_vars. Плейбук физически не может задеть хосты за пределами тех, которые передал EDA.
Первые результаты
Схема работает в продакшне несколько недель - пока на трёх сценариях: рестарт упавшего прикладного сервиса, очистка заполнившегося временного раздела под логи, перезапуск агента мониторинга при потере связи с Zabbix-прокси.
Из наблюдений: throttle спас нас несколько раз - без него при одном реальном инциденте ушло бы с десяток параллельных запусков. Случай, когда плейбук отработал, но сервис поднялся и снова упал через минуту - throttle корректно пропустил второе событие, дежурный получил уведомление и разобрался вручную. Именно так и должно работать.
Managed-сопровождение с EDA - это не «автоматика вместо дежурного». Это смещение его работы: меньше рутинных подъёмов ночью по известным сценариям, больше разбора нетривиальных инцидентов, куда автоматика не дотягивается. По крайней мере, так работает у нас сейчас.