ADG Оставить заявку
Блог DevOps 5 мин чтения

Grafana 8.3/8.4 и unified alerting: мигрируем правила, собираем грабли

Grafana 8.3/8.4 переводит unified alerting в default. Рассказываем о миграции правил для нескольких клиентов: типичные ловушки, скрипт конвертации, новая структура каналов.

Контекст момента

Grafana 8.3/8.4: unified alerting стал движком по умолчанию, legacy alerting объявлен deprecated; новый редактор панелей; улучшения Loki datasource

Grafana 8.3 и следом 8.4 принесли одно принципиальное изменение: unified alerting теперь включён по умолчанию для новых инсталляций, а старый движок предупреждений объявлен legacy. Это не «старый добрый deprecated, живи ещё десять лет» - это реальный сигнал к действию, потому что миграция нетривиальна и тихо не пройдёт.

Мы ведём мониторинг для нескольких клиентов в рамках managed-сопровождения, и по части из них Grafana уже работала с alert-правилами на классическом движке. Решили не ждать пока это само рассосётся - пошли по стекам и перевели всё на unified alerting.

Что изменилось в архитектуре

Классический alerting был встроен прямо в Grafana: правила хранились в SQLite/PostgreSQL вместе с dashboard-ами, notification channels - там же. Unified alerting вводит отдельный слой - Grafana Alertmanager (или внешний Alertmanager, если уже есть). Правила теперь живут в папках-группах, привязаны к datasource через UID, а не к панели dashboard-а.

Ключевые структурные изменения:

  • Notification channels исчезли. Вместо них - contact points и notification policies. Contact point - это куда слать (Telegram, email, PagerDuty). Policy - дерево маршрутизации по лейблам алертов, определяющее какой contact point получит какое уведомление и с каким silence/mute-поведением.
  • Правила отвязаны от панелей. В классическом alerting правило жило прямо в панели и редактировалось там же. Теперь правила - отдельные сущности, панель может их отображать, но не содержит.
  • Grafana-managed alerts vs datasource-managed alerts. Unified alerting поддерживает два режима: правила, которые Grafana вычисляет сама (Grafana-managed), и правила, которые живут непосредственно в Prometheus/Loki (datasource-managed, через Ruler API). Это важно - если уже есть правила в Prometheus recording rules, их можно подключить без дублирования.

Что нашли при миграции

Инструмент экспорта есть - в Grafana 8.3 появилась кнопка в UI для миграции классических алертов в unified. На деле это работает для простых случаев. Для реальных стеков начинаются нюансы.

Первое - notification channels не конвертируются автоматически в contact points. Grafana создаёт обёртку-заглушку, но маршрутизацию (кто получает что) нужно выстраивать руками. Если было пять каналов с разными получателями для разных dashboard-ов - придётся вручную выстраивать policies.

Второе - правила с template-переменными. В классических алертах можно было использовать переменные dashboard-а в threshold-запросах. В unified alerting это не работает - правила самодостаточны и независимы от dashboard-а. Такие правила нужно переписывать, жёстко зафиксировав значения или параметризировав через labels.

Третье - multi-dimensional alerts. Unified alerting нативно поддерживает multi-dimensional: одно правило может генерировать алерты для каждого инстанса по отдельности через label-ы из PromQL. Классический движок так не умел - там было одно правило, один алерт. При миграции это надо использовать, а не пытаться воспроизвести старое поведение «один монолитный алерт на всё».

Четвёртое - silence не переносятся. Если были активные silence в классическом alerting - они пропадают. Нужно их зафиксировать и воссоздать руками.

Скрипт конвертации

Для ускорения миграции написали небольшой Python-скрипт, который тянет классические алерты через Grafana API (/api/alerts), строит для каждого unified-правило в формате provisioning YAML и раскладывает по папкам согласно dashboard-у источника. Это не полная автоматизация - на выходе получается заготовка, которую надо проверить глазами, - но экономит часы ручной работы при переносе двадцати-тридцати правил.

Грубая структура скрипта:

import requests, yaml, pathlib

GRAFANA_URL = "http://localhost:3000"
AUTH = ("admin", "password")

alerts = requests.get(f"{GRAFANA_URL}/api/alerts", auth=AUTH).json()

for alert in alerts:
    rule = {
        "title": alert["name"],
        "condition": "C",
        "data": [
            {
                "refId": "A",
                "datasourceUid": alert.get("dsUID", "__expr__"),
                "model": {"expr": alert.get("query", ""), "refId": "A"},
            }
        ],
        "noDataState": "NoData",
        "execErrState": "Alerting",
        "for": f"{alert.get('for', 300)}s",
        "labels": {},
        "annotations": {"summary": alert.get("message", "")},
    }
    folder = alert.get("dashboardSlug", "migrated")
    pathlib.Path(f"rules/{folder}").mkdir(parents=True, exist_ok=True)
    with open(f"rules/{folder}/{alert['id']}.yaml", "w") as f:
        yaml.dump({"apiVersion": 1, "groups": [{"name": folder, "rules": [rule]}]}, f)

Результат - набор YAML-файлов, которые можно положить в provisioning Grafana и загрузить без UI-кликов. Удобно особенно когда нужно воспроизвести правила на нескольких инсталляциях.

Улучшения Loki datasource в 8.3/8.4

Отдельно стоит отметить улучшения в Loki datasource - они напрямую влияют на алертинг по логам. В 8.3 появилась поддержка LogQL metric queries в alert-правилах: теперь можно писать правило вида «если за последние 5 минут в логах Nginx больше N строк с кодом 5xx - алерт». Раньше для этого нужно было либо тащить метрики отдельно через Prometheus recording rules, либо городить workaround через Loki Ruler.

Это закрывает реальный кейс: мониторинг по логам без дополнительной прослойки. На одном из клиентских стеков мы как раз убрали несколько вспомогательных recording rules в Prometheus, которые существовали только чтобы прокинуть агрегаты из логов в алерты.

Где сейчас

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

Unified alerting в целом - более правильная архитектура. Правила как код, provisioning через YAML, интеграция с внешним Alertmanager, multi-dimensional алерты - это то, чего в классическом движке не было и не появилось бы. Переход болезненный, но разовый.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.