Есть три рабочих окружения — 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
Таким же образом можно писать любые условия по тегам, и использовать любое количество вложенных проверок для выбора дальнейшего маршрута алерта.




