# Шаблон конфигурации 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: # Если хост целиком недоступен, не сыпать отдельно про каждый его # warning-сервис. `target_matchers` НАМЕРЕННО ограничен одним warning # (#3471): раньше сюда попадал и critical, и падение node-exporter молча # гасило заодно PostgresLongTransactionCritical и все critical cAdvisor- # алерты того же хоста — самое важное сообщение исчезало вместе с шумом, # который оно должно было подавить. Warning того же хоста подавлять по- # прежнему стоит (диск/память/своп неотличимы от «нет данных»), а critical # обязан пережить это подавление и дойти до дежурного отдельно. - source_matchers: [alertname = "HostAgentDown"] target_matchers: [severity = "warning"] 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: | ⚪ Мониторинг жив — сторож отчитался, канал доставки работает. Если это сообщение перестало приходить дважды подряд, замолчал сам мониторинг.