SLO на Prometheus: первый error budget и что он нам показал
Внедрили SLI/SLO поверх Prometheus для нескольких сервисов. Первый error budget неожиданно показал, что 80% инцидентов сосредоточены в трёх местах.
Культура SRE активно распространяется: Google SRE Workbook опубликован в 2018 и широко обсуждается в сообществе
Google SRE Workbook вышел в 2018 году и с тех пор не сходит с повестки ни одной конференции по эксплуатации. Идея SLO как инструмента приоритизации звучит убедительно: вместо того чтобы чинить всё подряд, договариваешься об уровне сервиса, считаешь error budget, и только потом решаешь, куда вкладывать усилия. На бумаге очень разумно. На практике - нужно сесть и сделать.
Мы взяли один из managed-проектов и попробовали внедрить SLI/SLO не как декларацию, а как реально работающие метрики с Prometheus и Alertmanager.
Что хотели получить
Задача была не философская. У команды накопилась усталость от «дежурства по ощущениям»: алертов много, приоритеты непонятны, каждый инцидент ощущается одинаково срочным. Хотелось ответить на простой вопрос: в каком месте системы боль концентрируется сильнее всего, и есть ли ещё запас по ошибкам или мы уже в минусе.
SLI выбрали стандартные для HTTP-сервисов: доля успешных запросов (success rate) и латентность на 99-м перцентиле. Целевые значения согласовали с заказчиком: 99,5% успешных запросов за скользящее окно 30 дней, p99 не выше 500мс для критичных эндпоинтов.
Данные уже были в Prometheus - он скрейпил метрики через http_requests_total с лейблами status и service. Это хорошо. Плохо было то, что часть сервисов метрики не отдавала вообще, а часть - отдавала в неконсистентном формате.
Как считали error budget в PromQL
Основной recording rule для success rate выглядит примерно так:
sum(rate(http_requests_total{status!~"5.."}[5m])) by (service)
/
sum(rate(http_requests_total[5m])) by (service)
Для error budget за 30 дней брали накопленный счётчик и считали, сколько «ошибочных» запросов ещё допустимо по целевому SLO. Логика: если SLO 99,5%, то из 1000 запросов допустимо 5 ошибочных. Если за 30 дней прошло X запросов - бюджет = X * 0,005.
Оставшийся бюджет мониторили как отдельную метрику. Alertmanager настроили так: при расходе 50% бюджета - warning в Slack, при 80% - page дежурному.
На это ушло примерно неделя плотной работы: настройка recording rules, отладка запросов, приведение метрик к общему виду для сервисов с несовместимыми лейблами. Один сервис пришлось переписывать кастомный exporter - он отдавал статус как строку «OK»/«FAIL» вместо HTTP-кода.
Что показал первый срез
Вот тут началось интересное. Как только данные за первые две недели набрались и мы построили нормальный дашборд в Grafana, стало видно: три сервиса из примерно пятнадцати потребляли подавляющую часть error budget. Остальные двенадцать - в зелёной зоне с большим запасом.
Это само по себе неудивительно. Удивительно другое: до внедрения SLO эти три сервиса не выглядели проблемными. Алерты по ним срабатывали регулярно, но вперемешку с алертами по остальным. Никто не воспринимал их как особо приоритетные - просто «фоновый шум».
Когда мы сопоставили инциденты за предыдущие три месяца с error budget - картина совпала. Примерно 80% инцидентов, которые требовали ручного вмешательства, приходились на эти три сервиса. Но мы не замечали этого, потому что инциденты разбросаны во времени и нет агрегации «а у чего статистически хуже всего».
Что поменяли в приоритетах
На ретро команда решила сфокусировать следующие два спринта на этих трёх сервисах: аудит зависимостей, анализ паттернов ошибок, улучшение таймаутов и retry-логики. Остальные задачи в беклоге - не трогаем.
Это звучит банально, но организационно сдвинуть это без данных было нереально. Всегда найдётся кто-то, кто скажет «а вот мой сервис тоже падал». С цифрами по error budget разговор становится конкретным.
Несколько вещей, которые стоит учитывать:
- Окно 30 дней - не единственный вариант. Для разных SLO имеет смысл смотреть и на недельные окна. За месяц можно не заметить аномалию, которая длилась три дня.
- Recording rules обязательны. Считать error budget налету по сырым метрикам на 30-дневном окне - Prometheus под нагрузкой это не любит. Recording rules на 5-минутный интервал и потом агрегация по ним - стандартный паттерн.
- Alertmanager routing. Алерт «потрачено 80% budget» должен попадать не в общий канал, а к конкретному ответственному за сервис. Иначе смысл теряется.
- Метрики должны быть консистентны. Треть работы по внедрению SLO - это приведение экспортеров к одному формату. Без этого ни одна PromQL-формула не работает честно.
Мы параллельно смотрели в сторону Istio как источника метрик - он отдаёт istio_requests_total с нужными лейблами прямо из sidecar, без изменений в приложении. После нашего опыта с Istio 1.2 это выглядит как разумный путь для новых сервисов.
SLO как инструмент работает. Не как серебряная пуля и не потому что Google так написал, а потому что заставляет перевести ощущение «что-то не то с системой» в конкретные числа - и потом разговаривать именно о них.