5. SLA, SLO, SLI
От инженерных метрик к бизнес-надежности
«Если поставить себе цель 100% надежности, вы никогда больше не выпустите в свет ничего нового».
— Бен Трейнор (основатель Site Reliability Engineering в Google)
В предыдущих статьях мы подробно изучили, как измерять поведение системы: научились настраивать Counter, собирать перцентили через Histogram и фильтровать измерения лейблами. Но здесь инженера подстерегает опасная иллюзия: легко увешать экран десятками графиков CPU, IOPS и свободной памяти, забыв о главном вопросе: «А доволен ли пользователь сервиса?».
Процессор может быть загружен всего на 2%, память свободна на 90%, а база данных рапортует об идеальном состоянии. Но если при этом упал ingress-контроллер или шлюз платежной системы, и ни один покупатель не может оформить заказ — ваша система на 100% мертва для бизнеса.
Чтобы перекинуть надежный мост между техническими датчиками (железом, рантаймом Go) и реальной ценностью для пользователей, инженеры Google в рамках практики Site Reliability Engineering (SRE) разработали стройный математический фреймворк: SLI, SLO и SLA.
Иерархия надежности
Три этих акронима образуют строгую восходящую пирамиду понятий:
flowchart TD
A["SLI<br>Service Level Indicator"] -->|"Измеряет"| B["Что происходит?<br>(Фактическая метрика)"]
C["SLO<br>Service Level Objective"] -->|"Цель"| D["Что мы обещаем?<br>(Инженерная норма)"]
E["SLA<br>Service Level Agreement"] -->|"Контракт"| F["Что будет,<br>если нарушим?<br>(Юридические последствия)"]
A --> C
C --> E
style A fill:#1e293b,stroke:#38bdf8,stroke-width:2px,color:#fff
style C fill:#312e81,stroke:#818cf8,stroke-width:2px,color:#fff
style E fill:#78350f,stroke:#f59e0b,stroke-width:2px,color:#fff
1. SLI (Service Level Indicator) — Индикатор
Это метрика, которая непосредственно отражает поведение системы с точки зрения пользователя.
SLI должен отвечать на вопрос: «Было ли обслуживание успешным?».
В качестве SLI выбираются не абстрактные аппаратные ресурсы, а пользовательский опыт:
- Доступность (Availability): Доля успешных ответов (HTTP 200) от общего числа запросов.
- Задержка (Latency): Доля запросов, обработанных быстрее порогового значения (например, 100мс).
- Пропускная способность: Количество запросов в секунду.
2. SLO (Service Level Objective) — Цель
Это целевое значение для SLI. Это договоренность внутри команды и с бизнесом о том, что считается «нормальной работой».
- Пример: «99.9% запросов должны возвращаться успешно за месяц».
- Пример: «99% запросов должны обрабатываться быстрее 200мс».
SLO — это инструмент управления ожиданиями. Если SLO выполняется, пользователи счастливы. Если нет — нужно звать на помощь.
Критически важно понимать: SLO никогда не должен быть равен 100%. 100% надежности в реальном мире не существует — падают кабели под океанами, сбоит память серверов, пользователи выходят в метро и теряют связь. Попытка добиться 100% доступности стоит экспоненциально дорого и намертво останавливает разработку новых фич.
3. SLA (Service Level Agreement) — Соглашение
Это формальный контракт с клиентом (часто финансовый), описывающий последствия нарушения SLO.
- «Если доступность упадет ниже 99.9%, мы вернем 10% стоимости подписки».
Error Budget (Бюджет ошибок)
Самая мощная концепция, вытекающая из SLO — Error Budget.
Если ваша цель (SLO) — 99.9% доступности, то у вас есть 0.1% «бюджета» на ошибки.
Физическая аналогия: бюджет на отпуск или бензобак автомобиля. Вы можете тратить бензин на быстрые обгоны (деплои и рискованные архитектурные эксперименты), пока в баке есть топливо. Но если стрелка на нуле — автомобиль обязан снизить скорость и двигаться только на станцию техобслуживания.
Зачем это нужно?
- Скорость разработки vs Стабильность: Если бюджет полон (ошибок мало) — можно смело деплоить новые фичи, рисковать, проводить рефакторинг. Если бюджет исчерпан (вы на грани нарушения SLO) — разработка замораживается, команда занимается только баг-фиксами и стабильностью.
- Объективные решения: Больше не нужно спорить «можно ли деплоить в пятницу?». Смотрим на Error Budget. Если он есть — можно. Если нет — нельзя.
Расчет бюджета:
Для SLO 99.9% за 30 дней:
$$ 30 \times 24 \times 60 \times 60 \times 0.001 \approx 43.2 \text{ минуты простоя в месяц} $$
Это значит, что все сбои в сумме не должны превышать 43 минуты в месяц.
Для трех девяток с половиной (99.95%) бюджет составляет всего 21.6 минуты, а для четырех девяток (99.99%) — жалкие 4.3 минуты за целый месяц!
Реализация SLO в Prometheus
Как превратить эти абстрактные цифры в работающие алерты?
SLI: Доступность (Availability)
Мы используем Counter'ы успешных и неуспешных запросов.
# SLI: Доля успешных запросов (HTTP 2xx, 3xx) за последние 7 дней
sum(rate(http_requests_total{status!~"5.."}[7d]))
/
sum(rate(http_requests_total[7d]))
SLO: Проверка цели
Если мы хотим узнать, соблюдается ли SLO 99.9%, мы сравниваем SLI с константой.
# Возвращает 1, если SLO соблюдается, 0, если нарушен
(sum(rate(http_requests_total{status!~"5.."}[7d])) / sum(rate(http_requests_total[7d]))) >= 0.999
Alerting: Burn Rate (Скорость сжигания бюджета)
Стандартный алерт rate(errors) > X плох тем, что он шумный. Методология SLO предлагает использовать Burn Rate (Скорость сжигания бюджета ошибок).
Burn Rate = 1 означает, что вы тратите бюджет ошибок ровно с той скоростью, при которой он иссякнет ровно к концу отчетного периода (за 30 дней).
Burn Rate = 14.4 означает, что 100% месячного бюджета сгорит всего за 2 дня (5% бюджета сгорает за 1 час).
Мы создаем алерты, которые срабатывают, если мы тратим бюджет слишком быстро. Если бюджет на месяц — 43 минуты, то потратить его за 1 час — это катастрофа, а потратить за 29 дней — это норма.
Для этого используется библиотека slo-libsonnet в Jsonnet или готовые рекурсии в Grafana, но принцип один: сравниваем короткое окно (fast burn) с длинным (slow burn).
Если быстрый burn rate подтверждается длинным окном — мы будим дежурного инженера среди ночи (Page alert). Если burn rate низкий — заводим тикет на утро (Ticket alert).
Mechanical Sympathy: Точность измерений
При измерении Latency как SLI важно помнить о природе времени в Go.
Использование time.Since(start) включает:
- Время выполнения бизнес-логики.
- Время работы GC (Garbage Collector).
- Время на планирование (если горутина долго ждала процессор).
Если вы используете Histogram в Prometheus, вы получаете агрегированные данные. Но выбор бакетов (Buckets) критичен.
- Если ваш SLO — 100мс, у вас обязан быть бакет
0.1. - Если бакетов нет рядом с SLO, вы не сможете точно посчитать, сколько запросов попало в норму.
Вспомним, как Prometheus выполняет функцию histogram_quantile: внутри корзины он делает линейную интерполяцию. Если у вас есть корзины 0.05 и 0.5, а порог SLO равен 0.2, Prometheus предположит равномерное распределение между 50 мс и 500 мс, что приведет к чудовищной математической погрешности!
// Правильный выбор бакетов под SLO 200ms
Buckets: []float64{.01, .05, .1, .2, .5, 1} // Бакет .2 (200ms) критически важен
Четкое попадание границы корзины в целевой порог SLO позволяет вычислять SLI задержки простой арифметической операцией без вызова тяжелой интерполяции:
$$\text{Latency SLI} = \frac{\text{rate}(http\_request\_duration\_seconds\_bucket\{le="0.2"\}[5m])}{\text{rate}(http\_request\_duration\_seconds\_count[5m])}$$
Итог
- SLI — это измерение (метрика).
- SLO — это цель (бизнес-требование).
- SLA — это последствия (контракт).
- Error Budget — это инструмент балансировки между скоростью разработки и стабильностью.
Переход от «мониторинга железа» (CPU/RAM) к «мониторингу пользовательского опыта» (SLI/SLO) — это маркер зрелости Senior-инженера.
Раздел метрик завершен. Мы переходим к следующему столпу Observability — Логированию. В следующей статье мы разберем, почему современные системы требуют структурированного подхода: 1. Structured logging.