8 lines
20 KiB
JSON
8 lines
20 KiB
JSON
{
|
||
"index": 151,
|
||
"slug": "editorial-2023-10-field-sli-slo",
|
||
"title": "SLI/SLO в релизном разговоре: от красного графика к проверяемому решению",
|
||
"excerpt": "Как связать SLI, SLO и error budget с пользовательским путём, окном измерения и обратимым действием — и не выдать один график за доказательство инцидента или автоматический запрет релиза.",
|
||
"contentHtml": "<p>На релизе график error budget становится красным. Один инженер предлагает остановить выкладку, другой просит не задерживать исправление. Но никто не может сразу ответить, какой пользовательский путь измеряет график, какие события входят в знаменатель и за какое окно посчитан расход. В итоге команда обсуждает цвет панели вместо проверяемого факта.</p>\n<p>Ошибка в такой ситуации стоит дорого в обе стороны. Слабый SLI может оставить сломанным путь, который сервер формально считает успешным. Нечёткая policy может остановить безопасное изменение из-за одного нерепрезентативного всплеска. Поэтому SLO полезен не как печать «можно» или «нельзя», а как часть петли: измерили, сравнили с целью, проверили контекст, выбрали действие, повторили измерение.</p>\n<p>Ниже — практический способ провести этот разговор. Сначала зафиксируем контракт показателя, затем разберём знаменатель и окно, после чего превратим расход бюджета в ограниченное и обратимое решение. Все числа в примерах учебные: они показывают арифметику и порядок проверки, но не описывают конкретную production-систему.</p>\n<h2>Что именно измеряют SLI, SLO и error budget</h2>\n<p>SLI (service level indicator) — количественная мера свойства сервиса: например, доля успешных запросов или доля запросов, завершившихся быстрее порога. SLO (service level objective) — целевое значение SLI при явно названных условиях. Error budget — допустимая часть неуспеха за то же окно. Для цели 99% это 1% событий, которые могут не соответствовать критерию, если договор считает их одинаково.</p>\n<p>Минимальный контракт должен назвать пользовательский scope, способ измерения, eligible-события, good-события, target и window. Scope говорит, какой результат защищаем. Eligible задаёт знаменатель. Good задаёт числитель. Window задаёт период, в котором результат сравнивают с целью. Policy добавляет владельца и действие, но не меняет саму формулу.</p>\n<pre><code>eligible = 1000\ngood = 994\ntarget = 0.99\nactual = good / eligible // 0.994 = 99.4%\nallowed_bad = eligible * (1 - target) // 10\nactual_bad = eligible - good // 6\nremaining_bad_capacity = allowed_bad - actual_bad // 4\n\n# Учебные числа: здесь нет источника событий и реального окна.</code></pre>\n<p>В учебной модели осталось место ещё для четырёх неуспешных событий до цели 99%. Это не означает, что сервис «на 99,4% надёжен» во всех смыслах: код 202 может лишь поставить операцию в очередь, а клиентский JavaScript может сломаться после ответа API. Если изменить exclusions, источник или границу завершения, изменятся eligible и good, а вместе с ними — весь вывод.</p>\n<h2>Сначала назовите пользовательский результат</h2>\n<p>Серверная метрика удобна, но удобство не делает её пользовательским SLI. Запрос «создать заказ» может получить 202, а очередь позднее отклонит заказ. Или backend ответит за 80 мс, пока браузер ждёт загрузки скрипта и не показывает подтверждение. Такой backend-SLI честно описывает свою точку измерения, но не весь путь.</p>\n<p>Формулировка должна начинаться с действия: «пользователь отправляет заказ и видит подтверждение». Затем задайте границу завершения: получение 202, появление записи в заказах или видимый экран подтверждения. Выберите источник, который действительно видит эту границу: серверный лог, black-box проверка или клиентская телеметрия. У каждого способа своя цена покрытия и сопровождения.</p>\n<p>Не смешивайте спецификацию и реализацию. Спецификация может звучать как «доля заказов, подтверждённых не позднее пяти минут». Реализация через лог API не увидит отказы до backend; реализация через браузерный synthetic-проверяющий охватит доступность пути, но может не отражать всех клиентов. В договоре нужно записать, какой пробел принят и зачем.</p>\n<figure><img src=\"/assets/editorial/2023/slo-error-budget-2023-decision-loop.svg\" alt=\"Петля решения SLI/SLO: сигнал проходит проверку контракта и контекста, затем владелец выбирает обратимое действие и повторную проверку\" loading=\"lazy\" /><figcaption>Схема показывает порядок разговора: сигнал не равен причине, а расход бюджета не является автоматическим релизным gate. Это учебная диаграмма, а не мониторинг или журнал инцидента.</figcaption></figure>\n<h2>Знаменатель и окно могут перевернуть вывод</h2>\n<p>Eligible — не «все записи, которые удобно посчитать», а заранее определённая популяция. Таймауты, повторные попытки, отмены и некорректные входы нельзя молча выкинуть только потому, что они ухудшают процент. Если событие исключается, запишите техническую причину, владельца правила и отрицательный пример. Иначе команда улучшает отчёт, меняя объект измерения.</p>\n<p>Окно тоже часть контракта. Скользящее окно сохраняет недавний сбой в расчёте и не обнуляет его в начале календарного месяца. Календарное окно удобнее для отчётности и планирования, но посреди периода сложнее оценить, сколько трафика ещё поступит. Для обоих вариантов укажите часовой пояс, границы, задержку событий и правило пересчёта.</p>\n<p>На малом трафике один отказ заметно меняет ratio. Это не запрет на SLO, а причина не строить срочный автоматический вывод на малой выборке. Можно увеличить окно, поднять минимальное число eligible-событий для page или отправлять такой сигнал в ticket на ручной разбор. Порог реакции выбирается вместе с формулой, а не после неё.</p>\n<table><caption>Карта разбора красного или зелёного сигнала</caption><thead><tr><th scope=\"col\">Наблюдение</th><th scope=\"col\">Возможная причина</th><th scope=\"col\">Проверяем</th><th scope=\"col\">Следующее действие</th></tr></thead><tbody><tr><td>Красный budget, но неизвестна формула</td><td>Смешаны окно, exclusions или версия запроса</td><td>Сверяем SLI-контракт и исходные выборки</td><td>Не принимать релизное решение до восстановления evidence</td></tr><tr><td>Команды получили разные проценты</td><td>Разные eligible, good или часовой пояс</td><td>Сравниваем запрос, период, фильтры и повторные попытки</td><td>Назначаем владельца одной версии расчёта</td></tr><tr><td>Зелёный SLI, но путь не работает</td><td>Точка измерения раньше пользовательского результата</td><td>Проходим сценарий до подтверждения</td><td>Расширяем scope или добавляем отдельный клиентский SLI</td></tr><tr><td>Один отказ сильно изменил процент</td><td>Малое окно или низкий трафик</td><td>Считаем объём и распределение событий</td><td>Меняем окно или переводим сигнал в ручной разбор</td></tr><tr><td>Красный график блокирует любой релиз</td><td>Policy не различает срочность и обратимость</td><td>Проверяем blast radius, rollback и тип изменения</td><td>Сужаем rollout, откатываемся или продолжаем с контролем</td></tr></tbody></table>\n<h2>Как превратить budget в решение о rollout</h2>\n<p>Policy — это не фраза «при красном остановить всё». В ней должны быть условие, evidence, владелец и действие. Например, при неизвестной формуле команда сначала восстанавливает источник данных. При подтверждённом расходе и неясной причине уменьшает долю трафика для нового релиза и назначает разбор. При исчерпанном бюджете откладывает несрочный rollout, но отдельно рассматривает security fix или исправление причины с явным планом отката.</p>\n<p>Прогрессивный rollout ограничивает blast radius, но не исправляет плохой SLI. На каждом этапе задайте длительность наблюдения, минимальный объём событий, критерий остановки и способ вернуть предыдущую версию. Ручное решение остаётся важным: одинаковый расход может означать известную деградацию, ошибку сбора или новую проблему после выкладки.</p>\n<p>После действия повторите расчёт на той же популяции и в сопоставимом окне. Если процент улучшился только после удаления таймаутов из eligible, это не восстановление сервиса. Если причина устранена, а signal не изменился, проверяйте задержку доставки или гипотезу, а не подгоняйте denominator.</p>\n<h2>Воспроизводимый порядок проверки</h2>\n<ol><li><strong>Назовите путь.</strong> Запишите действие пользователя, ожидаемый результат, симптом и цену ошибочного решения.</li><li><strong>Зафиксируйте контракт.</strong> Укажите scope, источник, eligible, good, exclusions, target, окно, часовой пояс и задержку поступления данных.</li><li><strong>Пересчитайте малую выборку.</strong> Возьмите несколько успехов и отказов, вручную проверьте классификацию и сохраните отрицательный пример. Сверьте результат с формулой из статьи.</li><li><strong>Проверьте реализацию.</strong> Сопоставьте логи, метрики, synthetic или клиентскую телеметрию с одной операцией и одной версией. Не называйте корреляцию причиной.</li><li><strong>Оцените решение.</strong> Проверьте объём трафика, срочность, обратимость и blast radius. Выберите pause, узкий rollout, rollback, исправление или продолжение с наблюдением по policy.</li><li><strong>Назначьте владельца.</strong> Запишите, кто выполняет действие, в какой момент и каким наблюдением подтверждается результат.</li><li><strong>Повторите без смены правил.</strong> Пересчитайте тот же SLI после изменения. Отдельно отметьте, что осталось вне покрытия.</li></ol>\n<h2>Ограничения и отрицательные случаи</h2>\n<p>SLI показывает соответствие выбранному критерию, но не объясняет корневую причину. Он также не покрывает то, что не попало в scope: не дошедшие до backend запросы, неверный результат, отдельный регион или позднее событие. Для этих рисков нужны дополнительные сигналы и проверки. Несколько зелёных SLI не складываются автоматически в доказательство здоровья всей системы.</p>\n<p>Числовой пример не подключён к файлам, CI, мониторингу, сети, HTTP или реальной конфигурации. Он не создаёт alert, не меняет rollout и не разрешает выпуск. Google SRE описывает error budget как механизм совместного решения, но конкретные target, окно, page и исключения требуют согласования продуктового владельца, разработки и эксплуатации.</p>\n<p>Если данных мало, задержка не известна или источник нельзя воспроизвести, правильный результат проверки — «решение отложено» либо «сигнал недостаточен», а не выдуманный инцидент. Если действие необратимо, сначала нужна дополнительная защита: staged rollout, snapshot, rollback или ручное подтверждение.</p>\n<h2>Критерий готовности к релизному решению</h2>\n<p>Разговор можно закрыть, когда другой инженер без устного контекста воспроизводит число и понимает действие. В записи есть пользовательский результат, версия формулы, eligible и good, target, окно, источник, владелец, критерий остановки, план отката и повторная проверка. Есть отрицательный пример, который текущий SLI не скрывает.</p>\n<p>Перед релизом достаточно задать три вопроса: что именно измеряется, почему это покрывает нужный путь и что произойдёт при ухудшении. Если на первый вопрос отвечает только цвет графика, а на третий — «разберёмся по ситуации», SLO пока остаётся отчётной метрикой, а не рабочим договором.</p>\n<h2>Проверяемые источники</h2><ul><li><a href=\"https://sre.google/sre-book/service-level-objectives/\" target=\"_blank\" rel=\"noopener noreferrer\">Google SRE Book: Service Level Objectives</a> — официальное объяснение SLI, SLO, пользовательских показателей, агрегации и error budget; параметры из статьи не выдаются за рекомендации для конкретного сервиса.</li><li><a href=\"https://sre.google/sre-book/service-best-practices/\" target=\"_blank\" rel=\"noopener noreferrer\">Google SRE Book: A Collection of Best Practices for Production Services</a> — официальные рекомендации измерять сервис с точки зрения пользователя, использовать error budget и наблюдать staged rollout с возможностью отката.</li><li><a href=\"https://sre.google/workbook/implementing-slos/\" target=\"_blank\" rel=\"noopener noreferrer\">Google SRE Workbook: Implementing SLOs</a> — официальный пошаговый материал о выборе SLI, rolling или calendar window, согласовании владельцев и error budget policy.</li></ul>"
|
||
}
|