linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Уроки
  • How it works
  • Симулятор
  • База знаний
  • Собеседование
Index
Categories
All entries
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
home/linux/kb/Observability и мониторинг/alerting-rules-alertmanager

kb/observability ── Observability и мониторинг ── intermediate

Alertmanager: route tree, inhibit, dedup, on-call

Alertmanager - принимает alerts от Prometheus, дедупит, группирует, роутит по route tree в PagerDuty/Slack/email. Inhibit suppress'ит зависимые alerts при upstream-падении. Silence на время maintenance. Шум убивает on-call.

view as markdownaka: alertmanager, alerting-rules, alert-routing, on-call, silence

Зачем Alertmanager

[[prometheus-basics|Prometheus]] оценивает alerting rules и пушит fired alerts в Alertmanager. Сам Prom не умеет:

  • Дедуплицировать (3 ингестера → 3 копии alert'а)
  • Группировать (10 нод down = 1 нотификация, не 10)
  • Роутить (team=db → DBAs Slack, team=net → on-call)
  • Inhibit (если cluster-down, не алерти про каждый pod)
  • Silence (maintenance window)
  • Templating (Slack message с runbook-ссылкой)

Это всё в Alertmanager. Standalone Go-binary, обычно 2-3 реплики HA через mesh-cluster.

Архитектура

Prometheus ─┐
Prometheus ─┼─► Alertmanager ─┬─► PagerDuty
Prometheus ─┘    (HA cluster)  ├─► Slack
                                ├─► Email
                                └─► generic webhook

3 Prom отправляют одинаковые alerts → Alertmanager dedupes по (labels, alertname). Кластер AM синхронизирует state через mesh-gossip, только один шлёт notification (gossip lock).

Lifecycle alert'а

┌──────────────────┐
│ Prometheus rule  │
│ expr: ... > X    │
│ for: 5m          │
└────────┬─────────┘
         │ POST /api/v2/alerts
         ▼
┌──────────────────┐
│ Alertmanager     │
│ ┌──────────────┐ │
│ │ dedup        │ │  по labels
│ ├──────────────┤ │
│ │ inhibit      │ │  блок если parent fired
│ ├──────────────┤ │
│ │ silence      │ │  блок если matched mute
│ ├──────────────┤ │
│ │ route        │ │  выбор receiver
│ ├──────────────┤ │
│ │ group        │ │  буферизация N сек
│ └──────────────┘ │
└────────┬─────────┘
         │
         ▼
 PagerDuty / Slack

Конфиг, структура

yaml
global:
  resolve_timeout: 5m
  slack_api_url: 'https://hooks.slack.com/services/...'
route:
  receiver: default-receiver
  group_by: ['alertname', 'cluster']
  group_wait: 30s              # ждём собрать batch
  group_interval: 5m           # batch updates
  repeat_interval: 4h          # повтор если не решено
  routes:
    - matchers:
        - severity = critical
        - team = database
      receiver: db-pagerduty
      continue: true           # НЕ останавливаем дальше route tree
    - matchers:
        - severity = warning
      receiver: slack-warnings
      group_interval: 30m
    - matchers:
        - team = network
      receiver: net-slack
receivers:
  - name: default-receiver
    slack_configs:
      - channel: '#alerts'
  - name: db-pagerduty
    pagerduty_configs:
      - service_key: <key>
        description: '{{ .CommonAnnotations.summary }}'
  - name: slack-warnings
    slack_configs:
      - channel: '#alerts-warnings'
inhibit_rules:
  - source_matchers: [severity = critical, alertname = ClusterDown]
    target_matchers: [severity =~ "warning|critical"]
    equal: [cluster]

Route tree, иерархия

Tree-структура: alert spускается сверху вниз, на каждом узле matchers проверяются. Первый match → отправлен в receiver.

  • continue: true, после match продолжать дерево (один alert → N receivers)
  • matchers, label = value, label != value, label =~ regex, label !~ regex
  • Дочерние routes наследуют group_by, group_wait, group_interval от родителя если не override

Pattern: branching по team label, тогда severity определяет receiver внутри.

Inhibit, suppress dependent

Сценарий: cluster-API упал → 50 alert'ов про каждый pod.

yaml
inhibit_rules:
  - source_matchers: [alertname = APIServerDown]
    target_matchers: [alertname = PodNotReady]
    equal: [cluster]

Если в кластере fire APIServerDown, все PodNotReady (с тем же cluster) blocked. Сразу как APIServerDown resolve, pods unblock и могут fire.

Best practice: иерархия inhibit от high-level к низкому (datacenter > cluster > node > pod).

Silence, temporary mute

Maintenance window: «глушим alerts по service=db до 16:00».

bash
amtool silence add \
    service=db env=prod \
    --duration=2h --comment="DB maintenance ticket DBA-1234"

Silence, labels matcher + expiration. AM не отправляет matched alerts. UI/CLI показывают alerts в suppressed state.

Best practice: всегда --comment с ссылкой на ticket. Без обоснования silences копятся, забываешь, alerts реально глохнут.

Grouping, анти-шум

10 нод одновременно вышли из rotation. Без grouping:

  • 10 PagerDuty инцидентов
  • 10 Slack pings
  • On-call злой

С group_by: [alertname, cluster]:

  • 1 PagerDuty с 10 nodes в payload
  • 1 Slack message: «10 nodes down: node-01 ... node-10»

group_wait = 30s, ждём всех чтобы собрать batch. Trade-off: быстрее notify vs больше шума.

Notification templates

Default Slack message, generic, мало пользы. Кастомная Go-template:

yaml
receivers:
  - name: slack-detailed
    slack_configs:
      - channel: '#alerts'
        title: '{{ .Status | toUpper }} {{ .CommonLabels.alertname }}'
        text: |
          *Severity:* {{ .CommonLabels.severity }}
          *Cluster:* {{ .CommonLabels.cluster }}
          *Description:* {{ .CommonAnnotations.description }}
          *Runbook:* {{ .CommonAnnotations.runbook }}
          *Dashboard:* {{ .CommonAnnotations.dashboard }}
          {{ range .Alerts }}
          • {{ .Labels.instance }}: {{ .Annotations.summary }}
          {{ end }}

Хороший alert содержит: severity, что сломано, runbook, dashboard, affected scope.

Alert hygiene, anti-patterns

Шум убивает on-call. Симптомы:

  • On-call устал, игнорит alerts → реальный инцидент пропустили
  • 50 alerts/день, 49 ignored
  • «alert fatigue»

Anti-patterns:

  • Алерт на raw метрику без for:, flap'ит на короткие spike'и
  • Алерт на average latency, не отражает p99 опыт
  • Алерт на абсолютное значение CPU, нерелевантно (90% CPU = OK на batch worker, problem на user-facing)
  • Алерт без runbook, on-call не знает что делать
  • Алерт на up == 0 без deadman, Prom сам упал, alert не отправится. См. ниже.

Best practices:

  • Алертить только на симптомы, не причины (RED method, Google SRE «4 golden signals»)
  • Использовать error budgets (sli-slo-error-budget) вместо threshold-alerts
  • Multi-window burn-rate для SLO
  • Каждый alert имеет runbook
  • Регулярно ревьюить noisy alerts, top-N по fire-count за месяц, тюнить threshold или удалять

Deadman alert

Кто алертит, что Prometheus сам упал? Если Prom down, alerting rules не оцениваются, AM не получает notifications.

Deadman:

yaml
- alert: DeadMansSwitch
  expr: vector(1)              # всегда firing
  annotations:
    summary: "Prometheus alive"

Прометей всегда шлёт. AM шлёт в receiver deadman каждые 5 минут. Receiver, внешний watchdog (Healthchecks.io, Cronitor): если notification не пришла за 10 минут, внешний alert «Prom мёртв».

On-call rotation

Alertmanager не управляет rotation сам, это PagerDuty/Opsgenie. AM шлёт в team_X service, PagerDuty знает кто on-call в данный момент.

yaml
receivers:
  - name: db-pagerduty
    pagerduty_configs:
      - service_key: <key>
        severity: critical
        group: database
        class: '{{ .CommonLabels.alertname }}'

PagerDuty class, для grouping инцидентов в их UI.

HA Alertmanager

3 instances в mesh-cluster:

alertmanager --cluster.peer=am-01:9094 --cluster.peer=am-02:9094 \
             --cluster.peer=am-03:9094

Все 3 принимают alerts от Prom (Prom отправляет всем). Gossip синхронизирует state (silences, inhibits). Только один шлёт notification через clock-based leader-election (избегает дублей).

Когда что-то пошло не так

  • Alert fired в Prom, но AM не получил, проверь Prometheus alertmanagers config + alertmanager_notifications_total counter. Network/auth.
  • AM получил, но не отправил, проверь route tree (matchers могут быть слишком strict). amtool config routes test симулирует routing.
  • PagerDuty/Slack rate limit, AM ретраит, экспоненциальный backoff. Если flood, повышай group_interval.
  • «stuck» alerts (resolved, но AM держит), resolve_timeout не сработал, Prom послал EndsAt в прошлом. Bug, обнови AM.
  • Silence не работает, matchers неточные. Test через amtool silence query.
  • HA AM шлёт дубли, clock skew между нодами > 30s. NTP обязателен (chrony-and-ntp).
  • Notification template error, Go-template errors молча. Логи AM покажут.

§ команды

bash
amtool config routes test --config.file=alertmanager.yml severity=critical team=db

Симуляция: куда уйдёт alert с этими labels - dry-run route tree

bash
amtool silence add severity=warning service=batch --duration=4h --comment='ticket-1234'

Silence все warnings batch-сервиса на 4 часа с обоснованием

bash
amtool silence query

Список активных silences - регулярно смотри, удаляй забытые

bash
curl -s http://alertmanager:9093/api/v2/alerts | jq '.[] | {alertname: .labels.alertname, status: .status.state}'

Текущие alerts через API - filter по state (active/suppressed/unprocessed)

bash
amtool check-config alertmanager.yml

Валидация config до reload (CI-friendly)

bash
curl -X POST http://alertmanager:9093/-/reload

Reload config без рестарта (требует --web.enable-lifecycle)

bash
promtool check rules /etc/prometheus/rules/*.yml

Проверка alerting rules в Prometheus - синтаксис, expr-валидность

§ см. также

  • prometheus-basicsPrometheus: scrape, TSDB, PromQL и production-pitfallsPrometheus - сервер мониторинга: сам опрашивает приложения по HTTP, собирает числовые метрики, хранит во встроенной БД ~15 дней. По ним строят графики в Grafana и алерты через Alertmanager. Стандарт de-facto в Kubernetes.
  • sli-slo-error-budgetSLI / SLO / error budget: SRE-метрики без шумаSLI - метрика для пользователя (availability, p99 latency). SLO - цель за период (99.9% за 30d). Error budget = 1-SLO, расходуется на инциденты+релизы. Multi-window burn rate alerting заменяет threshold-алерты, меньше шума.
  • metric-typesТипы метрик: counter, gauge, histogram, summary4 типа метрик: counter (только вверх), gauge (любое значение), histogram (buckets для p99), summary (quantile в клиенте). Native histogram (Prom 2.40+) - sparse buckets, аккуратнее по памяти. Exemplars связывают метрику с trace_id.
  • service-discovery-prometheusService discovery в Prometheus: k8s, Consul, file_sd, relabelProm discoverит targets через k8s API, Consul, file_sd (static). relabel_configs - до scrape (filter+rewrite labels). metric_relabel - после scrape (drop bad metrics). Без relabel - cardinality из k8s взрывается.
  • opentelemetryOpenTelemetry: signals, OTLP, Collector pipelineOpenTelemetry - CNCF-стандарт для metrics+traces+logs в одном SDK. OTLP протокол (gRPC или HTTP). Collector принимает, фильтрует, роутит в Prom/Tempo/Loki/Jaeger. Auto-instrumentation без code change.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки