Прямой ответ
Alert fatigue — состояние, когда команда перестаёт реагировать на уведомления (200 сообщений в день → канал на mute → реальный инцидент пропущен среди шума — цена fatigue — не раздражение, а пропущенные инциденты и выгорание дежурных (oncall — SRE-позиция — «алерт, на который не отреагировали» — хуже отсутствия алерта: ложное чувство защищённости); источники шума (по убыванию вреда): (1) не-actionable алерты («CPU 80%» — всегда 80% вечером — никто не действует — алерт без действия = шум by definition — критерий Google SRE: страница → действие, иначе — дашборд/тикет — алерт-дизайн); (2) дубли и лавины (один упавший сервис → 12 алертов (поды/БД/очередь/health-чеки — каскад — 12 сообщений об одной причине — группировка Alertmanager (group_by: [alertname, service] — 12 в одно — Alertmanager) и inhibition (правила подавления: «cluster down — молчим о подах этого кластера» — inhibit_rules — корневая причина глушит производные — каскад схлопывается — метрики-иерархия); (3) flapping (порог на границе значения — алерт вкл/выкл каждые 2 минуты — resolved-firing-resolved — решение: for: период (5–15 минут стабильности — метрики-базлайн), multiwindow-условия (SLO-паттерн — 1h+5m — шум отсеян), гистерезис-пороги (срабатывание 85%, recovery 75% — «между порогами — тишина» — Alertmanager не умеет сам — правило-конструкция или VM-флаги (VM); (4) повторы без эскалации (repeat_interval каждый час до починки — 8 одинаковых сообщений — «мы помним» — repeat 4h+ для page, resolved обязателен — Grafana-настройка); дедупликация по слоям: правило (одно условие — один алерт — дубли правил из разных эпох — инвентаризация — техдолг), Alertmanager (grouping+inhibition+silence — настройка), канал (Slack-треды/бот-агрегатор — «12 сообщений» в один тред — интеграции); процесс-лечение (техника без ритуала умирает): еженедельный обзор (10 минут: топ-алертов по срабатываниям — каждый — вопрос «действие было?» — нет → тюнинг/удаление/в тикеты — техдолг-ритуал), метрика здоровья алертинга (actionable ratio — доля срабатываний с действием — цель: page >80%, ticket >50% — дашборд алертинга (Grafana — «алертинг сам под наблюдением» — healthcheck), правило двух ложных (ложное ×2 — правка в спринте — incident-практика), постмортем-триггер (пропущенный инцидент → почему мониторинг молчал/кричал не туда — runbook); severity-контракт (главная организационная мера): critical/page — будит и требует немедленного действия (единицы в неделю — иначе не page), warning/ticket — рабочая очередь (утро — oncall-дизайн), info — дашборд (не уведомляет вовсе) — «всё critical» — главная причина fatigue — пересортировка — 80% эффекта (сценарий ниже — severity-дисциплина).
Практика: измерение шума и чистка
Диагностика (день): выгрузка срабатываний за месяц (Alertmanager API/Grafana state history — таблица: алерт × срабатывания × действия (структура-анализ — «топ-20 алертов дают 70% сообщений» — Парето шума — метрики-анализ); классификация каждого из топ-20: ложный (условие/порог — тюнинг — базлайн), верный-но-не-actionable (симптом без действия — в дашборд/тикет — или переписать на действие — «диск 75%» → «диск кончится через 3 дня по тренду» — ёмкость-прогноз — прогнозный алерт действеннее порогового), верный-и-actionable (оставить — оптимизировать доставку — группировка/треды), дубль (консолидация — ревью); чистка (спринт): удаление/слияние мёртвых, пересортировка severity (page только actionable — контракт), группировка/inhibition (Alertmanager — каскады), for/гистерезис на flapping, repeat_interval-разрежение; закрепление: alert-ревью в ревью-чеклисте (новый алерт — «какое действие при срабатывании?» — без ответа — не мёрж — тесты-алертов), еженедельный ритуал (календарь — 10 минут — техдолг), метрика actionable ratio (дашборд — тренд вниз — разбор — SLO алертинга — «у алертинга тоже SLO» — SRE); инструменты-помощники: Grafana Alerting-аналитика (state history — срабатывания по правилам — Grafana), amtool (конфиг-аудит — маршруты/группы — Alertmanager), alert-аннотации в инцидент-трекер (Jira/Linear-интеграция (вебхуки) — «алерт → тикет → действие зафиксировано» — actionable ratio считается честно — метрики-качество).
Практический сценарий: oncall-выгорание → 2 страницы в неделю
Контекст: команда 6 человек, ротация oncall по неделе; симптом: дежурный месяца игнорировал канал (300+ сообщений/день — «всё равно ложные»), реальный инцидент (БД-блокировки (блокировки)) обнаружил пользователь через 40 минут — разбор показал: алерт БД сработал на 2-й минуте — утонул в 15 сообщениях деплой-шума (incident — «алертинг не подвёл — подвёл канал»); лечение (2 спринта): (1) аудит (месяц срабатываний: 9 400 уведомлений, топ-5 источников — 71%: k8s pod-crashloop (840 — деплой-окна без silence — деплой-шум), «CPU > 70%» (2 100 — порог из 2019 — никогда не actionable), disk-75% (1 300 — всегда 75% — ёмкость), дубли health-чеков (1 500 — три системы чекают одно), flapping memory-алерта (900 — resolved-firing-качели); (2) действия: авто-silence деплой-окон из CI (деплой → silence 15 мин по лейблу deploy (CI — вебхук — 840→0), CPU-алерт — удаление (заменён прогнозом «trend → capacity за 3 дня» — actionable — ёмкость), disk — порог 85%+прогноз, health-дубли — консолидация в один (ревью), memory — for: 10m + гистерезис (flapping умер), группировка каскадов + inhibition (pod down глушит его чеки — Alertmanager); (3) severity-пересортировка (page: 6 правил (SLO-burn (SLO), БД-блокировки/диск-критично/платёжка-ошибки — только «бросай всё»; ticket: 23 (утренняя очередь — oncall); дашборд: 40+ (без уведомлений — Grafana); (4) ритуалы (еженедельный alert-обзор, actionable ratio на дашборде (метрики), правило двух ложных — процесс); результаты месяца: 9 400 → 310 уведомлений (−97%), page — 7 за месяц (все с действием — actionable 100%), время реакции на инциденты 40 мин → 4 мин (page-канал тихий — каждое сообщение — событие — «тишина = доверие» — SRE), oncall-выгорание снято (ротация снова добровольная — ретроспектива — команда-культура); вывод: fatigue лечится не «ещё одним каналом», а вычитанием (удаление не-actionable — главная операция — техдолг) + контрактом severity — алертинг-гигиена как процесс — алерт-зрелость.
FAQ
Как понять, что у команды alert fatigue? Маркеры: канал алертов на mute/«прочитано» массово (Slack-статистика — сообщения без реакций), инциденты обнаруживаются пользователями раньше мониторинга (incident-лог — «кто первый заметил» — ответ «клиент» — диагноз), дежурные меняют правила молча (silence на всё/выключение уведомлений — крик о помощи — oncall), 100+ уведомлений в день на команду (эмпирика SRE: page-поток единицы в неделю на дежурного — SRE-нормы), actionable ratio <50% (измерение — раздел выше — цифра, не ощущение — метрики); проверка-эксперимент: «пропустите тестовый инцидент» (chaos — инъекция в staging с алертами — отреагировал ли кто за 5 минут — «алерты работают, команда нет» — fatigue подтверждён); следствие-ловушка: «добавим алертов» (симптом — пропустили — лечение — ещё шум — обратный эффект — вычитание — сценарий выше — алерт-дизайн).
Как правильно группировать и подавлять каскадные алерты?
group_by — по причине, не по следствию ([alertname, service] — 20 подов сервиса — одно сообщение со списком (Alertmanager — group_wait 30s/group_interval 5m — «подождать собратьев» — баланс задержки и полноты — настройка); inhibition (корневое глушит производное: правило «alertname=ClusterDown → inhibit всё с этим cluster» — matchers по лейблам — k8s-каскады — нода легла — поды не шумят), зависимость в аннотациях («причина: X» в сообщении производного — дежурный видит связь — runbook); границы: не глушить другие сервисы (ингибиция внутри домена причины — «БД легла» не должна глушить алерты платёжки — она-то как раз важна — микросервисы — inhibition-правила — точечно — ревью — ревью); тестирование каскадов: chaos-сценарий «убить ноду» (chaos — проверить: одно групповое сообщение, inhibit сработал, корневой алерт виден — «группировка проверена боем» — тесты); Grafana Alerting — та же модель (policies/nesting — Grafana — семантика Alertmanager — переносимо).
Что делать с алертами, которые срабатывают по делу, но действовать некому? Класс «3 часа ночи, диск 82%» (правда — но действие утром — page не нужен): деградация severity (page → ticket с утренней очередью (oncall-процесс — «срочность ≠ важность» — действие отложенное — канал тихий), прогнозность (порог 82% → тренд-прогноз «кончится через N дней» (ёмкость — actionable планированием, не ночью — планирование), автоматизация действия (диск → авто-очистка логов/расширение тома (k8s-storage — алерт «автоматика сработала, проверьте» — info-уровень — graceful); критерий: page — только «действие немедленно предотвращает ущерб» (SRE-позиция); «дежурный всё равно посмотрит утром» — да, но ticket-очередью, не ночным пушем — сон дежурного — ресурс (oncall — выгорание — сценарий выше); исключение: бизнес-часы критичны (платёжка ночью — page — SLO — «ущерб растёт с каждой минутой» — критерий не время, а скорость ущерба — incident).
Как поддерживать алерт-систему здоровой в долгосроке? Ритуалы: еженедельный alert-обзор (топ срабатываний → действия — процесс), постмортем-обязательство (инцидент → алерт добавлен/поправлен или обоснование — runbook), квартальная инвентаризация (все правила — «актуально?» — мёртвые — удаление — техдолг — зависимости-аналогия); метрики алертинга: actionable ratio (page >80% — метрики), MTTA/MTTD (incident-метрики — время обнаружения — тренд), число page на дежурство (норма — единицы — SRE) — дашборд алертинга (Grafana — «система предупреждения под мониторингом» — healthcheck); инженерная гигиена: алерты как код (git+ревью+тесты — Grafana Alerting/recording rules — дрейф исключён — IaC), новые алерты только с runbook-ссылкой (runbook — «алерт без инструкции» — не мёрж — ревью), chaos-проверки раз в квартал (chaos — «алерт сработал, группа собралась, inhibition сработал» — проверка боем — тесты); культура: алерт-шум — техдолг команды, не «особенность жизни» — техдолг-управление — «терпим шум» — путь к пропущенному P0 — SRE-зрелость.
Источники: документация Alertmanager, Google SRE Workbook (being on-call), SRE Book (monitoring) — ссылки в шапке.