{ "index": 151, "slug": "editorial-2023-10-field-sli-slo", "title": "SLI/SLO в релизном разговоре: от красного графика к проверяемому решению", "excerpt": "Как связать SLI, SLO и error budget с пользовательским путём, окном измерения и обратимым действием — и не выдать один график за доказательство инцидента или автоматический запрет релиза.", "contentHtml": "
В день релиза на панели краснеет error budget. Один инженер говорит: «бюджет почти закончился». Другой просит не задерживать исправление. On-call не может показать, какой пользовательский путь пострадал, за какой период считался показатель и какие события попали в знаменатель. Команда спорит о цвете, а не о данных.
\nЦена ошибки двойная. Шумный сигнал может остановить безопасное изменение. Слишком узкий SLI может пропустить отказ после точки измерения, и команда выпустит рискованный релиз. В обоих случаях SLO превращается в отчётность: число есть, но оно не подсказывает следующий безопасный шаг.
\nТезис статьи простой: error budget не принимает решение вместо команды. Он запускает проверяемую петлю. Сначала нужно подтвердить договор SLI: что измеряем, для кого, в каком окне и по какой формуле. Затем нужно проверить контекст и выбрать действие по policy. Только после этого можно обсуждать rollout, паузу или исправление.
\nSLI — количественная мера свойства сервиса. Например, доля запросов, которые завершились полезным результатом, или доля операций с задержкой ниже порога. SLO — целевое значение этой меры в заданных условиях. Error budget — допустимая часть неуспеха в том же договоре. Если target равен 99%, бюджет равен 1% eligible-событий за указанное окно.
\nФормула сама по себе ничего не решает. Для success ratio нужны как минимум scope, eligible count, good count, target и window. Scope задаёт путь пользователя и границу ответственности. Eligible определяет знаменатель. Good определяет успешный исход. Window задаёт период сравнения. Policy связывает состояние бюджета с действием и владельцем.
\neligible = 1000\ngood = 994\ntarget = 0.99\nactual = good / eligible // 0.994\nallowed_bad = eligible * (1 - target) // 10\nactual_bad = eligible - good // 6\nremaining = allowed_bad - actual_bad // 4\n\n// Все числа учебные. Источник событий отсутствует.\n// Результат не описывает production-доступность.\nВ этом примере остаются четыре условные единицы бюджета. Это арифметика модели, а не факт о сервисе. Если исключить отменённые операции, изменить окно или считать только ответы одного backend, результат станет другим. Поэтому процент без версии договора нельзя сравнивать с прошлым процентом и нельзя использовать как самостоятельную причину для блокировки.
\nПользователь оценивает путь, а не внутренний HTTP-ответ. Запрос может получить код 202, но очередь позже отклонит операцию. Backend может ответить быстро, пока клиент ждёт подтверждение в другом компоненте. Если SLI измеряет только первый ответ, он может быть технически точным и продуктово бесполезным.
\nСначала назовите действие пользователя: например, «отправить заказ и получить подтверждение». Затем определите границу: где путь считается завершённым, какие отказы входят в оценку, кто владеет источником событий. Если путь нельзя связать с наблюдаемым результатом, не объявляйте готовый SLO. Сначала сократите вопрос или добавьте нужный сигнал.
\nЗнаменатель также требует явного правила. Eligible-события нельзя выбирать по удобству. Если фильтр исключает таймауты, повторные попытки или отмены, запишите причину и отрицательный пример. Иначе команда улучшит процент удалением сложных случаев. Это не повышение надёжности, а изменение измеряемой популяции.
\nФиксированное окно проще объяснить: события с 1 по 28 число сравниваются с предыдущим таким же периодом. Скользящее окно быстрее показывает недавнее ухудшение, но каждый момент измерения содержит немного иной набор событий. В обоих вариантах нужно назвать часовой пояс, границы, задержку поступления событий и правило пересчёта.
\nНизкий трафик усиливает цену одного отказа. При десяти eligible-событиях один failure меняет ratio сильнее, чем при миллионе. Это не означает, что малотрафиковый путь нельзя измерять. Это означает, что порог, окно и способ реакции надо выбирать вместе. Иногда полезнее ticket и ручной разбор, чем срочное оповещение на каждое колебание.
\n| Симптом | Причина | Проверка | Действие |
|---|---|---|---|
| Процент стал красным | Неизвестны окно и версия формулы | Сверить SLI-contract, границы и период | Приостановить интерпретацию, запросить источник |
| Команды считают доступность по-разному | Разные eligible и good | Сравнить запросы, исключения и отрицательные случаи | Зафиксировать одну формулу и владельца |
| Процент хороший, путь сломан | SLI измеряет ранний backend-ответ | Пройти пользовательский сценарий до результата | Расширить scope или добавить отдельный SLI |
| Один отказ резко изменил ratio | Малое окно или низкий трафик | Посчитать eligible и проверить распределение событий | Выбрать устойчивое окно и ручной response |
| Красный график блокирует любой релиз | У policy нет исключений и владельца | Проверить обратимость, срочность и evidence | Сузить rollout, исправить, отложить или продолжить по policy |
Policy должна отвечать на пять вопросов. Какое состояние бюджета запускает разбор? Какие данные обязан принести владелец? Какое действие обратимо? Кто принимает решение? Когда команда пересматривает договор? Запись «при красном графике остановить всё» не отвечает ни на один вопрос до конца.
\nПрактичная ветка может выглядеть так: если формула или scope неизвестны, решение откладывают до проверки данных. Если договор подтверждён, но причина неясна, открывают разбор и уменьшают exposure рискованного изменения. Если budget exhausted, non-urgent rollout приостанавливают, а обязательное исправление оценивают отдельно с владельцем и планом отката. Если сигнал восстановился, повторяют ту же проверку; новый процент не должен появиться из другой формулы.
\nТакая policy не запрещает каждый релиз. Она не разрешает и каждый релиз. Она задаёт минимальное evidence и оставляет полномочие у владельца. Security fix, изменение инфраструктуры и продуктовый rollout могут иметь разные уровни срочности, поэтому один универсальный gate создаёт ложную уверенность.
\nОдин SLI не объясняет корневую причину. Trace, log и dashboard помогают только тогда, когда они относятся к той же операции, версии и периоду. Корреляция не доказывает причинность. Красный budget не доказывает инцидент. Зелёный budget не доказывает, что весь пользовательский путь работает.
\nУчебная арифметика выше не читает файлы, часы, monitoring, CI, сеть, HTTP или production-конфигурацию. Она не создаёт alert, не меняет rollout и не выдаёт разрешение на выпуск. В реальной системе эти полномочия должны находиться в явно назначенных инструментах и runbook. Если команда не может проверить источник или обратить действие, это ограничение нужно записать до решения.
\nРазбор готов, когда другой инженер без устного контекста может воспроизвести число и понять решение. В записи есть пользовательский путь, версия формулы, eligible и good, target, окно, источник, владелец, выбранное действие, план отката и повторная проверка. Есть хотя бы один отрицательный пример: событие, которое нельзя молча исключить, или путь, который текущий SLI не покрывает.
\nРелизный разговор также готов, если команда может ответить на три вопроса: что измеряем, почему этому сигналу можно доверять в данном решении и что произойдёт при ухудшении. Если на любой вопрос отвечает только цвет графика, договор ещё не готов.
\n