Минимальный bridge
Alertmanager отправляет JSON в ваш receiver. Receiver форматирует короткий текст и вызывает Nerve CLI.
export NERVE_DSN="nerve://TOKEN:[email protected]"
echo "alert firing: api latency high" | nerve send --severity alert
Что не отправлять
Не кладите в push полный payload с secret labels. Лучше отправлять alertname, status, instance и ссылку на Grafana или runbook.
Alertmanager route
Обычно Nerve не должен получать все alert-ы. Оставьте warning/info в Grafana или Slack, а на телефон отправляйте только page-worthy события: service down, high error rate, certificate expires, disk full.
route:
receiver: default
routes:
- matchers:
- severity="critical"
receiver: nerve-phone
receivers:
- name: nerve-phone
webhook_configs:
- url: http://127.0.0.1:8099/alertmanager
Формат короткого сообщения
[{{ .Status }}] {{ .CommonLabels.alertname }}
instance={{ .CommonLabels.instance }}
severity={{ .CommonLabels.severity }}
runbook={{ .CommonAnnotations.runbook_url }}
Группировка и дедупликация
Если Alertmanager уже группирует alert-ы, не разворачивайте их в десятки отдельных push. Один сигнал с количеством firing/resolved alert-ов лучше, чем поток одинаковых уведомлений.
Resolved-сообщения
Для critical alert-ов включите resolved notification. Иначе телефон сообщит только о проблеме, но не скажет, что она уже ушла.
send_resolved: true
title: '{{ .Status }}: {{ .CommonLabels.alertname }}'
text: 'firing={{ len .Alerts.Firing }} resolved={{ len .Alerts.Resolved }}'
Где запускать bridge
Bridge можно держать рядом с Alertmanager в той же private network. Ему нужен только NERVE_DSN и возможность вызвать nerve send; доступ к Prometheus TSDB или Kubernetes API не требуется.
Чеклист перед production
- проверить test alert через amtool или curl;
- убедиться, что secret labels не попадают в текст;
- ограничить receiver только severity=critical;
- проверить resolved-сообщение.