Оповещение, которое приходит только по e-mail, — это инцидент без ответственного. Интеграция Zabbix и GLPI нужна, чтобы превращать каждую обнаруженную проблему в отслеживаемую заявку — с номером, ответственным, категорией, приоритетом и SLA — и автоматически закрывать её, когда Zabbix подтверждает восстановление. Секрет не в том, чтобы «создать заявку», а в том, чтобы не создать сорок.
Что должна обеспечивать интеграция
Мост Zabbix → GLPI, выдерживающий продуктив, должен давать четыре гарантии, а не просто «отправлять заявку»:
- Идемпотентность: одна проблема порождает одну заявку, а не по одной на каждый шаг эскалации.
- Корреляция проблемы и восстановления: событие recovery должно найти и закрыть именно ту заявку, которую открыло.
- Сопоставление серьёзности: серьёзность в Zabbix последовательно превращается в приоритет GLPI, а не остаётся на усмотрение каждого аналитика.
- Достаточный контекст: хост, IP, триггер, время и сообщение в теле, чтобы аналитик мог действовать, не открывая Zabbix.
Архитектура: где webhook превращается в заявку
Zabbix срабатывает через Action; Action выполняет медиа-операцию типа Webhook; Webhook — это встроенный в Zabbix скрипт на JavaScript, который делает POST на конечную точку на стороне GLPI. На стороне GLPI мы используем приёмник модуля Automations, который проверяет подпись HMAC, применяет карту полей и создаёт (или закрывает) заявку. Мы избегаем прямого вызова REST API GLPI из Zabbix, потому что каждый вызов требовал бы пары app-token/user-token и пары initSession/killSession — при лавине оповещений это перегружает API и вдобавок исчерпывает сессии.
Артефакт: Media Type webhook в Zabbix
Параметры сопоставляют макросы события; скрипт собирает payload и обрабатывает HTTP-код. Проблема и восстановление используют один и тот же Media Type — их различает поле event_value (1 = проблема, 0 = восстановление):
// Zabbix -> Media type -> Webhook -> Parametros
// endpoint = https://glpi.cliente.com/plugins/nextool/automations/webhook/zabbix
// event_id = {EVENT.ID} // estavel no par problema/recovery
// event_value = {EVENT.VALUE} // 1 = problema, 0 = recuperacao
// host_name = {HOST.NAME}
// host_ip = {HOST.IP}
// trigger_name = {TRIGGER.NAME}
// severity = {TRIGGER.SEVERITY}
// occurred = {EVENT.DATE} {EVENT.TIME}
// message = {ALERT.MESSAGE}
// hmac = {$NEXTOOL_HMAC} // macro secreta, nunca no corpo do alerta
var p = JSON.parse(value);
var req = new HttpRequest();
req.addHeader('Content-Type: application/json');
req.addHeader('X-Nextool-Signature: ' + p.hmac);
var payload = JSON.stringify({
event_id: p.event_id,
recovery: p.event_value === '0',
host: p.host_name,
host_ip: p.host_ip,
trigger: p.trigger_name,
severity: p.severity,
occurred: p.occurred,
message: p.message
});
var resp = req.post(p.endpoint, payload);
var code = req.getStatus();
if (code < 200 || code >= 300) {
Zabbix.log(3, '[nextool] falha HTTP ' + code + ': ' + resp);
throw 'Envio ao GLPI falhou: HTTP ' + code;
}
return resp;
Карта серьёзности Zabbix → приоритет GLPI
В Zabbix шесть уровней серьёзности, в GLPI — пять приоритетов. Мы фиксируем карту в приёмнике, чтобы не оставлять это на усмотрение каждого аналитика:
| Серьёзность Zabbix | Приоритет GLPI | Становится заявкой? |
|---|---|---|
| Not classified / Information | - | Нет (только запись) |
| Warning | Низкий | Да |
| Average | Средний | Да |
| High | Высокий | Да |
| Disaster | Очень высокий | Да + уведомление дежурной смены |
Дедупликация и автоматическое закрытие
Именно это отличает игрушечную интеграцию от той, что выдерживает продуктив. При создании заявки приёмник записывает tickets_id GLPI как тег события в Zabbix (или в таблицу корреляции с индексом по event_id). Когда Zabbix отправляет recovery с тем же event_id, приёмник находит эту заявку и добавляет комментарий о восстановлении — или закрывает её, в зависимости от политики клиента. Без этого ключа recovery не знает, какую из заявок закрыть, и у вас копятся открытые заявки по уже решённым проблемам.
Типичные ошибки, которые мы исправляем при сопровождении
При сопровождении самый частый инцидент — не оповещение, которое не стало заявкой, а оповещение, которое стало сорока заявками. Интерфейс, «моргавший» (flapping) в 3 часа ночи, создал десятки одинаковых заявок, потому что Action срабатывал на каждом шаге эскалации, а приёмник не выполнял дедупликацию. Исправление двустороннее: в Zabbix — зависимость триггеров, гистерезис в выражении восстановления и медиа-операция только на первом шаге; в GLPI — идемпотентность по event_id. Ещё две повторяющиеся ошибки: передавать категорию заявки свободным текстом (GLPI ожидает числовой itilcategories_id — новый текст не совпадает, и заявка остаётся без категории) и помещать секрет HMAC в тело оповещения вместо защищённого макроса, такого как {$NEXTOOL_HMAC}.
Сравнение способов интеграции
| Способ | Без кода? | Дедупликация/recovery | Когда использовать |
|---|---|---|---|
| Модуль Automations (приёмник) | Да (карта через JSONPath) | Встроенная, по event_id | Стандарт для большинства клиентов |
| REST API GLPI напрямую | Нет | Реализуете вы | Без модуля; немного хостов |
| Внешний скрипт (Python/Bash) | Нет | Реализуете и поддерживаете вы | Нестандартные бизнес-правила |
Если у вас уже работает Zabbix, но оповещения умирают в почтовом ящике, который никто не читает, NexTool внедрит этот мост с модулем Automations и будет поддерживать правила в актуальном состоянии в рамках сопровождения — триггеры, карту серьёзности и политику закрытия. Узнайте о модуле Automations.
Проверено командой NexTool Solutions.