Красивые дашборды нравятся всем, пока сервер работает. Как только ночью падает база или диск заполняется на 95 процентов, выясняется неприятная правда: графики молча рисуют проблему, но никого не будят. Между "видеть метрику" и "узнать о сбое вовремя" лежит отдельный механизм доставки алертов, и в связке с Grafana его обычно закрывает Alertmanager. Статья собирает рабочую конфигурацию целиком: правила в Grafana, доставка в Telegram и на email, группировка потоков уведомлений и проверка всей цепочки тестовым срабатыванием.

Как устроена цепочка доставки алертов от сбоя до уведомления

Механизм состоит из трёх независимых ролей. Правила алертов решают, что считать проблемой: они смотрят на метрики и переводят числа в события с текстом и метками. Служба доставки принимает события, группирует их, гасит повторы и выбирает маршрут: кому, каким каналом и с каким приоритетом. Приёмники - это конечные точки, например чат в Telegram или почтовый ящик администратора.

Возникает вопрос: зачем Grafana отдельная служба доставки, если уведомления можно слать прямо из правил. Ответ в поведении при реальном сбое. Упавший маршрутизатор генерирует десятки событий сразу: недоступность узла, потеря метрик, срабатывание проверок на всех серверах за ним. Без промежуточного звена администратор получает лавину одинаковых сообщений вместо одного понятного. Alertmanager собирает поток в компактные группы, ждёт короткую паузу на случай соседних событий, подавляет следствия при наличии более серьёзной причины и повторяет напоминание не чаще заданного интервала. В спокойном режиме эти детали не видны, в аварийном они экономят часы.

У события есть жизненный цикл из двух состояний. Пока нарушено условие, но выдержка по времени не истекла, событие числится pending и никуда не отправляется: краткий всплеск загрузки не должен будить никого. После истечения выдержки событие становится firing и попадает в службу доставки. К нему приложены метки вроде severity и instance, по которым строится маршрутизация, и аннотации с человеческим текстом. Понимание этих двух состояний экономит много времени при отладке: событие "висит, но не приходит" почти всегда означает, что правило просто не дозрело.

Установка Alertmanager рядом с Prometheus и разбор базового файла конфигурации

В Ubuntu 24.04 служба ставится из репозитория пакетом prometheus-alertmanager и сразу регистрируется в системе инициализации. В ручном варианте скачивают официальный архив, распаковывают в /opt и пишут юнит на пять строк - оба пути дают одинаковый результат, различие только в удобстве будущих обновлений. После запуска служба слушает порт 9093, и этот порт не открывают наружу без веской причины: веб-интерфейс умеет ставить паузы, но не умеет защищать себя всерьёз.

Здоровье установки проверяется тремя командами подряд.

sudo apt install prometheus-alertmanager
sudo systemctl enable --now prometheus-alertmanager
curl -s localhost:9093/-/ready

Ответ ready от последней команды означает, что служба прочитала конфигурацию и готова принимать события. Если Prometheus уже развёрнут, ему указывают адрес соседа в его собственном конфигурационном файле секцией alerting, и с этой секунды все сработавшие правила потекут в службу доставки автоматически.

Ключевой файл - /etc/prometheus/alertmanager.yml, и в минимальном рабочем виде он описывает две вещи: параметры отправки и маршруты. Пример конфигурации с почтой и Telegram выглядит так.

global:
  resolve_timeout: 5m
  smtp_smarthost: "mail.example.com:587"
  smtp_from: "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript."
  smtp_auth_username: "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript."
  smtp_auth_password: "пароль-ящика"

route:
  receiver: email-all
  group_by: ["alertname", "instance"]
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  routes:
    - matchers:
        - severity="critical"
      receiver: telegram-admin
    - matchers:
        - severity="warning"
      receiver: email-all

receivers:
  - name: email-all
    email_configs:
      - to: "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript."
        send_resolved: true
  - name: telegram-admin
    telegram_configs:
      - bot_token: "токен-бота"
        chat_id: 123456789
        send_resolved: true
        parse_mode: "HTML"

