Deep Engineering
Средний·Опубликовано·25 МИН

SLO и бюджет ошибок: почему «99,9 %» без окна не значит ничего

Одна и та же цель означает 43 минуты в месяц и полторы минуты в сутки. Урок разбирает арифметику окна, показывает, что незаметный инцидент съедает бюджета больше заметного, и объясняет, почему выбор между календарным и скользящим окном — это выбор правила, по которому кончается заморозка выкаток.

Полное техническое изложение

TL;DR

Надёжность считают долей, а обещают — уровнем этой доли за названный срок. Из тысячи запросов 990 успешных — это доступность 99 %. Обещание «мы держим 99 %» назначает уровень, а всё, что ниже уровня, — это то, сколько плохого обещание допускает: десять запросов из тысячи. Пока не сказано, за какой срок считается доля, такое обещание можно понять как угодно.

Отсюда главное следствие: одно и то же число означает разные вещи, а дороже всего оказывается то, чего никто не заметил. Арифметика: 99,9 % — это 43,2 минуты за 30 дней и 1,4 минуты за сутки. А цена инцидентов расставляет их не так, как ощущение: полная недоступность на 10 минут — 23 % месячного бюджета, а два процента ошибок в течение суток, которых никто не увидит глазами, — 67 %.

Дальше — единицы, окна и границы. Единица бюджета ошибок следует из SLI: при доступности, считаемой по запросам, бюджет удобно считать в неуспешных запросах — при 1000 запросов в секунду и цели 99,9 % за 30 дней это 2 592 000 запросов; при доступности, считаемой по времени, бюджет считают во времени. Половина запросов на час — 1 800 000 ошибок, или 69 % месячного бюджета. Окно — это правило, по которому кончается заморозка выкаток: после инцидента на 28-й день календарного месяца бюджет восстановится 1-го числа, а скользящее окно вернёт его только через 30 дней после самого инцидента. И всё это арифметика и модель, а не замер: числа выводятся из цели, окна и профиля инцидента при явно названных допущениях.

Порог входа
Перед уроком достаточно понимать
  • запрос к сервису может закончиться успехом или ошибкой, и ошибки случаются всегда;
  • доля считается делением: сколько успешных из скольких всего;
  • выкатка новой версии — это риск: что-то может сломаться именно из-за неё.
Заранее знать не нужно
  • SLI, SLO, SLA и бюджет ошибок — все четыре слова разбираются здесь же, с самого начала;
  • окна наблюдения, календарное против скользящего, выгорание бюджета.

Что здесь на самом деле спрашивают

Лестница обычно такая:

  1. «Что такое SLI, SLO и SLA?» — разминка на терминологию.
  2. «Что означает 99,9 %?» — здесь выясняется, спросит ли собеседник про окно.
  3. «Как из SLO получается бюджет ошибок?» — начало содержания.
  4. «Что делать, когда бюджет исчерпан?» — вопрос про решение, а не про метрику.
  5. «Календарное окно или скользящее?» — вопрос, отделяющий тех, кто этим пользовался.
  6. «Почему нельзя просто поставить цель 100 %?» — вопрос про смысл бюджета.
модель с допущениямиЧисла этого урока — арифметика и модель из bench/slo/budget.py, а не замер живой системы. Допущения: постоянный поток 1000 запросов в секунду, прямоугольный инцидент, бюджет по доле неуспешных запросов.

Урок стоит на расчёте, а не на прогоне. Причина простая: бюджет ошибок — это арифметика над двумя числами, и всё, что в нём есть, выводится, а не измеряется. Скрипт печатает и исходные величины, и результат, поэтому каждое число здесь можно пересчитать самому.

База: четыре слова, которые обычно путают

Начнём с арифметики на пальцах, без единого термина.

Сервис получил 1000 запросов. Из них 990 закончились успехом, а десять — ошибкой. Значит, доступность сервиса на этой тысяче — 99 %, а «плохого» случилось десять запросов из тысячи. Всё, никакой другой математики в теме нет: остальное — договорённости о том, что считать, какого уровня хотеть и что делать, когда уровень не выдержан.

