С чего начать Первые шаги трек · 15 ступеней
Linux Labs

Alertmanager: кому и сколько раз уходят алерты

15 мин Ubuntu 24.04 · Alertmanager 0.26

Служба, которая принимает алерты Prometheus, группирует их, глушит и рассылает уведомления получателям по маршрутам.

Шпаргалка

9 команд Версия для печати
  • amtool check-config /etc/prometheus/alertmanager.yml проверить
  • sudo systemctl reload prometheus-alertmanager перечитать конфиг
  • amtool alert активные алерты
  • amtool alert query severity=critical отбор по меткам
  • amtool alert query -o extended все метки
  • amtool silence add instance=web01 -d 2h -c 'замена диска' тишина
  • amtool silence query действующие тишины
  • amtool silence expire 6c91da38-1b58-4c6f-835e-3b504d18dd7b снять
  • amtool alert add alertname=Test severity=warning пробный алерт

Обзор

Alertmanager — служба, которая получает алерты от Prometheus и решает, кому, когда и сколько раз о них сообщить. Prometheus по правилу решает, что алерт горит (prometheus), и отправляет его в Alertmanager. Дальше Alertmanager:

  1. собирает алерты в группы по меткам, чтобы одно событие давало одно уведомление, а не по одному на каждую машину;
  2. по дереву маршрутов выбирает получателя;
  3. пропускает алерты, которые заглушены тишиной или подавлены другим алертом;
  4. отправляет уведомление — письмо, вебхук, сообщение в чат — и повторяет его, пока алерт горит.
text
Prometheus ──алерты──▶ Alertmanager :9093 ──уведомления──▶ получатели
 (правила)              группы, маршруты,                 (webhook,
                        тишина, подавление                 почта…)

В Ubuntu это пакет prometheus-alertmanager: служба с тем же именем, конфиг /etc/prometheus/alertmanager.yml, данные — тишины и журнал отправленного — в /var/lib/prometheus/alertmanager. Порт 9093 — веб-интерфейс и API, 9094 — связь узлов кластера. Утилита amtool — из того же пакета. На учебной машине пакет стоит, служба выключена, а конфиг из пакета — пример с почтой и PagerDuty: без сети он бесполезен, свой конфиг пишут заново.

Путь алерта

Куда Prometheus отправляет алерты — раздел alerting в prometheus.yml; в пакете это localhost:9093. Нашёл ли Prometheus Alertmanager:

text
$ curl -s localhost:9090/api/v1/alertmanagers | jq -c .data
{"activeAlertmanagers":[{"url":"http://localhost:9093/api/v2/alerts"}],
  "droppedAlertmanagers":[]}

Адрес отправки Prometheus собирает из scheme (по умолчанию http), адреса из targets, path_prefix (по умолчанию пусто) и /api/v2/alerts; полностью он виден в url ответа выше. Лишний path_prefix — например /alertmanager, скопированный с сервера за прокси, — даёт адрес, которого у Alertmanager нет (alertmanager).

Prometheus отправляет только алерты в состоянии firing и повторяет отправку, пока алерт горит; когда условие перестало выполняться, отправляет его ещё раз с временем окончания — Alertmanager считает алерт решённым. К меткам алерта Prometheus добавляет external_labels из своего конфига: в конфиге пакета это monitor: 'example', и у каждого алерта есть метка monitor="example".

Алерт в Alertmanager — это метки (по ним алерты различаются, группируются и выбирают маршрут), аннотации (текст: summary, description) и время начала и конца.

Группировка и интервалы

group_by перечисляет метки: алерты с одинаковыми значениями этих меток попадают в одну группу, группа — одно уведомление со списком алертов. На учебной машине три алерта InstanceDown для web01, web02 и web03:

group_by Уведомлений В каждом
[alertname] 1 три алерта
[alertname, instance] 3 по одному

Без group_by все алерты маршрута — одна группа; group_by: ['...'] — каждый алерт отдельно.