Смысл маршрутизации читается сверху вниз. Событие с меткой severity уровня critical уходит в Telegram, прочие предупреждения собираются в почтовые письма. Поле group_wait в 30 секунд даёт соседним событиям шанс приехать вместе, group_interval ограничивает частоту пополнений группы, repeat_interval заставляет службу напоминать о невылеченной проблеме каждые четыре часа. Флаг send_resolved отправляет сообщение о восстановлении, и по опыту это половина ценности алертов: знать, когда стало спокойно, не менее важно, чем знать о факте сбоя.

Регистрация бота в Telegram и получение идентификатора чата для отправки

Доставка в мессенджер идёт через бота, и бот создаётся за пару минут. В поиске Telegram находят штатного служебного бота платформы, командой /newbot регистрируют нового, задают отображаемое имя и короткий идентификатор. В ответ приходит длинный токен вида цифры и буквы через двоеточие - он единственный секрет, который нужен для отправки, и хранить его стоит с правами 600 там же, где пароли сервера.

Идентификатор чата добывается технически. Боту отправляют любое сообщение из нужного чата, затем вызывают метод API сбора обновлений и читают поле chat.id в ответе.

curl -s https://api.telegram.org/botТОКЕН/getUpdates | jq '.result[0].message.chat.id'

Для личных чатов идентификатор положительный, для групповых начинается с минуса, и отсутствие знака в конфигурации - самая частая причина, по которой сообщения тихо не доходят. Проверить отправку руками можно тем же curl методом sendMessage, подставив идентификатор и текст. Полезная привычка - отдельный чат для алертов и отдельный бот на каждый контур: продакшен и тестовая площадка не должны смешивать потоки, иначе среди учебных срабатываний теряется настоящее.

Токен ведёт себя как пароль с одной кнопкой отключения. Утёкший в репозиторий или скриншот токен отзывается через того же служебного бота командой ревокации, после чего доставка остановится у всех, включая законного владельца, и токен придётся вписывать заново. Поэтому конфигурацию с токеном не хранят в открытых репозиториях, а на сервере файлу выставляют права 600 и владельца из-под которого работает служба.

Правила алертов в Grafana и связка с контактами доставки

Grafana строит правила в разделе алертов и умеет доставлять уведомления двумя способами. Первый - контактные точки самой Grafana, где среди типов доступен и Alertmanager, и мессенджер напрямую. Второй - правила Prometheus, а Grafana остаётся витриной. Практика контуров небольшого размера выбирает единые правила в Grafana и точку доставки типа Alertmanager: вся маршрутизация живёт в одном файле, а панели служат источником выражений.

Типовое правило для загрузки процессора формулируется выражением на языке запросов и порогом. Например, событие срабатывает, когда средняя загрузка узла держится выше 90 процентов пять минут подряд. К правилу добавляются метки severity и team, по ним маршрутизатор и раскладывает события по приёмникам. Набор здравых порогов для начала выглядит скромно и покрывает большинство ночных историй: процессор 90 процентов на 5 минут, доступная память ниже 10 процентов, свободное место на разделе меньше 15 процентов, служба или контейнер недоступен 2 минуты. Список расширяется по мере знакомства с характером конкретной инфраструктуры, и первая ошибка начинающих - десятки правил с порогами на грани шумов.

Какие пороги выбрать для правил и как оформить текст уведомления

Выражения для базового набора проверок выглядят компактно и читаются как обычная арифметика.

# процессор: средняя загрузка выше 90 процентов на пятиминутном окне
(1 - avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m]))) > 0.90

# память: доступно меньше 10 процентов от общего объёма
(node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) < 0.10

# диск: свободно меньше 15 процентов на корневом разделе
(node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) < 0.15

Если правила живут в Prometheus, а Grafana подключена к нему как витрина, тот же порог оформляется файлом правил с выдержкой времени и аннотациями.

