Новинка Виртуальный VDS сервер в Нидерландах от 390р
Выберите продукт

Alertmanager без боли: маршрутизация инцидентов, тишина на ночь и шаблоны алертов

Разбираем практическую конфигурацию Alertmanager: как группировать и маршрутизировать алерты по сервисам и сменам, включать тишину на ночь и выходные, писать шаблоны сообщений для чатов и почты, управлять инхибитами и повторной доставкой.
Alertmanager без боли: маршрутизация инцидентов, тишина на ночь и шаблоны алертов

Если вы уже ловили «шквал» уведомлений от мониторинга, значит пора привести в порядок Alertmanager. Сырые алерты из Prometheus полезны, но без продуманной маршрутизации, инхибитов, правил тишины и шаблонов они превращают дежурство в лотерею. В этом руководстве я разложу по полочкам: как построить дерево маршрутов, как включать «тишину» на ночь и как оформлять сообщения так, чтобы по ним действительно можно было быстро действовать.

Зачем трогать Alertmanager, если «и так работает»

Alertmanager — это сердце уведомлений в связке Prometheus → Alertmanager → получатели (почта, чат, тикеты, телефон). Ошибки в его настройке стоят дорого: дубли, ложные срабатывания, игнор важных инцидентов и выгоревший on-call. Качественная конфигурация решает сразу несколько задач:

  • снижает шум за счёт группировки и повторной доставки с интервалами;
  • направляет инциденты «кому надо» на основании лейблов (team, service, severity, environment);
  • глушит вторичные алерты, пока горит «корневой» (inhibit rules);
  • уважает жизнь: есть окна тишины ночью и по выходным;
  • даёт понятные, единообразные сообщения через шаблоны.

Минимальный каркас конфигурации

Базовая структура alertmanager.yml включает global, корневой route, список receivers, опциональные inhibit_rules и time_intervals. Ниже — пример, который можно взять за основу, а затем адаптировать под свою оргструктуру.

global:
  resolve_timeout: 5m

templates:
  - tpl/*.tmpl

route:
  group_by: ['alertname', 'cluster', 'service']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: 'noc'
  routes:
    - matchers:
        - 'severity="critical"'
      receiver: 'pager'
      continue: true
    - matchers:
        - 'team="payments"'
        - 'environment="prod"'
      receiver: 'payments'
      mute_time_intervals: ['night']
      repeat_interval: 2h
    - matchers:
        - 'environment="stage"'
      receiver: 'dev-chat'
      group_wait: 10s
      repeat_interval: 30m

inhibit_rules:
  - source_matchers:
      - 'severity="critical"'
    target_matchers:
      - 'severity=~"warning|info"'
    equal: ['cluster', 'service']

time_intervals:
  - name: 'night'
    time_intervals:
      - weekdays: ['monday:friday']
        times:
          - start_time: '22:00'
            end_time: '08:00'
      - weekdays: ['saturday', 'sunday']
        times:
          - start_time: '00:00'
            end_time: '24:00'

receivers:
  - name: 'noc'
    email_configs:
      - to: 'noc@example.local'
        send_resolved: true

  - name: 'pager'
    email_configs:
      - to: 'oncall@example.local'
        send_resolved: false

  - name: 'payments'
    slack_configs:
      - channel: '#payments-alerts'
        send_resolved: true
        title: '{{ template "msg.title" . }}'
        text: '{{ template "msg.body" . }}'

  - name: 'dev-chat'
    slack_configs:
      - channel: '#dev-alerts'
        send_resolved: true
        text: '{{ template "msg.body" . }}'

Ключевые моменты:

  • group_by и интервалы группировки избавляют от лавины однотипных сообщений при всплеске;
  • continue: true позволяет отправить критичный инцидент одновременно на пейджер и в общий канал;
  • mute_time_intervals отключает доставку для выбранной ветки ночью и в выходные (про это — ниже);
  • inhibit_rules «глушит» второстепенные алерты, если есть критический для тех же cluster и service.

Если вы только разворачиваете стек Prometheus и Alertmanager, удобнее всего держать его на отдельном VDS: так проще управлять портами, системными сервисами, бэкапами и обновлениями.

Консоль с amtool: проверка конфигурации и дерево маршрутов

Как правильно группировать и настраивать интервалы

Группировка — главный антишумовой механизм. В большинстве команд достаточно alertname + «контекст» сервиса, например cluster и service. Чем больше полей в group_by, тем больше уникальных групп и тем выше риск спама. Держите набор коротким и стабильным: поля должны присутствовать во всех алертах, которые пойдут по этой ветке.

Про интервалы:

  • group_wait — сколько подождать, прежде чем отправить первую сводку. 30–60 секунд помогают «собрать» волну;
  • group_interval — как часто присылать обновления по группе, пока она меняется. 5–10 минут обычно достаточно;
  • repeat_interval — как часто напоминать, если состояние не изменилось. Для critical логично 1–2 часа, для warning — 3–6 часов или больше.

Маршрутизация по лейблам: команда, сервис, среда, важность

Alertmanager не «угадывает», куда слать алерты — он смотрит только на лейблы. Значит, лейблы должны приходить из правил в Prometheus. Пример правила с понятной маркировкой:

groups:
- name: app
  rules:
  - alert: ApiHighErrorRate
    expr: sum(rate(http_requests_total{job="api",status=~"5.."}[5m]))
          / sum(rate(http_requests_total{job="api"}[5m])) > 0.05
    for: 10m
    labels:
      severity: warning
      team: payments
      service: api
      environment: prod
      runbook: wiki/alerts/api-errors
    annotations:
      summary: 'API 5xx > 5%'
      description: 'Доля 5xx по job=api превысила 5% за 10m'

Дальше в routes вы расписываете — критичное уходит на пейджер, предупреждения — в чат команды, стейджинг — в канал разработчиков, а всё остальное — в NOC. Поддерживайте единый словарь значений (severity, environment, team) — это избавляет от исключений в маршрутах. За примерами готовых правил посмотрите материал про готовые алерты для Node Exporter и Nginx в статье Prometheus: готовые метрики и алерты для Node и Nginx, а для проверки внешней доступности — гайд по Blackbox Exporter HTTP/TCP/ICMP проверки.

Тишина на ночь и выходные: time_intervals vs silences

Есть два рабочих подхода к «ночной тишине»:

  1. mute_time_intervals с предопределёнными интервалами — предпочтительно. Вы объявляете named-интервалы и ссылаетесь на них из нужных веток маршрутов. Это декларативно, видно в конфиге и не требует периодических задач.
  2. Silence — точечное «заглушение» для конкретных алертов/лейблов на период времени. Удобно для разовых работ, ночных релизов, миграций. Можно автоматизировать, но злоупотреблять не стоит.

Пример с time_intervals мы уже видели. Добавлю советы:

  • Определите часовой пояс один раз и используйте его последовательно. Если нужны разные — добавьте timezone на уровне интервала.
  • Не отключайте ночью critical инциденты, влияющие на пользователей. Лучше перенаправьте их в другой канал или сократите повторную доставку.
  • Суббота/воскресенье — частый источник «шторма» от фоновых задач. Вынесите их в отдельную ветку маршрута с интервалом тишины на выходные.

Silence: быстрые рецепты через amtool

amtool — консольная утилита для работы с Alertmanager. Предполагается, что настроена переменная окружения с адресом инстанса. Быстрые операции:

# Проверить конфигурацию Alertmanager
amtool check-config /etc/alertmanager/alertmanager.yml

# Посмотреть дерево маршрутов в удобном виде
amtool config routes

# Заглушить алерты по сервису api в проде на 8 часов
amtool silence add -l service=api -l environment=prod -d 8h -c "Ночное окно работ"

# Найти активные silences по сервису
amtool silence query service=api

# Завершить конкретный silence по ID
amtool silence expire 1234567-89ab-cdef-0123-456789abcdef

Лучшие практики для silences:

  • Всегда добавляйте понятный комментарий и автора (по возможности — с контактом).
  • Делайте точечные matchers, чтобы случайно не заглушить соседние сервисы.
  • Выбирайте минимально достаточную длительность. Лучше продлить, чем забыть снять.

Инхибиты: глушим вторичные алерты при корневой причине

Когда «лежит» база, вспыхивает десяток алертов: timeouts, 500 на API, деградация очередей. Инхибит-правила позволяют посылать только главный сигнал (например, critical), пока он активен, и молчать по warning/info с теми же ключевыми лейблами.

Что важно:

  • Поле equal должно включать общий контекст для исходного и целевого алертов (например, cluster и service), иначе вы задушите лишнее или наоборот — не задушите нужное.
  • Убедитесь, что «корневой» алерт действительно загорается раньше дочерних и имеет более высокий severity.
  • Тестируйте в тестовой ветке маршрута или на стенде: неправильный инхибит легко скрывает важные сигналы.
FastFox VDS
Облачный VDS-сервер
Виртуальные серверы с быстрым запуском и гибкой конфигурацией от 390₽ / мес
Доступные локации
Россия Нидерланды

Шаблоны сообщений: единый стиль и полезный контент

Встроенные шаблоны Alertmanager основаны на Go templates. Я рекомендую вынести оформление в отдельные файлы и подключать их через templates:. Так вы получите единый стиль во всех каналах и сможете легко менять формат.

# alertmanager.yml
templates:
  - tpl/*.tmpl

receivers:
  - name: 'payments'
    slack_configs:
      - channel: '#payments-alerts'
        title: '{{ template "msg.title" . }}'
        text: '{{ template "msg.body" . }}'
        send_resolved: true

Пример файла tpl/alert.tmpl с двумя блоками — заголовок и тело. Его можно переиспользовать в Slack, почте и других интеграциях.

{{ define "msg.title" }}
[{{ if eq .Status "firing" }}FIRING{{ else }}RESOLVED{{ end }}] {{ .CommonLabels.alertname }}
{{ end }}

{{ define "msg.body" }}
Severity: {{ .CommonLabels.severity }}
Service: {{ .CommonLabels.service }}
Environment: {{ .CommonLabels.environment }}
Count: {{ len .Alerts }}

{{ range .Alerts -}}
- {{ .Annotations.summary }}
  Labels: cluster={{ .Labels.cluster }}, instance={{ .Labels.instance }}
  StartsAt: {{ .StartsAt }}
{{- end }}

Runbook: {{ .CommonLabels.runbook }}
{{ end }}

Советы по шаблонам:

  • Используйте .CommonLabels и .CommonAnnotations для полей, совпадающих у всех алертов в группе, и отличия выводите в цикле range .Alerts.
  • Делайте компактные заголовки и подробное тело. В мобильных клиентах важно, чтобы заголовок был читаемым.
  • Не полагайтесь на поля, которые могут отсутствовать у части алертов. Проверяйте через условные выражения.

Группировка алертов и инхибит-правила в Alertmanager

Повторная доставка и «жизненный цикл» инцидента

repeat_interval — инструмент напоминаний. Для critical держите интервал короче (1–2 часа), для warning — длиннее. В критичных ветках стоит отключать send_resolved, если у вас есть тикет-система, которая фиксирует закрытие инцидента и не требует отдельного «RESOLVED» в чате. Но для командных каналов «RESOLVED» полезен — он завершает историю.

Не забывайте, что Alertmanager дедуплицирует одинаковые алерты. Если вы часто меняете лейблы «на лету» (например, добавляете динамические метки), это может рушить дедупликацию и снова множить сообщения. Держите набор лейблов стабильным, особенно те, что попадают в group_by.

Валидация и безопасное внесение изменений

Перед релизом любой правки конфигурации:

  • Прогоняйте amtool check-config — словили синтаксис сейчас, а не ночью;
  • Смотрите дерево маршрутов amtool config routes — быстро видно, куда уйдёт конкретный алерт;
  • Создайте «тестовые» алерты из Prometheus (или временные правила) с набором нужных лейблов и пройдитесь по сценарию.

Хорошая практика — хранить конфигурации в системе контроля версий, иметь CI на проверку синтаксиса и, при возможности, отдельный стенд Alertmanager для прогона шаблонов и маршрутов.

Типовые паттерны маршрутизации

Ролевой доступ: NOC, on-call, команда

Классическая связка выглядит так: по умолчанию всё летит в NOC, критичное — дополнительно в on-call, а алерты определённых сервисов/команд — в их каналы. Такой подход обеспечивает и централизованный контроль, и прямую доставку по компетенции.

Среды и релисы

Для environment=stage и canary используйте отдельные ветки маршрутов с более щадящими интервалами, включайте тишину на ночь и по выходным. Для продакшна правила должны быть строгими и без «белых пятен».

Производственные окна

Если у вас повторяющиеся окна работ (бэкапы, тяжелые миграции), заведите отдельные time_intervals и привяжите их к конкретным сервисам через mute_time_intervals. Это лучше, чем создавать recurring silences скриптами.

Анти‑паттерны и подводные камни

  • Один общий канал для всех алертов. Невозможно отслеживать приоритеты и ответственность.
  • Слишком широкие silences без точных matchers. Риск «ослепить» мониторинг на часы.
  • Группировка по нестабильным лейблам (динамические версии, эфемерные ID). Получите лавину мелких групп.
  • Искусственная «тишина» для критичных инцидентов из-за удобства. Нельзя молчать, когда падает пользовательский трафик.
  • Отсутствие инхибитов. Будете ловить каскад вторичных алертов при одной корневой проблеме.

Наблюдаемость самого Alertmanager

Alertmanager экспортирует собственные метрики. Полезно построить дашборд по количеству срабатываний и доставок по получателям, по числу активных silences, времени очередей. Это помогает увидеть «шумные» правила, просадки доставки и эффект изменений конфигурации.

Чек‑лист перед выкладкой

  • Правила в Prometheus добавляют severity, team, service, environment.
  • Дерево route покрывает нужные ветки, нет «дыр» и неожиданного «поглощения» маршрутов сверху.
  • group_by минимален и стабилен, интервалы подобраны под приоритеты.
  • mute_time_intervals описаны и применены к веткам, где тишина уместна.
  • Инхибиты настроены, проверены на тестовых алертах.
  • Шаблоны подключены и рендерятся одинаково в почте и чатах.
  • amtool сообщает «ок» по синтаксису, дерево маршрутов читаемо.

Итоги

Правильно настроенный Alertmanager — это не про магию, а про дисциплину лейблов, аккуратные маршруты, окна тишины и единые шаблоны. Начните с малого: заведите обязательные лейблы в правилах, разложите ветки маршрутов по приоритету, добавьте один‑два интервала тишины для шумных сегментов и подключите шаблон сообщений. Уже это резко снизит шум и сделает инциденты управляемыми. Дальше — инхибиты, выверенные интервалы повторной доставки и наблюдаемость самого контура оповещений. И тогда on‑call перестанет быть лотереей, а станет нормальным, предсказуемым процессом.

Поделиться статьей

Вам будет интересно

Как безопасно выполнить bootstrap MariaDB Galera после полного останова

Как безопасно выполнить bootstrap MariaDB Galera после полного останова

После одновременной остановки всех узлов Galera обычного запуска MariaDB недостаточно. Сначала найдите сервер с последней транзакц ...
CoreDNS в Kubernetes: исправляем CrashLoopBackOff, SERVFAIL и DNS-петлю

CoreDNS в Kubernetes: исправляем CrashLoopBackOff, SERVFAIL и DNS-петлю

Разберём, почему CoreDNS перезапускается или отвечает SERVFAIL, как обнаружить замкнутую пересылку DNS-запросов, проверить доступн ...
Apache Kafka KRaft на VDS: отдельные controller и broker

Apache Kafka KRaft на VDS: отдельные controller и broker

Соберём новый Kafka-кластер без ZooKeeper на шести Linux VDS: три узла controller образуют отказоустойчивый metadata quorum, а три ...