Error budget в VictoriaMetrics: recording rules, burn-rate алерты и одна честная панель
Как мы собрали error budget для сервисов первого уровня из уже существующих метрик: SLO-цели по сервисам, multi-window burn-rate алерты, ряд в Grafana — и почему отрицательный бюджет сразу после запуска не был инцидентом.
В Gambchamp нам нужен был error budget для сервисов первого уровня одной продуктовой платформы — что-то, что видно с одного взгляда и на что можно алертить. Предлагали слэш-команду в чате, которая печатала бы бюджет. Мы выбрали панель в Grafana — данные уже лежали в VictoriaMetrics, а новый бот означает новый сервис, новый токен и ещё одну вещь, которую надо держать живой.
SLI и цели
SLI взяли самый простой и честный: доля ответов без 5xx. У каждого сервиса своя цель, записанная до того, как появилось хоть одно правило. Правила легли в отдельную группу для этой платформы, так что общие правила алертов остались нетронутыми.
Три recording rules
slo:target_error:ratio{app,cluster}— допустимая доля ошибок (1 − SLO) по сервису, собранная черезlabel_replace(vector(x), ...), объединённыеor;slo:errors:ratio_rate30d— реальная доля ошибок за 30 дней, записанная как... or 0 * total, чтобы сервис без ошибок показывал 0, а не пустую серию;slo:error_budget:remaining_ratio30d = 1 - ratio30d / target— 1 значит полный бюджет, 0 — израсходован, меньше нуля — перерасход.
Поскольку цель несёт те же метки {app, cluster}, что и серия ошибок, каждое сравнение — чистый join один к одному.
Burn-rate алерты
Multi-window, multi-burn-rate, классическая схема из SRE workbook:
- быстрый: сгорание 14.4× за 5 минут и за час, critical,
for: 2m; - медленный: сгорание 6× за 30 минут и за 6 часов, warning,
for: 15m.
Рядом — простые RED-правила на симптомы: p99 латентности выше секунды, но только с порогом по трафику (один медленный запрос простаивающего сервиса — не инцидент), «нет трафика» для сервисов нулевого уровня и «метрика пропала».
Панель
Один ряд: stat по каждому сервису плюс тренд, пороги — красный ниже 0, оранжевый ниже 0.2, зелёный выше. Ряд ушёл в code-first генератор дашбордов, а не в UI Grafana — правки в UI перезаписываются при следующем деплое.
Бюджет −26 %, и всё в порядке
Сразу после запуска один платёжный сервис показал бюджет −26 %. Выглядело тревожно. Всё это дал один всплеск в день запуска: около 2 100 ошибок депозита за 9,5 часа, несколькими неделями раньше. 30-дневное окно просто его включало. Бюджет вылечился бы сам, как только тот день выйдет из окна. Burn-rate алерты, которые смотрят на короткие окна, всё это время молчали — и это правильно.
Мелочи, которые полезно знать
- Recording rule, построенное на других recording rules, появляется на несколько циклов вычисления позже: входные серии сначала должны записаться и стать доступными для запроса. Это не баг.
- vmalert нужен
-remoteWrite.url, иначе результаты recording rules уходят в никуда. - Дашборд читает серию
ALERTSиз TSDB, а не из какого-либо Alertmanager, так что последующее разделение каналов уведомлений на него не повлияло.
Выводы
- Начинайте с метрик, которые уже есть; SLO не требует нового сервиса.
- Сделайте так, чтобы случай «ошибок нет» возвращал 0, а не пустую серию, иначе все правила ниже по цепочке тихо ломаются.
- Burn rate — для пейджинга, 30-дневный бюджет — для планирования. Они отвечают на разные вопросы.
- Сразу после запуска 30-дневное окно искажено ошибками периода запуска. Знайте, когда они выйдут из окна, прежде чем паниковать.