Правила алертинга, Alertmanager и базовые уведомления
«Алерт без действия — это просто шум»
Мониторинг без алертинга — как дымовая сигнализация, которая не звонит пожарным.
Цели алертинга:
Плохой алерт:
«CPU high on server-42»
Хороший алерт:
«High CPU (95%) on payment-api-server-42 for 10 minutes. Check recent deployments and autoscaling metrics. Runbook: https://wiki/...»
┌──────────────────────────────────────────────────────────────┐
│ Prometheus │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Alert Rules │ │
│ │ (вычисление условий) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Alertmanager │ │
│ │ (маршрутизация, группировка, подавление) │ │
│ └─────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Email │ │ Slack │ │PagerDuty│
└─────────┘ └─────────┘ └─────────┘
Компоненты:
Правила определяются в YAML-файле и загружаются в Prometheus.
groups:
- name: application_alerts
interval: 30s # Как часто вычислять правила
rules:
- alert: HighErrorRate
expr: sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) > 0.05
for: 5m
labels:
severity: critical
team: backend
annotations:
summary: "High error rate detected"
description: "Error rate is {{ $value | humanizePercentage }} on {{ $labels.instance }}"
runbook_url: "https://wiki/runbooks/high-error-rate"Поля:
alert — имя алерта (уникальное)expr — PromQL выражение, которое возвращает 1 (алерт) или 0 (нет алерта)for — как долго условие должно выполняться перед срабатываниемlabels — метки для категоризации и маршрутизацииannotations — человекочитаемое описание (поддерживает шаблонизацию)Prometheus вычисляет expr по расписанию (evaluation_interval или interval в группе).
Результат:
for секунд → алерт firing- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))
> 0.05
for: 5m
labels:
severity: critical
annotations:
summary: "High HTTP error rate"
description: "Error rate is {{ $value | humanizePercentage }} over the last 5 minutes"Почему так:
rate()[5m] — сглаживает кратковременные скачкиfor: 5m — требует устойчивого превышенияsum() — агрегирует по всем инстансам (проблема системы, а не одного сервера)- alert: HighLatency
expr: |
histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))
> 0.5
for: 10m
labels:
severity: warning
annotations:
summary: "High latency detected"
description: "95th percentile latency is {{ $value | humanizeDuration }}"Почему так:
for: 10m — более длительное окно, потому что задержка может колебаться- alert: ServiceDown
expr: up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Service {{ $labels.job }} is down"
description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 1 minute"Почему так:
up == 0 — метрика автоматически добавляется Prometheus для всех targetsfor: 1m — быстро, но не слишком (избегаем ложных срабатываний при перезапуске)- alert: DiskSpaceLow
expr: |
(node_disk_size_bytes - node_disk_free_bytes) / node_disk_size_bytes * 100
> 85
for: 30m
labels:
severity: warning
annotations:
summary: "Disk space low on {{ $labels.instance }}"
description: "Disk usage is {{ $value | humanizePercentage }} on {{ $labels.device }}"Почему так:
for: 30m — диск заполняется медленно, не нужно реагировать на кратковременные скачки- alert: DiskWillFillIn4Hours
expr: |
predict_linear(node_disk_free_bytes[24h], 4*3600) < 0
for: 1h
labels:
severity: warning
annotations:
summary: "Disk will fill in 4 hours on {{ $labels.instance }}"
description: "Based on 24h trend, disk {{ $labels.device }} will be full in 4 hours"Почему так:
predict_linear() — предсказывает будущее значение на основе тренда- alert: HighMemoryUsage
expr: |
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes)
/
node_memory_MemTotal_bytes
* 100
> 90
for: 15m
labels:
severity: warning
annotations:
summary: "High memory usage on {{ $labels.instance }}"
description: "Memory usage is {{ $value | humanizePercentage }}"Alertmanager настраивается отдельно от Prometheus.
alertmanager.yml)global:
smtp_smarthost: 'smtp.example.com:587'
smtp_from: 'alertmanager@example.com'
slack_api_url: 'https://hooks.slack.com/services/XXX/YYY/ZZZ'
# Маршрутизация
route:
receiver: 'default-receiver'
group_by: ['alertname', 'severity']
group_wait: 30s # Ждём перед отправкой первой группы
group_interval: 5m # Ждём перед отправкой следующих алертов той же группы
repeat_interval: 4h # Повторяем, если алерт не resolved
# Дочерние маршруты
routes:
- match:
severity: critical
receiver: 'pagerduty-critical'
- match:
team: backend
receiver: 'slack-backend'
# Получатели
receivers:
- name: 'default-receiver'
email_configs:
- to: 'alerts@example.com'
- name: 'pagerduty-critical'
pagerduty_configs:
- service_key: 'your-pagerduty-service-key'
- name: 'slack-backend'
slack_configs:
- channel: '#backend-alerts'
send_resolved: true
# Подавление (inhibition)
inhibit_rules:
# Если критический алерт сработал, не отправлять warning той же системы
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'instance']Ключевые концепции:
Похожие алерты группируются в одно уведомление:
group_by: ['alertname', 'severity']Вместо 10 отдельных уведомлений о 10 серверах с высоким CPU — одно: «10 серверов с высоким CPU».
Если сработал критический алерт, warning той же системы не отправляется:
inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'instance']Через UI Alertmanager можно установить silence — временное подавление алертов.
Использование:
Плохо:
«CPU high»
Хорошо:
«CPU > 90% на payment-api в течение 15 минут. Проверьте очередь задач и последние деплои. Runbook: https://wiki/...»
Правило: если на алерт нельзя отреагировать — не создавайте его.
Проблема: alert fatigue — усталость от уведомлений. Люди перестают реагировать.
Решения:
for для фильтрации кратковременных скачковОпределите 2-3 уровня:
| Уровень | Когда | Куда | Реакция |
|---|---|---|---|
critical | Сервис недоступен или критически деградировал | PagerDuty, телефон | Немедленно |
warning | Проблема, которая может стать критической | Slack, email | В течение часа |
info | Информация для контекста | Email, лог | Когда удобно |
annotations:
summary: "..."
description: "..."
runbook_url: "https://wiki/runbooks/..."
dashboard_url: "https://grafana/d/..."Способы:
promtool check rules alerting.ymlРаз в квартал проверяйте:
Grafana 8+ имеет свою систему алертинга (Unified Alerting).
Преимущества Grafana Alerts:
Когда использовать Grafana:
Когда использовать Prometheus:
http://localhost:9090)# Получить все алерты
curl http://localhost:9090/api/v1/rules
# Получить состояние алертов
curl http://localhost:9090/api/v1/alertsПроверьте выражение в Prometheus UI:
Теперь вы умеете настраивать алерты. В следующей теме вы изучите Loki — систему агрегации логов, которая дополняет метрики Prometheus деталями событий.
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.