Теперь те самые четыре слова, каждое обычными словами.

SLI — что мы измеряем. Это сама величина: доля успешных запросов. Могла бы быть и другая: доля запросов быстрее 300 мс, доля успешно оформленных заказов. Пока не выбрана величина, спорить не о чем.

SLO — какого уровня мы хотим. Это цель по выбранной величине: «доля успешных запросов не ниже 99 %». Внутреннее решение команды, а не обещание внешнему миру.

Бюджет ошибок — сколько плохого мы себе разрешаем. Это то же самое число, повёрнутое другой стороной: если цель 99 %, то на тысяче запросов разрешено десять неуспешных. Не «десять ошибок — это плохо», а «десять ошибок оплачены заранее».

SLA — внешнее обязательство. То, что записано в договоре с клиентом, с последствиями за нарушение. Живёт отдельно от SLO и обычно мягче: внутреннюю цель держат строже, чем обещанное наружу, чтобы запас между ними оставался местом для инженерных решений, а не для юристов.

И вот главный вопрос урока: на какой тысяче? Доля 990 из 1000 посчитана на одной тысяче запросов. За час их будет одно количество, за месяц — совсем другое, и одна и та же цель на этих отрезках означает совершенно разные вещи.

Этого уже достаточно, чтобы ответить на базовый вопрос собеседования. Всё дальнейшее — про то, во что превращается цель, когда назван срок, в чём считается бюджет и что происходит, когда он кончается.

Механизм 1: цель без окна не имеет смысла

1. THE SAME TARGET, DIFFERENT WINDOWS
-------------------------------------
    target          1d          7d         30d         90d
    99.00%    14.4 min       1.7 h       7.2 h      21.6 h
    99.50%     7.2 min    50.4 min       3.6 h      10.8 h
    99.90%     1.4 min    10.1 min    43.2 min       2.2 h
    99.99%         9 s     1.0 min     4.3 min    13.0 min
модель с допущениямиbench/slo/budget.py. Чистая арифметика: доля недоступности, умноженная на длину окна.

Прочитайте строку 99,9 % слева направо: 1,4 минуты за сутки, 10,1 минуты за неделю, 43,2 минуты за месяц, 2,2 часа за квартал. Одно обещание — и четыре разные величины.

Отсюда первое, что стоит уточнять в разговоре: «у нас три девятки» — это ещё не обещание. Три девятки в сутки — жёсткая цель, при которой один перезапуск с минутной паузой съедает большую часть суточного бюджета. Три девятки в квартал — цель, при которой можно позволить себе двухчасовую аварию раз в три месяца.

Отсюда же практический вывод про переговоры: если окно не названо, стороны понимают обещание по-разному и обнаружат это в первый же инцидент.

Механизм 2: единица бюджета следует из SLI

Бюджет ошибок — это «сколько плохого разрешено». Первый вопрос здесь — плохого в чём, и ответ не выбирают по вкусу: единица бюджета следует из SLI.

  • SLI считается по запросам («доля успешных запросов») — бюджет удобно считать в неуспешных запросах.
  • SLI считается по времени («доля минут, когда сервис работал») — бюджет считается во времени, в минутах недоступности.

В этом уроке SLI — доля успешных запросов, поэтому дальше всё считается в запросах, а минуты стоят рядом как перевод. Перевод верен только для полной недоступности: там каждая нерабочая минута — это все запросы этой минуты, и только поэтому 2 592 000 запросов можно назвать «43,2 минуты».

2. WHAT ONE INCIDENT COSTS
--------------------------
  target                                       99.9%
  window, days                                 30
  requests in the window                       2 592 000 000
  error budget, requests                       2 592 000
  error budget, minutes of total outage        43.2 min

  incident: 100% of requests fail for 10 min   600 000 requests = 23% of the budget
  incident: 50% of requests fail for 60 min    1 800 000 requests = 69% of the budget
  incident: 2% of requests fail for 1440 min   1 728 000 requests = 67% of the budget
модель с допущениямиbench/slo/budget.py. Поток принят постоянным — 1000 запросов в секунду; при неравномерной нагрузке те же проценты дадут другие абсолютные числа.

Три инцидента, три совершенно разных ощущения — и цена, которая расставляет их не так, как ощущение.

Полная недоступность на десять минут — то, что заметят все, попадёт в новости внутреннего чата и потребует разбора. Стоит она 23 % месячного бюджета.

Два процента ошибок в течение суток — то, чего не заметит никто: графики почти ровные, отдельные пользователи повторили запрос и забыли. Стоит это 67 % — втрое дороже громкой аварии.

Отсюда главная мысль урока: бюджет измеряет не громкость, а объём. Он и нужен затем, чтобы уравнять в правах два вида ущерба, которые интуиция оценивает несопоставимо.

И заметьте, чем это сравнение вообще держится: обе аварии посчитаны в одной единице, в неуспешных запросах, потому что такова здесь SLI. Считай мы доступность по времени, тихую деградацию нечем было бы измерить — сервис-то отвечал все сутки, недоступным он не был ни минуты.

И отсюда практика: тихая деградация опаснее шумной, потому что её никто не торопится чинить. Обнаруживает её только счёт бюджета — не глаз и не дежурный.

Механизм 3: календарное окно против скользящего

Третий блок — про то, что происходит после инцидента.

3. CALENDAR WINDOW AGAINST ROLLING WINDOW
-----------------------------------------
  budget for 30 days, requests                 2 592 000
  incident on day 28: 50% for 1 hour           1 800 000 requests
  that is                                      69% of the budget

  calendar window: the budget resets on the 1st
  budget left on day 29                        31%
  budget left on day 31 (new month)            100%

  rolling 30-day window: the incident stays for 30 days
  budget left 1 day after the incident         31%
  budget left 15 days after the incident       31%
  budget left 29 days after the incident       31%
  budget left 31 days after the incident       100%
модель с допущениямиbench/slo/budget.py. Один и тот же инцидент, две разные учётные политики; разница видна не в момент аварии, а через несколько дней после. Возвращение бюджета к 100 % в обеих политиках задано правилом окна, а не посчитано: блок показывает, как правило выглядит по дням.

Инцидент один. Разница — в том, когда снова можно выкатывать.

Календарное окно прощает по расписанию: авария 28-го числа стоит два дня осторожности, а 1-го бюджет полон. Это удобно для отчётности и создаёт понятный перекос: конец месяца — время рисковать, начало — время не выкатывать ничего важного, потому что «бюджет только начался».

Скользящее окно ничего не прощает по календарю: инцидент влияет ровно 30 дней, а потом выпадает из окна сам. Оно честнее описывает пережитое пользователем, но требует объяснять, почему сегодня выкатывать нельзя, а вчера было можно, хотя ничего не случилось.

Обе политики законны, и вопрос на собеседовании обычно не «какая правильная», а «понимаете ли вы, что выбор делаете не про метрику, а про правило окончания заморозки».

Глубже: зачем бюджет нужен и почему цель ставят ниже 100 %

Последний уровень — про смысл конструкции и её границы, а не про арифметику.

Бюджет ошибок превращает надёжность из спора в арифметику с общим ответом. Пока он есть, выкатывать можно: риск оплачен заранее. Когда он исчерпан, выкатки останавливают — не в наказание, а потому что дальнейший риск нечем покрывать.

Отсюда ответ на вопрос про 100 %. Цель в сто процентов означает нулевой бюджет, то есть запрет на любое изменение: каждая выкатка — риск, а платить за него нечем. Именно поэтому цель ставят ниже единицы намеренно — не потому, что не умеют лучше.

И отсюда же — почему бюджет считают по метрике, которую видит пользователь. Метрика «сервис отвечает на проверку» (следующий урок) прекрасно себя чувствует, пока пользователи получают ошибки; бюджет, посчитанный по ней, никогда не кончится и ничего не остановит.

Как отвечать на собеседовании

Короткий ответ: SLO — это цель по метрике плюс окно, а бюджет ошибок — то, сколько плохого эта цель разрешает в этом окне; считается он в тех же единицах, в которых считается сама метрика. 99,9 % за 30 дней при 1000 запросов в секунду и доступности, считаемой по запросам, — это 2 592 000 неуспешных запросов, что при полной недоступности равно 43,2 минуты; те же 99,9 % за сутки — 1,4 минуты.

Этого достаточно, чтобы ответить верно. Дальше — то, что добавляют, если собеседник копает.

Если интервьюер копает глубже

Хороший ответ отличают три вещи. Первая — вы сразу спрашиваете про окно, потому что без него цель не число. Вторая — вы знаете, что тихая деградация дороже громкой аварии: два процента ошибок за сутки стоят 67 % месячного бюджета против 23 % у десятиминутной полной недоступности. Третья — вы говорите, что бюджет существует ради решения: пока он есть, выкатки идут; когда кончился, останавливаются, и в этом весь смысл цели ниже ста процентов.

И одна вещь, на которой легко переусердствовать. Сказать «бюджет считают в запросах, а не в минутах» — значит выдать частный случай за правило. Единица бюджета следует из SLI: доступность, считаемая по запросам, даёт бюджет в неуспешных запросах; доступность, считаемая по времени, даёт бюджет во времени. Ошибка не в минутах как таковых, а в переводе одного в другое: «43,2 минуты» верны ровно настолько, насколько инцидент похож на полную недоступность, и именно поэтому тихая деградация в минутах не считается вовсе — сервис при ней не был недоступен ни минуты.

Дальше спросят

Спросят дальше

Чем SLO отличается от SLA?

Короткий ответ

SLO — внутренняя цель, по которой принимают решения о выкатках; SLA — внешнее обязательство с последствиями в договоре. Практика обычно такая, что внутренняя цель строже внешнего обязательства: запас между ними и есть место, где живут решения без юридических последствий.

Из этого следует ответ на вопрос «что если мы нарушили SLO»: ничего юридического, но выкатки останавливаются. Если же нарушено SLA — начинается разговор про компенсации, и это уже не инженерное решение.

Спросят дальше

По какой метрике считать бюджет?

Короткий ответ

SLI — это сама метрика: доля успешных запросов, доля запросов быстрее порога, доля успешных операций. SLO — цель по этой метрике плюс окно, за которое её считают, а бюджет считается в единицах этой же метрики: по запросам — значит в неуспешных запросах, по времени — значит во времени. Считать бюджет надо по SLI, который описывает опыт пользователя, и именно поэтому в определение SLI входит порог: «успешный» и «быстрее 300 мс» — разные метрики и разные бюджеты.

Метрика вида «сервис отвечает на проверку» для бюджета не годится: она может быть зелёной, пока пользователи получают ошибки, и посчитанный по ней бюджет никогда не кончится.

Спросят дальше

Что делать, когда бюджет исчерпан?

Короткий ответ

Останавливать выкатки того, что этот бюджет тратит, и заниматься причинами. Смысл не в наказании: изменения — главный источник риска, и когда платить за риск нечем, разумно перестать его создавать.

Полезно оговорить заранее, что именно останавливается: выкатки продукта — да; исправления, снижающие расход бюджета, — нет. Иначе правило превращается в запрет чинить.

Спросят дальше

Почему бы не поставить цель 100 %?

Короткий ответ

Потому что это нулевой бюджет и, следовательно, запрет на любое изменение: каждая выкатка создаёт риск, а покрывать его нечем. Цель в сто процентов означает не «мы очень надёжны», а «у нас нет права на изменение».

Есть и вторая причина: сто процентов нельзя измерить. Любая метрика имеет собственные пропуски и сбои сбора, и цель, равная пределу, ломается на первом же сбое измерительной системы.

Частые заблуждения

Утверждение

99,9 % — это понятная цель

На самом деле

Без окна — нет: арифметика даёт 1,4 минуты в сутки и 43,2 минуты за 30 дней из одного и того же числа. Пока окно не названо, стороны понимают обещание по-разному и обнаружат это в первый же инцидент.

Утверждение

громкая авария всегда дороже тихой деградации

На самом деле

Наоборот, чаще дешевле: полная недоступность на 10 минут — 23 % месячного бюджета, а два процента ошибок в течение суток — 67 %. Бюджет измеряет объём ущерба, а не громкость, и тихая деградация опаснее именно потому, что её никто не торопится чинить.

Утверждение

бюджет ошибок — это всегда разрешённое время простоя

На самом деле

Единица бюджета следует из SLI. Считаете доступность по времени — бюджет и есть время простоя. Считаете по запросам, как в этом уроке, — бюджет есть число неуспешных запросов: при 1000 запросов в секунду и цели 99,9 % за 30 дней это 2 592 000 запросов. Ошибка не в минутах, а в переводе одного в другое: «43,2 минуты» верны только для полной недоступности, а два процента ошибок за сутки в минутах простоя не видны вовсе.

Утверждение

календарное и скользящее окно — вопрос вкуса

На самом деле

Это разные правила окончания заморозки. После инцидента на 28-й день календарное окно вернёт бюджет 1-го числа, а скользящее — только через 30 дней после самой аварии. Один и тот же инцидент, два разных ответа на вопрос «можно ли выкатывать сегодня».

Утверждение

цель 100 % — это просто очень высокая планка

На самом деле

Это нулевой бюджет, то есть запрет на любое изменение: каждая выкатка создаёт риск, а покрывать его нечем. Плюс сто процентов нельзя измерить — у любой метрики есть собственные пропуски, и цель, равная пределу, ломается на первом сбое сбора.

Утверждение

бюджет можно считать по доступности сервиса для проверок

На самом деле

Тогда он никогда не кончится. Проверка отвечает и в тот момент, когда пользователи получают ошибки (следующий урок), поэтому бюджет считают по метрике, описывающей опыт пользователя: доля успешных запросов или доля запросов быстрее порога.

Утверждение

исчерпанный бюджет означает, что надо остановить всю работу

На самом деле

Останавливают то, что бюджет тратит, — выкатки продукта. Исправления, снижающие расход, не останавливают никогда, иначе правило превращается в запрет чинить. Об этом стоит договориться заранее, а не в момент аварии.

Практика

Две задачи. Сначала ответьте, потом сверьтесь с настоящим выводом: в обеих правильный ответ взят из прогона расчёта, а не назначен.

Практика · что напечатает

Цель 99,9 %, поток 1000 запросов в секунду. Печатаются три вещи: бюджет за 30 дней в переводе на полную недоступность, тот же бюджет за одни сутки, и во сколько процентов месячного бюджета обойдётся полная недоступность длиной десять минут. Что напечатает этот код?
budget = budget_requests(TARGET, WINDOW_DAYS)
print(human_minutes(WINDOW_DAYS * 24 * 60 * (1 - TARGET)))
print(human_minutes(1 * 24 * 60 * (1 - TARGET)))
print(f"{incident_errors(1.0, 10) / budget * 100:.0f}")

Практика · оцените

Цель 99,9 % за 30 дней. Сутки сервис отдаёт ошибку на два процента запросов — так, что этого никто не замечает. Какую долю месячного бюджета съест этот день, в процентах?
%

Проверка знаний

Вопрос 1 из 6

Что означает цель 99,9 % без указания окна?

Источники и что читать дальше

1 ИСТОЧНИК

  1. Расчёт этого урока: модель бюджета ошибокИсточник. У этого урока нет внешнего первоисточника, и это сказано прямо: всё, что в нём есть, — арифметика, выводимая из двух чисел (цель и окно), плюс модель инцидента с объявленными допущениями. Допущения: постоянный поток 1000 запросов в секунду круглые сутки, прямоугольный инцидент, бюджет считается по доле неуспешных запросов, а не по времени недоступности, скользящее окно сдвигается посуточно. Прогон печатает и исходные величины, и результат, поэтому расчёт можно пересчитать целиком./ru/bench/slo/budget.py