SLO и бюджет ошибок: как измерить надёжность
SLO и бюджет ошибок: как измерить надёжность
Логи, метрики и трейсы отвечают на вопрос «что происходит». Остаётся вопрос, на который они сами не отвечают: достаточно ли хорошо работает сервис.
Без числа этот спор бесконечен. Продукт говорит «пользователи жалуются», разработка говорит «у нас всё зелёное», и оба правы, потому что меряют разное. SLO превращает надёжность в договорённость с конкретной цифрой - и, что важнее, даёт объективное правило, когда останавливать релизы.
SLI / SLO / SLA - основа измерений
- SLI (Service Level Indicator) - конкретная метрика. «Доля запросов, обработанных быстрее 200ms».
- SLO (Service Level Objective) - внутренняя цель. «99.9% запросов за 200ms».
- SLA (Service Level Agreement) - договорное обязательство перед клиентом, обычно мягче SLO. «99.5%».
SLI: rate(http_requests_total{le="0.2"}) / rate(http_requests_total)
текущее значение: 99.2%
SLO: 99.9%
Бюджет ошибок (error budget): 100% - 99.9% = 0.1%
= 43 минуты простоя в месяц
Концепция error budget от Google SRE: если бюджет не исчерпан, можно деплоить новые фичи; если исчерпан - фокус на надёжности. Это объективный механизм торможения релизов без drama.
Почему 100% - неправильная цель
Соблазн поставить SLO 100% и «просто не падать» проходит после первой попытки это посчитать. Каждая девятка стоит примерно на порядок дороже предыдущей:
| SLO | Допустимый простой в месяц | Что для этого нужно |
|---|---|---|
| 99% | 7 часов 18 минут | один сервер, дежурство в рабочие часы |
| 99.9% | 43 минуты | резервирование, автоматический откат, дежурство 24/7 |
| 99.99% | 4 минуты 20 секунд | несколько зон доступности, автоматическое переключение |
| 99.999% | 26 секунд | человек физически не успевает вмешаться |
На последней строке дежурный уже не помогает: пока он читает уведомление, бюджет месяца исчерпан. Всё должно чиниться само, а это другой порядок сложности и стоимости системы.
Отсюда практическое правило: SLO выбирают чуть выше того, что пользователь замечает, и чуть ниже того, что вы можете обеспечить без героизма. Если пользователи не жалуются при 99.5%, ставить 99.99% - значит тратить кварталы инженерного времени на то, чего никто не заметит.
SLO в коде
Концепция «error budget burn rate» - насколько быстро мы тратим бюджет ошибок. Алерт на быстрый burn срабатывает, когда за 1 час потрачено 2% месячного бюджета - это тревожный сигнал ещё до полного исчерпания.
# 1h burn rate = errors_per_hour / monthly_budget
1h_error_rate / (1 - 0.999)
Error budget policy: что происходит, когда бюджет кончился
Бюджет ошибок бесполезен, пока заранее не записано, что делать при его исчерпании. Иначе разговор каждый раз начинается с нуля и заканчивается тем, что релиз всё-таки выкатывают.
Работающая политика выглядит примерно так:
- бюджет израсходован меньше чем на половину - выкатываем как обычно;
- израсходовано больше половины - рискованные изменения едут с флагом функциональности и планом отката, миграции схемы - только в тихое время;
- бюджет исчерпан - заморозка новых функций, вся команда работает над надёжностью, пока бюджет не восстановится в следующем периоде;
- бюджет исчерпан второй период подряд - это уже не инцидент, а системная проблема: пересматриваем либо архитектуру, либо сам SLO.
Ключевое здесь - что правило записано до инцидента и одинаково для всех. Тогда заморозка релизов перестаёт быть чьим-то волевым решением и становится следствием цифры, с которой все согласились заранее.
Multi-window multi-burn-rate alerts
Простой алерт «error rate > 1% за 5 минут» имеет проблемы: на маленьком RPS вы либо ловите false positives при единичных ошибках, либо пропускаете медленное сжигание SLO. Google SRE Workbook предлагает решение - алерты по нескольким окнам с разными burn rate.
Burn rate - насколько быстрее, чем заложено в SLO, тратится бюджет ошибок. Если SLO 99.9%, бюджет 0.1%. Текущий error rate 0.5% = burn rate 5× (тратим бюджет в 5 раз быстрее, исчерпаем за 30/5 = 6 дней вместо 30).
groups:
- name: slo-burn-rate
rules:
# Быстрое сжигание: пейджер
- alert: ErrorBudgetBurnFast
expr: |
(
job:error_rate:ratio5m{job="api"} > (14.4 * 0.001)
and
job:error_rate:ratio1h{job="api"} > (14.4 * 0.001)
)
for: 2m
labels: {severity: critical}
annotations:
summary: "SLO budget burns at 14.4× rate (1h window)"
# Медленное сжигание: тикет
- alert: ErrorBudgetBurnSlow
expr: |
(
job:error_rate:ratio30m{job="api"} > (6 * 0.001)
and
job:error_rate:ratio6h{job="api"} > (6 * 0.001)
)
for: 15m
labels: {severity: warning}
annotations:
summary: "SLO budget burns at 6× rate (6h window)"
Конкретные коэффициенты из SRE Workbook: 14.4× за 1h (page) - означает «при таком burn 2% бюджета будет потрачено за 1 час»; 6× за 6h (ticket) - «5% за 6 часов». Условие AND с коротким окном фильтрует point-in-time всплески: если за 5 минут плохо, но за 1 час всё ОК - это, скорее всего, шум.
Как выбрать SLI, который что-то значит
Метрика для SLI должна отражать опыт пользователя, а не удобство измерения. Загрузка процессора - плохой SLI: пользователю всё равно, сколько у вас CPU, пока страницы открываются. Доля успешных ответов быстрее порога - хороший: именно это человек и чувствует.
Три вопроса, которые отсеивают неподходящие метрики:
- Заметит ли пользователь ухудшение этой метрики? Если нет, это метрика для диагностики, а не для SLO. Ей место на дашборде, а не в цели.
- Можно ли на неё повлиять? SLI, зависящий целиком от внешнего сервиса, превращает бюджет ошибок в лотерею: команда тратит его на чужие сбои и ничего не может сделать.
- Однозначно ли считается граница? «Быстро» надо перевести в число. Порог обычно берут из наблюдений: смотрят, при какой задержке пользователи начинают уходить или жаловаться, и ставят SLO чуть строже.
Для типичного HTTP-сервиса рабочий набор - два SLI: доступность (доля ответов не-5xx) и задержка (доля ответов быстрее порога). Добавлять третий стоит только тогда, когда есть отдельный сценарий, который эти два не покрывают, - например, свежесть данных для отчёта, который строится асинхронно.
Итоги
- ✅ Различать SLI (что меряем), SLO (наша цель) и SLA (обещание клиенту)
- ✅ Считать бюджет ошибок и понимать, сколько минут он даёт
- ✅ Выбирать реалистичный SLO, а не максимальный
- ✅ Настраивать алерты по скорости сжигания бюджета, а не по мгновенному проценту ошибок
Мини-практика
Возьми любой свой HTTP-сервис и сформулируй для него один SLI и один SLO. Посчитай бюджет ошибок в минутах на месяц. Затем напиши recording rule для этого SLI и два алерта по burn rate - быстрый и медленный, по образцу из этого урока.
Дальше - алерты, дежурство и разбор инцидентов.