Параметр Что задаёт По умолчанию
group_wait пауза перед первым уведомлением новой группы: успеть собрать алерты, которые придут следом 30s
group_interval пауза перед уведомлением об изменении группы: новый алерт в ней или решённый 5m
repeat_interval повтор, если в группе ничего не изменилось 4h

Пятьдесят уведомлений на одно событие — почти всегда группировка: в group_by метка, которая у каждого алерта своя (instance, pod, path), или '...'. Повторы того же уведомления каждые несколько минут — слишком короткий repeat_interval.

Маршруты

Маршруты — дерево. Корневой route принимает каждый алерт и обязан иметь receiver. Дочерние маршруты в routes проверяются сверху вниз; алерт уходит в первый, чьи matchers подошли, и спускается дальше, если у того есть свои routes. Не подошёл ни один — уведомление получает получатель родителя. continue: true у маршрута говорит «проверять и следующие»: так одно уведомление уходит нескольким получателям. Дочерний маршрут наследует group_by и интервалы родителя, если не задал свои; заданный group_by заменяет родительский целиком, метки не складываются.

Критичное — и дежурному, и команде:

yaml
route:
  receiver: team
  routes:
    - matchers: [severity="critical"]
      receiver: oncall
      continue: true
    - matchers: [team="web"]
      receiver: team-web

Без continue: true критичный алерт команды web ушёл бы только дежурному: проверка остановилась бы на первом подошедшем маршруте.

Условия в matchers — как селекторы promql: severity="critical", team!="db", severity=~"critical|page". Все условия списка должны выполниться. Старые формы match и match_re ещё читаются.

yaml
route:
  receiver: chat
  group_by: [alertname]
  routes:
    - matchers:
        - severity="critical"
      receiver: pager

amtool рисует дерево и отвечает, куда уйдёт алерт с заданными метками (флаг --config.file обязателен, см. alertmanager):

text
$ amtool config routes show \
    --config.file=/etc/prometheus/alertmanager.yml
Routing tree:
.
└── default-route  receiver: chat
    └── {severity="critical"}  receiver: pager

$ amtool config routes test \
    --config.file=/etc/prometheus/alertmanager.yml severity=critical
pager

Тишина и подавление

Тишина (silence) — временный запрет уведомлений для алертов, метки которых подходят под условия. Её ставит человек — amtool silence add или веб-интерфейс — с комментарием и сроком. Алерт под тишиной остаётся в списке со статусом suppressed, уведомлений по нему нет. Тишины хранятся в /var/lib/prometheus/alertmanager и переживают перезапуск.

Подавление (inhibition) — правило в конфиге: пока горит алерт- источник, алерты-цели с теми же значениями меток из equal не рассылаются. Машина недоступна — незачем отдельно сообщать, что на ней кончается диск:

yaml
inhibit_rules:
  - source_matchers: [alertname="NodeDown"]
    target_matchers: [severity="warning"]
    equal: [instance]

На учебной машине: тишина на alertname=DiskFull instance=web02 — уведомления о web02 нет, о web04 есть; NodeDown на web03 — DiskFull того же web03 в статусе suppressed.

amtool

amtool — Alertmanager из терминала: смотрит алерты, ставит и снимает тишины, проверяет конфиг и маршруты. Команды alert и silence идут в API Alertmanager. На учебной машине amtool по умолчанию ходит на http://localhost:9093; другой адрес — --alertmanager.url=… или строка в /etc/amtool/config.yml (для всех) либо ~/.config/amtool/config.yml (для себя):

yaml
alertmanager.url: http://localhost:9093

Алерты:

text
$ amtool alert
Alertname  Starts At                Summary     State
DiskFull   2026-10-22 04:44:53 UTC  мало места  active
DiskFull   2026-10-22 04:44:53 UTC              active

