← Все статьи

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-дневное окно искажено ошибками периода запуска. Знайте, когда они выйдут из окна, прежде чем паниковать.