groups:
  - name: host
    rules:
      - alert: HighCPU
        expr: (1 - avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m]))) > 0.90
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Загрузка процессора выше 90 процентов"
          description: "Узел держит высокую загрузку дольше пяти минут"

Текст уведомления оформляют по правилу первой строки: сразу кто, что и насколько. Хороший шаблон начинается с имени узла и метрики, продолжает конкретной цифрой и заканчивается ссылкой на панель. Сравните "проблемы на сервере" и "web-1, свободно 9 процентов на разделе /var, порог 15 процентов": вторая формулировка позволяет начинать действовать до открытия дашборда. Эмоциональные обороты в алертах не работают, конкретные числа работают всегда.

Группировка, подавление и паузы в правилах маршрутизации

Кроме группировки маршрутный файл поддерживает подавление следствий. Классическая пара: событие "узел недоступен" уровня critical подавляет все предупреждения с этого же узла, потому что они не самостоятельные проблемы, а эхо. Правило описывается в секции inhibit_rules и экономит администратору десятки сообщений при падении одной машины.

inhibit_rules:
  - source_matchers:
      - severity="critical"
    target_matchers:
      - severity="warning"
    equal: ["instance"]

Паузы закрывают третью бытовую ситуацию: плановые работы. Кнопка Silence в веб-интерфейсе на 9093 глушит события по фильтрам на заданное время, например на два часа обслуживания базы. У пауз есть инструмент командной строки amtool, им ставят и снимают паузы из скриптов, а заодно проверяют синтаксис файла конфигурации командой amtool check-config - она ловит ошибку в YAML до перезапуска службы, что при удалённом администрировании стоит дорого.

Дисциплина работы с паузами - отдельная часть культуры дежурства. Хорошая пауза имеет автора, причину и конечный срок, а бесконечных пауз не существует: сочетание фильтров, отключённое на месяц, превращается в тихую дыру, через которую уходит настоящий сбой. Раз в месяц список активных пауз пересматривают целиком и вычищают забытые записи, это занимает пять минут и защищает от слепых зон лучше любого нового правила.

Проверка цепочки тестовым алертом и типичные ошибки интеграции

Собранную связку проверяют по шагам, и каждый шаг отсекает свой класс ошибок. Порядок выглядит так:

  1. amtool check-config подтверждает, что файл маршрутизации читается без синтаксических ошибок;
  2. в веб-интерфейсе 9093 отправляется тестовое событие и фиксируется приход в оба приёмника;
  3. в Grafana создаётся заведомо срабатывающее правило, например порог загрузки в 1 процент;
  4. после доставки тестовое правило гасится до нормальных порогов, а история событий сверяется в списке алертов.

Диагностика идёт по цепочке от источника к приёмнику. Журнал службы показывает очередь отправок и ошибки доставки, читается он командой journalctl с ключом -u для юнита prometheus-alertmanager и -f для слежения в реальном времени. Список активных событий с метками показывает amtool alerts, а веб-интерфейс хранит историю с фильтрами по приёмникам. Если событие есть в списке, но сообщения нет, проблема в конфигурации приёмника; если события нет вовсе - смотрят правило и метрики на шаг раньше.

Из повторяющихся граблей стоит помнить четыре. Идентификатор группового чата без минуса, из-за чего доставка молчит при валидном токене. Почта через порт 25, который у большинства провайдеров закрыт исходяще - решением служит 587 с авторизацией и шифрованием. Токен бота в YAML без кавычек, где двоеточие внутри ломает структуру файла. Открытый наружу порт 9093 как единственная защита веб-интерфейса - при доступе из интернета паузы ставит кто угодно, поэтому интерфейс прячут за обратный прокси или туннель администратора. Рабочая связка Grafana, Alertmanager, Telegram и почты собирается за вечер, после чего мониторинг начинает разговаривать с администратором сам, а не наоборот.