Summary — аннотация summary. Заглушённых тишиной и подавленных алертов в выводе amtool alert нет — их показывают -s (--silenced) и -i (--inhibited). amtool alert query instance=web01 отбирает по меткам, -o extended печатает все метки и аннотации, -s показывает заглушённые тишиной, -i — подавленные, -o json — всё в JSON для jq.

Тишины:

text
$ amtool silence add alertname=DiskFull instance=web01 \
    -d 30m -c 'замена диска'
6c91da38-1b58-4c6f-835e-3b504d18dd7b
$ amtool silence query
ID                                    Matchers                       …
6c91da38-1b58-4c6f-835e-3b504d18dd7b  alertname="DiskFull" instance=…

Вывод silence query здесь обрезан: дальше столбцы Ends At, Created By и Comment. Команда печатает ID новой тишины; снять её — amtool silence expire <ID>, ID всех тишин — amtool silence query -q. -d — срок (30m, 2h), -c — комментарий, без него тишина не ставится.

Пробный алерт без Prometheus — проверить маршрут и получателя:

bash
amtool alert add alertname=Test severity=warning \
  --annotation=summary='проверка доставки'

Конфигурация

14

alertmanager.yml

Конфиг с двумя получателями-вебхуками: всё — в chat, критичное — в pager.

yaml
route:
  receiver: chat
  group_by: [alertname]
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  routes:
    - matchers:
        - severity="critical"
      receiver: pager
receivers:
  - name: chat
    webhook_configs:
      - url: http://127.0.0.1:5001/chat
  - name: pager
    webhook_configs:
      - url: http://127.0.0.1:5001/pager

Вебхук получает POST с JSON: receiver, status (firing или resolved), groupLabels, commonLabels и список alerts с метками, аннотациями и статусом каждого. У вебхука send_resolved по умолчанию включён: когда алерт решён, приходит уведомление и об этом.

Проверить и применить:

bash
amtool check-config /etc/prometheus/alertmanager.yml
sudo systemctl reload prometheus-alertmanager
journalctl -u prometheus-alertmanager -o cat | tail -3

check-config печатает SUCCESS и что нашёл: маршрут, число получателей и правил подавления. После reload в журнале — Completed loading of configuration file.

Ключи запуска и кластер

Ключи службы — переменная ARGS в /etc/default/prometheus-alertmanager (в пакете пустая). По умолчанию Alertmanager запускается узлом кластера: слушает порт 9094 и ищет частный адрес машины, чтобы сообщать его соседям. У машины без такого адреса — на учебной ВМ только lo — служба не стартует (alertmanager). Один узел без кластера:

bash
# /etc/default/prometheus-alertmanager
ARGS="--cluster.listen-address="

Ключи читаются при запуске: после правки — sudo systemctl restart prometheus-alertmanager. curl -s localhost:9093/api/v2/status | jq .cluster.status после этого — "disabled".

