# Шаблон конфигурации Alertmanager. Боевой файл собирается на хосте при деплое
# (`envsubst` в deploy-metrics.yml) и в репозиторий не попадает — токен бота и
# идентификатор чата живут в окружении хоста, а не в git.
#
# ПОЧЕМУ TELEGRAM НАПРЯМУЮ, А НЕ ЧЕРЕЗ БЭКЕНД МЕРЫ. У МЕРЫ уже есть рабочий путь
# доставки (вебхук GlitchTip → бот), и соблазн переиспользовать его велик. Но тогда
# сообщение о том, что лёг Poincare, шло бы через сервис НА Poincare. Алерт обязан
# уметь уйти без участия хоста, про который он написан.
#
# Telegram с Beget работает — проверено серией замеров 25.08: TLS-рукопожатие
# 18 из 20, getMe 4 из 4. Ломается только длинный long-poll (30 с), а отправка
# сообщения — короткий запрос.
#
# ПОЧЕМУ ДВЕ ТЕМЫ, А НЕ ОДНА (#3163). Форум держит тему «алерты» (158,
# клиентские инциденты МЕРЫ) и тему «метрики» (245, инфраструктурный шум —
# диск, память, просевший экспортер). Инфраструктурный шум и клиентский
# инцидент не равны по срочности, а смешанные в одной теме они обучают
# пролистывать обе. Поэтому `telegram` и `telegram-heartbeat` ниже адресуют
# ИНФРАСТРУКТУРНУЮ тему (`METRICS_TELEGRAM_INFRA_TOPIC_LINE`). Получателя
# `telegram-clients` в этом списке нет: он не шлёт в Telegram напрямую, а
# вебхуком уходит в alert-ack, и тему адресует сам, своей переменной
# METRICS_TELEGRAM_TOPIC_ID.
global:
resolve_timeout: 5m
route:
receiver: telegram
# Группируем по алерту и хосту: пятнадцать контейнеров одного хоста, упавших
# разом, — это одно событие, а не пятнадцать сообщений.
group_by: ["alertname", "host"]
group_wait: 45s
group_interval: 5m
# Повтор раз в 6 часов. Чаще — приучает игнорировать, реже — можно проспать.
repeat_interval: 6h
routes:
# Watchdog не должен смешиваться с настоящими алертами и не должен молчать:
# это «сторож сторожа», он горит всегда и подтверждает, что канал доставки жив.
- receiver: telegram-heartbeat
matchers:
- alertname = "Watchdog"
group_wait: 0s
group_interval: 12h
repeat_interval: 12h
# Клиентский инцидент. host="apps" — это продуктовая машина: если на ней
# критично, значит МЕРА и Site Finder недоступны людям, а не «где-то в
# инфраструктуре тесно». Такое зовём поимённо и напоминаем часто.
#
# Почему отдельный маршрут, а не общий critical: 27.08 продукты лежали
# 10 часов, и разницы между «диск на 86 %» и «клиенты не могут открыть
# сайт» в канале не было никакой. Разный текст и разная настойчивость —
# это и есть разница.
#
# repeat_interval 30m против 3h у прочего критичного: пока инцидент не
# погашен, напоминание должно быть неудобным. Заглушить его — осознанное
# действие через Alertmanager, и оно же служит отметкой «принято».
- receiver: telegram-clients
matchers:
- severity = "critical"
- host = "apps"
group_wait: 10s
repeat_interval: 30m
# Прочее критичное — инфраструктура, клиенты пока не затронуты.
- receiver: telegram
matchers:
- severity = "critical"
group_wait: 10s
repeat_interval: 3h
inhibit_rules:
# Если хост целиком недоступен, не сыпать отдельно про каждый его сервис.
- source_matchers: [alertname = "HostAgentDown"]
target_matchers: [severity =~ "warning|critical"]
equal: ["host"]
receivers:
- name: telegram
telegram_configs:
- bot_token: "${METRICS_TELEGRAM_BOT_TOKEN}"
chat_id: ${METRICS_TELEGRAM_CHAT_ID}
${METRICS_TELEGRAM_INFRA_TOPIC_LINE}
api_url: "https://api.telegram.org"
parse_mode: HTML
send_resolved: true
message: |
{{ if eq .Status "firing" }}🔴{{ else }}🟢{{ end }} {{ .CommonLabels.alertname }}{{ if .CommonLabels.host }} · {{ .CommonLabels.host }}{{ end }}
{{ range .Alerts }}
{{ .Annotations.summary }}
{{ if .Annotations.description }}{{ .Annotations.description }}{{ end }}
{{ end }}
# Клиентский инцидент уходит В СЕРВИС, а не напрямую в Telegram.
#
# Alertmanager инлайн-клавиатуру не умеет, а без кнопки нет обратной связи
# «человек увидел и взял в работу». Сервис alert-ack (тот же хост, рядом)
# формирует сообщение с упоминанием дежурного и кнопкой подтверждения, а по
# нажатию отвечает в ту же тему «принято, кто, во сколько».
#
# ЧТО ПРОИСХОДИТ, ЕСЛИ СЕРВИС ЛЁГ. Alertmanager считает доставку неудачной и
# повторяет; плюс сам инцидент остаётся активным и переуведомляется каждые
# 30 минут (repeat_interval маршрута выше). То есть алерт задерживается, но
# не теряется. Это сознательный размен: дублировать то же сообщение вторым,
# прямым каналом означало бы два уведомления на каждый инцидент, а шум в
# канале тревог опаснее, чем задержка.
- name: telegram-clients
webhook_configs:
- url: "http://alert-ack:8080/alertmanager"
send_resolved: true
- name: telegram-heartbeat
telegram_configs:
- bot_token: "${METRICS_TELEGRAM_BOT_TOKEN}"
chat_id: ${METRICS_TELEGRAM_CHAT_ID}
${METRICS_TELEGRAM_INFRA_TOPIC_LINE}
api_url: "https://api.telegram.org"
parse_mode: HTML
send_resolved: false
message: |
⚪ Мониторинг жив — сторож отчитался, канал доставки работает.
Если это сообщение перестало приходить дважды подряд, замолчал сам мониторинг.