Есть три рабочих окружения – Dev, Stage, Production.
Есть пачка алертов с разными уровнями важности – info, warning и critical, например:
... - name: SSLexpiry.rules rules: - alert: SSLCertExpiring30days expr: probe_ssl_earliest_cert_expiry{job="blackbox"} - time() < 86400 * 30 for: 10m labels: severity: info annotations: summary: "SSL certificate warning" description: "SSL certificate for the {{ $labels.instance }} will expire within 30 days!" ...
Алерты отправляются в Slack и в OpsGenie.
Задача: в зависимости от окружения и уровня важности – слать либо в только в Slack, либо в Slack + OpsGenie.
OpsGenie, в свою очередь, в зависимости от уровня важности:
- для warning – оптравляет либо только письмо на почту + сообщение в приложение на телефоне
- для алертов уровня critical – письмо на почту + сообщение в приложение + звонок на телефон от бота
Т.е. выглядит всё это так:
- Dev
- любые сообщения, независимо от уровня важности – шлём только в Slack
- Staging:
- info – только в Slack
- warning и critical – в Slack и OpsGenie, но для OpsGenie ставим уровень warning (P3)
- Production
- info – только в Slack
- warning и critical – в Slack и OpsGenie, но для OpsGenie ставим уровень critical (P1)
Для разбивки сообщений между Slack и OpsGenie используется три ресивера, при этом в warning и critical ресиверах – для OpsGenie устанавливаются уровни P3 и P1 соответсвенно:
... receivers: - name: 'default' slack_configs: - send_resolved: true title_link: 'https://monitor.example.com/prometheus/alerts' title: '{{ if eq .Status "firing" }}:confused:{{ else }}:dancing_panda:{{ end }} [{{ .Status | toUpper }}] {{ .CommonAnnotations.summary }}' text: "{{ range .Alerts }}*Priority*: `{{ .Labels.severity | toUpper }}`\nMonitoring host: {{ .Labels.monitor }}\n{{ .Annotations.description }}\n{{ end }}" - name: 'warning' slack_configs: - send_resolved: true title_link: 'https://monitor.example.com/prometheus/alerts' title: '{{ if eq .Status "firing" }}:disappointed_relieved:{{ else }}:dancing_panda:{{ end }} [{{ .Status | toUpper }}] {{ .CommonAnnotations.summary }}' text: "{{ range .Alerts }}*Priority*: `{{ .Labels.severity | toUpper }}`\nMonitoring host: {{ .Labels.monitor }}\n{{ .Annotations.description }}\n{{ end }}" opsgenie_configs: - priority: P3 - name: 'critical' slack_configs: - send_resolved: true title_link: 'https://monitor.example.com/prometheus/alerts' title: '{{ if eq .Status "firing" }}:scream:{{ else }}:dancing_panda:{{ end }} [{{ .Status | toUpper }}] {{ .CommonAnnotations.summary }}' text: "{{ range .Alerts }}*Priority*: `{{ .Labels.severity | toUpper }}`\nMonitoring host: {{ .Labels.monitor }}\n{{ .Annotations.description }}\n{{ end }}" opsgenie_configs: - priority: P1
И собственно “маршрутизация” алертов выполняется в блоке route
:
... route: group_by: ['alertname', 'cluster', 'job', 'env'] repeat_interval: 24h group_interval: 5m # capture All Dev + All INFO receiver: 'default' routes: # capture All WARN to the 'warning' with P3 - match: severity: warning receiver: warning routes: # forward Dev WARN to the 'default' - match_re: env: .*(-dev).* receiver: default # capture All CRIT to the 'critical' with P1 - match: severity: critical receiver: critical routes: # forward Stage CRIT to the 'warning' - match_re: env: .*(-stage).* receiver: warning # forward Dev CRIT to the 'default' - match_re: env: .*(-dev).* receiver: default ...
Тут задаём дефолтный роут ‘default
‘ – все алерты, не попавшие под действия правил ниже – будут отправлены через него в ресивер default
, который выполняет отправку только в Slack.
Далее, описываем дополнительные маршруты:
- в
match
ловим алерты по тегуseverity: warning
- во вложенном роуте с помощью
match_re
проверяем значение тегаenv
– если в нём содержится “-dev” – то отправляем сообщение в ресиверdefault
- все остальные алерты с уровнем warning “возвращаются выше” – и отправляются в
receiver: warning
Аналогично поступаем на следующем уровне – ловим алерты с severity: critical
, и проверяем их:
- если
env: .*(-stage).*
– шлём вwarning
- если
env: .*(-dev).*
– вdefault
- все остальные (остаёся env == production и severity == critical) – отправляем в ресивер
critical
Таким же образом можно писать любые условия по тегам, и использовать любое количество вложенных проверок для выбора дальнейшего маршрута алерта.