Директива Что делает Пример
route alertmanager.yml Корневой маршрут — через него проходит каждый алерт; обязателен receiver. route: {receiver: chat}
receiver route Имя получателя из списка receivers, которому уходят уведомления этого маршрута. receiver: pager
group_by route Метки, по которым алерты собираются в группы; группа — одно уведомление. '...' — каждый алерт отдельно. group_by: [alertname]
group_wait route Пауза перед первым уведомлением новой группы — чтобы собрать алерты, которые придут следом. group_wait: 30s
group_interval route Пауза перед уведомлением об изменении группы — новом или решённом алерте. group_interval: 5m
repeat_interval route Через сколько повторить уведомление, если в группе ничего не изменилось. repeat_interval: 4h
routes route Дочерние маршруты; алерт уходит в первый подошедший, иначе остаётся у родителя. routes: [{matchers: [severity="critical"], receiver: pager}]
matchers route, inhibit_rules Условия на метки алерта — =, !=, =~, !~; все условия должны выполниться. matchers: [severity="critical", team=~"web|db"]
continue route true — после этого маршрута проверять и следующие, уведомление уйдёт нескольким получателям. continue: true
receivers alertmanager.yml Список получателей; у каждого name и способы доставки — webhook_configs, email_configs и другие. receivers: [{name: chat, webhook_configs: [{url: http://127.0.0.1:5001/chat}]}]
webhook_configs.url receivers Адрес, на который Alertmanager отправляет POST с JSON уведомления. url: http://127.0.0.1:5001/chat
send_resolved webhook_configs Сообщать ли, что алерт решён; у webhook включено по умолчанию, у email — выключено. send_resolved: false
inhibit_rules alertmanager.yml Подавление — пока горит алерт-источник, алерты-цели с теми же метками из equal не рассылаются. inhibit_rules: [{source_matchers: [alertname="NodeDown"], target_matchers: [severity="warning"], equal: [instance]}]
resolve_timeout global Через сколько считать решённым алерт без endsAt, если его перестали присылать. global: {resolve_timeout: 5m}

Ничего не найдено. Попробуй запрос короче.

Рецепты

4

Проверить маршрут до отправки

bash
c=/etc/prometheus/alertmanager.yml
amtool config routes test --config.file=$c severity=critical team=db
amtool config routes test --config.file=$c --verify.receivers=pager \
  severity=critical

Первая команда печатает имя получателя. Вторая сверяет его с ожидаемым: не совпало — WARNING: Expected receivers did not match resolved receivers. и код выхода 1, годится для скрипта проверки.

Послать пробный алерт через API

bash
curl -s -XPOST -H 'Content-Type: application/json' \
  localhost:9093/api/v2/alerts \
  -d '[{"labels":{"alertname":"Test","severity":"warning"}}]'

В массиве можно прислать сразу много алертов. Алерт без endsAt считается решённым через resolve_timeout (5 минут), если его не присылать снова.

Тишина на время работ

bash
amtool silence add instance=web01 -d 2h -c 'замена диска, Иван'

Условие — только на машину, которую трогаешь, срок — на время работ. Закончил раньше — amtool silence expire <ID>.

Не будить из-за следствий

Правило из раздела alertmanager: при NodeDown молчат предупреждения с той же машины. Без equal недоступность одной машины глушила бы предупреждения со всех.

Неполадки

10

Служба не стартует: No private IP address found

text
$ journalctl -u prometheus-alertmanager -o cat | grep level=error
… level=error msg="unable to initialize gossip mesh" err="create
  memberlist: Failed to get final advertise address: No private IP
  address found, and explicit IP not provided"

Режим кластера не нашёл частного адреса машины. Служба падает и перезапускается, пока systemd не сдастся: Start request repeated too quickly. Решение — ARGS="--cluster.listen-address=" (alertmanager), затем sudo systemctl reset-failed prometheus-alertmanager и start.

amtool: connection refused

text
amtool: error: Get "http://localhost:9093/api/v2/alerts?active=true…":
  dial tcp 127.0.0.1:9093: connect: connection refused

Alertmanager не запущен или слушает другой адрес: systemctl status prometheus-alertmanager, ss -tlnp | grep 9093.

comment required by config

amtool silence add без -c: комментарий к тишине обязателен. Добавь -c 'что и зачем'.

undefined receiver

text
$ amtool check-config /etc/prometheus/alertmanager.yml
Checking '/etc/prometheus/alertmanager.yml'  FAILED: undefined
  receiver "oncall" used in route
amtool: error: failed to validate 1 file(s)

Маршрут ссылается на получателя, которого нет в receivers, — обычно опечатка в имени. Если такой конфиг перечитать reload, Alertmanager продолжит работать со старым, а в журнале будет Loading configuration file failed. Служба active — это ещё не значит, что новый конфиг принят.

scheme required for webhook url

amtool config routes show или test без --config.file берут конфиг у запущенного Alertmanager через API. Адреса вебхуков API скрывает, и разобрать такой конфиг amtool не может. Передай файл: --config.file=/etc/prometheus/alertmanager.yml.

Уведомление не доходит: Notify attempt failed

text
… level=warn component=dispatcher receiver=chat integration=webhook[0]
  msg="Notify attempt failed, will retry later" attempts=1
  err="Post \"<redacted>\": dial tcp 127.0.0.1:5001: connect:
  connection refused"

Получатель не отвечает. Alertmanager повторяет попытки сам; почини получателя — уведомление уйдёт. Адрес в журнале скрыт, смотри url в конфиге.

Алерт горит в Prometheus, а в Alertmanager его нет

  • алерт ещё pending: Prometheus отправляет только firing (prometheus);
  • curl -s localhost:9090/api/v1/alertmanagers — пустой activeAlertmanagers: в prometheus.yml нет раздела alerting или в нём не тот адрес;
  • Alertmanager не запущен — amtool alert ответит connection refused.

Error sending alert: bad response status 404

text
$ journalctl -u prometheus -o cat | grep 'Error sending alert'
… msg="Error sending alert"
  alertmanager=http://localhost:9093/alertmanager/api/v2/alerts
  count=1 err="bad response status 404 Not Found"

Prometheus отправляет алерты, а Alertmanager отвечает 404: адрес собран неверно (alertmanager). amtool alert при этом пуст, хотя ALERTS в Prometheus горит. Сверь url в curl -s localhost:9090/api/v1/alertmanagers с http://localhost:9093/api/v2/alerts и убери лишний path_prefix.

Уведомлений слишком много

Посмотри, по каким меткам собрана группа: groupLabels в теле вебхука. Если там instance или другая метка, своя у каждого алерта, — убери её из group_by. Повторы одного и того же — подними repeat_interval.

Алерт в статусе suppressed

Его глушит тишина или подавление. Какие именно — в JSON:

text
$ amtool alert query -o json alertname=DiskFull | jq -c '.[].status'
{"inhibitedBy":[],"silencedBy":["6c91da38-…"],"state":"suppressed"}

ID в silencedBy — тишина из amtool silence query, в inhibitedBy — алерт-источник правила подавления.

Опасно

1

Широкая тишина

amtool silence add severity=~".+" -d 7d глушит все алерты на неделю, и через день о ней никто не помнит. Условие — на конкретную машину или алерт, срок — на время работ, в комментарии — кто и зачем. amtool silence query -q | xargs amtool silence expire снимает все тишины разом, в том числе чужие.

Термины

5
группировка алертов alert grouping
Сборка алертов с одинаковыми значениями меток из group_by в одну группу: группа — одно уведомление. Метка, своя у каждого алерта, в group_by даёт по уведомлению на алерт.
маршрут алерта alert route
Узел дерева route в конфиге Alertmanager: условия matchers на метки алерта и получатель. Алерт уходит в первый подошедший дочерний маршрут, иначе — получателю родителя.
получатель (receiver)
Именованный способ доставки уведомлений Alertmanager: webhook, почта, чат. Маршрут называет получателя по имени из списка receivers. Ещё встречается в: GPG, Postfix
тишина (silence)
Временный запрет уведомлений Alertmanager для алертов с подходящими метками. Ставится с комментарием и сроком: amtool silence add; алерт под тишиной — suppressed. Ещё встречается в: ping, Таймеры systemd, tcpdump
подавление (inhibition)
Правило inhibit_rules в Alertmanager: пока горит алерт-источник, алерты-цели с теми же метками из equal не рассылаются. Например, при NodeDown молчат предупреждения той же машины.

См. также

  • prometheus — правила, которые порождают алерты.
  • promql — выражения правил и синтаксис условий на метки.
  • node-exporter — метрики машины, по которым пишут правила.
  • grafana — свои алерты и уведомления в Grafana.
  • jq — разобрать amtool alert query -o json и тело вебхука.
  • curl — API Alertmanager из терминала.
  • systemctl — reload, restart, reset-failed.
  • journalctl — журнал службы: ошибки конфига и доставки.
Загрузка…