✻ Урок 5.4 · Тема 5: Надёжность и инциденты
Изменения без аварий и аварийное восстановление
Содержание урока
Зачем это нужно
Пятница, за три дня до распродажи. В очереди на выкатку накопилось много правок: новая оплата, исправления корзины, обновление библиотеки. Менеджер спрашивает: «Можно всё это выкатить сегодня?» Правильный ответ состоит не из слова «да» или «нет», а из вопросов: сколько у нас осталось бюджета ошибок, как быстро мы заметим плохую версию и как быстро вернём старую.
Большинство серьёзных сбоев начинается с изменения: выкатка, правка конфига, миграция. Сам код пишут быстро, а вот уверенность, что изменение безопасно, и умение отыграть его назад берутся из заранее продуманных приёмов. Урок про эти приёмы: как выкатывать небольшими кусками, как решать об откате по цифрам, а не по настроению, и что делать, если сломалось так, что откат не помогает и нужно восстанавливаться из копий.
Шаг проекта: в ~/monitoring-lab/05-reliability/04-release лежат скрипты «плохой выкатки» и отката с отметками на графиках Grafana, check-release.sh с критерием отката, budget.sh с расчётом расхода бюджета ошибок и dr.md, где для каждого компонента «Магазина» записаны цели RPO и RTO (сколько данных можно потерять и сколько можно простоять, подробно ниже).
Что нужно знать
- SLI, SLO и бюджет ошибок: урок 1.2. Золотые сигналы: урок 1.1.
- Дашборды, аннотации и скрипт
orders.sh: урок 3.1. Алерты на сгорание бюджета: урок 3.2. - Логи и трейсы с общим
trace_id: тема 4. - Инцидент и его участники: урок 5.1. Паттерны надёжности, в том числе повторы оплаты и таймауты: урок 5.3.
- Стенд с профилем
monitoringзапущен,docker compose,curl,jq: load-tester, урок 5.3.
Картина целиком
Представь, что ты меняешь колесо на ходу автобуса. Можно остановить автобус, сделать работу и ехать дальше, а можно придумать способ, при котором пассажиры ничего не заметят. SRE выбирает второе, но не из геройства: любое изменение это шанс сломать, и этот шанс нужно делать маленьким, заметным и обратимым. Для выкатки это значит: новую версию сначала получает малая доля покупателей, остальные пока ездят на старой, а если что-то не так, версию быстро возвращают.
Поэтому у каждого изменения есть точки остановки: проверка до выкатки, небольшая доля трафика, наблюдение по метрикам, кнопка «назад». Если вся цепочка не помогла и данные потеряны, остаётся запасной план: копии и восстановление.
flowchart LR
A["Изменение<br>в коде"] --> B["Проверка<br>на preprod"]
B --> C["Выкатка<br>на малую долю"]
C --> D{"Метрики<br>в норме?"}
D -->|да| E["Больше трафика,<br>потом все"]
D -->|нет| F["Откат"]
F --> G{"Откат<br>помог?"}
G -->|нет| H["Восстановление<br>из копий"]
Читай схему слева направо: до продакшена изменение проходит проверку (тесты и preprod, подробно ниже), потом его пускают на малую долю трафика и сверяют метрики. Плохое отправляется на откат, а если откат не лечит (например, испорчены данные), включается аварийное восстановление.
Теория
Частые маленькие релизы безопаснее больших
Допустим, в пятницу выкатываешь сразу сорок изменений, и покупатели начинают получать ошибки. Какое из сорока виновато? Ты не знаешь. Можно откатить все, но тогда пропадут и хорошие. Можно искать делением пополам: откатить половину, проверить, откатить половину оставшегося. Для сорока изменений это около шести заходов (два в шестой степени уже больше сорока), и каждый заход занимает выкатку, ожидание и просмотр графиков. Если выкатывать каждое изменение отдельно, виновный известен сразу: это то, что поехало последним.
В этом и смысл правила «выкатывай часто и понемногу» (small batch). Маленькое изменение проще понять, проще проверить, проще откатить, а вред от него ограничен. Большой релиз накапливает риск, как накопившиеся долги: чем дольше копишь, тем больнее платить.
Прикинь сам: релиз раз в месяц ломается в одном случае из пяти. Релиз каждый день ломается раз в тридцать. Что полезнее для бюджета ошибок: реже, но большими, или чаще, но маленькими?
Обычно второе: каждая поломка маленькой выкатки короче и дешевле. Но это работает только при двух условиях: выкатка автоматизирована (иначе люди устают) и откат быстрый (иначе частота не помогает).
Осторожно: «частые релизы» не значит «выкатывать без проверки». Частота хороша ровно настолько, насколько надёжны проверка и откат.
Главное: малое изменение легко найти и отменить, поэтому частые маленькие выкатки в сумме надёжнее редких больших.
Откуда берётся уверенность, что выкатывать вообще можно? Из бюджета ошибок.
Бюджет ошибок и политика: что делать, когда он кончился
Бюджет ошибок ты уже считал в уроке 1.2: при SLO 99% за 30 дней можно «потратить» 1% времени, это 43 200 минут на 1%, то есть 432 минуты полной недоступности. Бюджет это разрешение на риск, а не наказание. Пока он есть, команда выкатывает смело. Когда он тает, нужно договорённое заранее правило, что делать. Такое правило называют политикой бюджета ошибок (error budget policy).
Хорошая политика короткая и записана до того, как бюджет кончился, потому что в момент кризиса спорить поздно. Пример ступеней (canary в таблице это выкатка сначала на малую долю покупателей, подробно она разобрана ниже):
| Израсходовано | Что делаем |
|---|---|
| меньше 50% | выкатываем как обычно |
| 50-90% | выкатываем только небольшие изменения, каждое с canary, новые фичи ждут |
| 90-100% | замораживаем всё, кроме исправлений надёжности и безопасности |
| больше 100% | заморозка, разбор причин, возвращаемся к релизам, когда бюджет снова есть |
Цифры в таблице пример: свои ступени команда выбирает сама и записывает вместе с владельцем продукта. Пороги зависят от того, как быстро у сервиса тратится бюджет: у быстро горящего сервиса ступени ставят раньше. Важно, что решение принято заранее и одинаково для всех: SRE не «запрещает», а ссылается на правило, которое подписали обе стороны. Burn rate (темп сгорания) и алерты на него разобраны в уроке 3.2 и в DevOps, уроке 8.11.
SRE в релизном цикле нужен не как привратник, который говорит «нет», а как человек, который делает безопасный путь простым: помогает с метриками выкатки, критерием отката, автоматикой и разбором, если изменение всё же сломало.
Главное: политика бюджета это заранее согласованное правило «что меняется, когда бюджета мало»; она превращает спор о рисках в договор.
Бюджет можно тратить на разные риски. Посмотрим, как не потратить его весь на одну выкатку.
Canary и A/B: похожи на вид, разные по цели
Canary (канарейка) это выкатка новой версии на малую долю пользователей, с наблюдением. Название пришло от шахтёров: канарейка в клетке первой чувствовала газ. Если метрики новой версии хуже, выкатка останавливается и возвращается назад, пока пострадали единицы. Если лучше или такие же, доля растёт: 5%, 25%, 50%, 100%.
A/B-тест (A/B test) тоже делит пользователей на две группы, но цель другая: узнать, какая версия лучше для бизнеса (конверсия, средний чек, клики). Тест идёт дни и недели, пока не накопится статистика, а обе версии считаются рабочими. Для SRE разница такая: canary проверяет, что версия не сломана, и заканчивается за минуты, A/B проверяет, какая версия выгоднее, и это вопрос продукта. Технически в обоих случаях трафик разделяется весами (например, в балансировщике или в service mesh), но смотрят на разные метрики.
flowchart TB
subgraph C["Canary: версия не сломана?"]
direction LR
C1["5% трафика"] --> C2{"ошибки и<br>задержка в норме?"}
C2 -->|да| C3["25%, 50%, 100%"]
C2 -->|нет| C4["откат"]
end
subgraph A["A/B: версия выгоднее?"]
direction LR
A1["50% на A,<br>50% на B"] --> A2["ждём статистику<br>дни или недели"] --> A3["выбираем<br>по бизнес-метрике"]
end
Доли 5%, 25%, 50% тоже примерные: долю берут такой, чтобы ошибку новой версии было видно на графике, а задело как можно меньше людей.
Читай обе схемы как две разные истории. Canary заканчивается быстро и отвечает «да, дальше» или «нет, назад». A/B длится долго и отвечает на вопрос не про надёжность.
Есть тонкость, которая часто выручает на собеседовании. На 5% трафика общий график ошибок почти не изменится: сто плохих ответов растворятся в общем потоке. Поэтому метрики канарейки смотрят отдельно: ошибки и задержку именно новой версии, а не всего сервиса. Автоматизируют это инструменты вроде Argo Rollouts и Flagger: они сами двигают долю и сами откатывают по метрикам, подробности в DevOps, уроке 9.6.
А вот что бывает, когда канарейки нет. 19 июля 2024 года компания CrowdStrike выпустила обновление конфигурации для своего агента на Windows сразу на все машины, а в нём была ошибка. Миллионы компьютеров по всему миру зависли с синим экраном. После этого компания сообщила, что вводит постепенную раздачу таких обновлений. Плохая версия на малой доле задела бы единицы, а не всех.
Поиграй с ползунками: посмотри, сколько бюджета съедает плохая версия при выкатке сразу всем и по ступеням.
На картинке две линии: красная показывает расход бюджета при выкатке сразу всем, синяя при ступенях canary. Пока ты замечаешь беду быстро, ступени экономят бюджет в разы, а при долгом обнаружении линии сближаются: canary дошёл до 100%.
Главное: canary проверяет надёжность и длится минуты, A/B проверяет пользу для бизнеса и длится недели; метрики канарейки смотри отдельно от общих.
Канарейка нашла проблему. Теперь нужна кнопка, которая быстро возвращает всё назад.
Большая красная кнопка: откат
В хорошей системе у каждого изменения есть откат (rollback): заранее проверенное действие, которое возвращает прежнее состояние. SRE называют такую возможность «большая красная кнопка»: нажал и вернулся. Кнопка работает, только если её нажимали до аварии. Откат, который ни разу не пробовали, при пожаре почти наверняка не сработает.
Пример для Kubernetes и Helm (на стенде «Магазин» Kubernetes нет, поэтому эти команды справочные, запускать их не нужно). На стенде то же самое, выкатку и откат, делают скрипты release.sh и rollback.sh: ты напишешь их в практике. Helm это менеджер пакетов для Kubernetes: он ставит приложение как «релиз» с номером ревизии. Kubernetes и Helm подробно разобраны в курсе DevOps.
# выкатка, которая откатится сама, если не станет здоровой за 5 минут
helm upgrade --install shop ./chart --namespace shop --atomic --timeout 5m
# история ревизий релиза
helm history shop --namespace shop
# вернуть предыдущую ревизию (0 значит «предыдущая»)
helm rollback shop 0 --namespace shop --wait
Первая команда ставит новую версию. Флаг --atomic говорит Helm: если за --timeout приложение не стало готовым, откати само (в Helm 4 тот же смысл у флага --rollback-on-failure, подробнее в DevOps, уроке 5.9). Вторая показывает ревизии, третья возвращает прошлую. Откат вручную обычно оформляют кнопкой в CI, чтобы не вспоминать команды ночью:
rollback:
stage: deploy
when: manual
script:
- helm rollback shop 0 --namespace shop --wait
Слово when: manual в GitLab CI превращает шаг в кнопку, которую нажимает человек. Её не должно быть сложно найти: ссылка на неё лежит в runbook.
Как Kubernetes понимает, что новая версия «здоровая»? По пробам (probe). Проба readiness отвечает на вопрос «готов ли под принимать трафик»: если нет, Kubernetes убирает под из балансировки, и запросы идут на остальные. Например, новая версия оплаты ещё запускается и не готова: пока проба не пройдёт, покупатели к ней не попадают. Проба liveness отвечает на другой вопрос: «жив ли процесс вообще»: если нет, под перезапускают. Например, оплата зависла и не отвечает совсем: её проще перезапустить, чем ждать. Не путай их: перезапуск по liveness не лечит перегрузку, а убирание по readiness как раз её смягчает. При выкатке readiness ещё и не пускает трафик на новую версию, пока она не запустилась. Подробности и YAML: DevOps, урок 5.7.
Главное: откат должен быть заранее придуман и проверен;
--atomicоткатывает неудачный запуск,helm rollbackвозвращает любую прошлую ревизию, аreadinessне пускает трафик на неготовую версию.
Кнопка есть. Но когда её нажимать?
Решение об откате: по каким признакам
Решение об откате принимают по заранее записанному критерию. Без него в момент проблемы начинается спор: «может, само пройдёт», «давайте ещё пять минут». Пока спорят, идёт расход бюджета. Хороший критерий короткий, измеримый и привязан к симптомам покупателя: «доля 5xx выше 2% три минуты подряд или p95 оформления заказа выше 1 секунды». Признаки, которые стоит учитывать:
- метрики после выкатки хуже, чем до (сравниваем с тем, что было минуты назад, а не с абстрактной нормой);
- ухудшение началось сразу после отметки выкатки на графике, а не раньше;
- ошибки в логах содержат то, что менялось (новый путь кода, новая зависимость);
- проблема растёт или стоит на месте: ухудшающийся сбой требует решения раньше, чем стабильный.
Когда откат не нужен? Если проблема не связана с выкаткой (на графике видно, что она началась до неё) или ты знаешь исправление и оно быстрее отката. Но по умолчанию, если сомневаешься и изменение свежее, откатывай: откат дёшев, расследование потом.
Есть и обратная сторона: откат тоже изменение, и вот случай, где именно откат сделал хуже. 1 августа 2012 года брокер Knight Capital выкатил новую версию торгового ПО, но на одном из восьми серверов старый код остался. Этот сервер начал отправлять лишние заказы, и компания потеряла около 440 миллионов долларов за 45 минут. Инженеры, пытаясь остановить, откатили новый код на остальных серверах, и это только ухудшило положение: старое поведение теперь работало на всех. Урок: откат должен быть проверен так же, как выкатка, а полное состояние всех машин нужно знать до того, как нажимаешь.
flowchart TD
A["Метрики хуже<br>после выкатки?"] -->|нет| B["Не связано<br>с выкаткой,<br>ищем причину"]
A -->|да| C{"Критерий отката<br>выполнен?"}
C -->|нет| D["Смотрим дальше<br>по расписанию"]
C -->|да| E["Откат"]
E --> F{"Метрики<br>вернулись?"}
F -->|да| G["Разбор потом,<br>выкатка заморожена"]
F -->|нет| H["Причина другая:<br>инцидент по 5.1"]
Схему читай сверху вниз как вопросы дежурному. Если критерий выполнен, откатываем без споров, а если откат не помог, значит, дело не в выкатке и дальше идёт обычный инцидент из урока 5.1.
Главное: критерий отката пишут заранее и по симптомам покупателя; сомневаешься и изменение свежее: откатывай, разбираться будешь после.
Часть таких решений можно доверить машине.
Автоматизируем то, что предсказуемо
Человек в три часа ночи медленнее и ошибается чаще. Поэтому всё, что случается регулярно и лечится одинаково, отдают автоматике:
- упавший процесс перезапускает Kubernetes или systemd;
- неготовый под убирается из балансировки по
readiness; - нагрузку подхватывает автомасштабирование: HPA добавляет копии приложения, VPA подбирает ему CPU и память (разбор в DevOps, уроке 5.11);
- неудачная выкатка откатывается сама по
--atomicили по метрикам канарейки; - при алерте автоматически создаётся задача, канал в мессенджере и приходит ссылка на runbook.
Последний пункт часто забывают: автоматика инцидент-менеджмента (завести канал, позвать дежурного, подставить шаблон статуса) экономит первые минуты, когда они дороже всего. Разумеется, автоматику ограничивают: она должна иметь предохранитель, например, не перезапускать сервис чаще раза в несколько минут, иначе при неправильной причине она устроит шторм сама. И автоматику нужно мониторить: её срабатывания это тоже события, которые видны на графике.
Главное: автоматизируй предсказуемое и повторяющееся, ставь предохранители и следи за самой автоматикой.
Ещё лучше поймать проблему до продакшена.
Проверка до продакшена: preprod, хаос и game day
Preprod (предпродакшен) это окружение, похожее на боевое, где изменение проходит интеграционные проверки: сервисы работают вместе, как у покупателей. Польза от preprod настоящая, только если он похож на продакшен: те же версии, сопоставимый объём данных и похожий трафик. Проверка на пустой базе с одним запросом в минуту не покажет ни пул соединений, ни медленный запрос, ни шторм повторов. Нагрузку на preprod проигрывают, например, повторяя записанный боевой трафик или генератором (load-tester).
Хаос-тестирование (chaos engineering) идёт дальше: ты намеренно ломаешь части системы и смотришь, держится ли она так, как ты предполагал. Убиваешь под, добавляешь задержку в сеть, отключаешь зависимость. Для Kubernetes такие эксперименты описывают и запускают специальные инструменты, например Litmus и Chaos Mesh. Начинают на preprod с маленьким радиусом поражения и записанной гипотезой «если убить один под оплаты, доля ошибок не превысит 1%».
Game day (игровой день) это учения: команда собирается, ей заранее готовят сбой (или включают его неожиданно, но в безопасных рамках), и она отрабатывает реакцию: алерт, дежурный, откат, связь, статус. Цель не в оценке людей, а в поиске дыр: алерт молчит, runbook устарел, у дежурного нет доступа. Типичные виды проверяемых сбоев: отказ компонента, отказ зависимости, перегрузка и потеря связи между площадками.
Главное: preprod работает, только если похож на продакшен; хаос-тесты проверяют гипотезы об устойчивости; game day проверяет людей и инструкции.
Всё это сокращает риск, но не убирает. Остаётся сценарий, когда ломается сама основа, и данные нужно вернуть.
Аварийное восстановление: RTO и RPO
Аварийное восстановление (disaster recovery, DR) это план, как вернуть сервис, если потеряно то, что откатом не лечится: база, площадка, весь кластер. У плана две цели.
RPO (recovery point objective) отвечает на вопрос «сколько данных мы готовы потерять», измеряется во времени: RPO 15 минут значит, что можно потерять записи последних 15 минут. Если копии делаются раз в час, то в худшем случае (авария прямо перед следующей копией) потеряется почти час.
RTO (recovery time objective) отвечает «сколько мы готовы быть недоступными»: RTO 45 минут значит, что сервис должен вернуться не позже, чем через 45 минут после начала аварии. В RTO входит всё: заметить, собрать людей, найти копию, восстановить, проверить, переключить трафик, а не только команда восстановления.
Не путай RPO и RTO с SLA и SLO: SLO это цель доступности в целом, а RPO и RTO это цели для конкретной аварии.
На линии слева данные между последней копией и аварией, они потеряны, и это RPO. Справа этапы простоя, и это RTO. Видно, что сама команда восстановления занимает малую часть, а остальное это обнаружение, сбор людей и проверка.
Полный разбор копий, WAL (журнала изменений базы) и проверки восстановлением ты найдёшь в DevOps, уроке 10.3.
Главное: RPO это сколько данных можно потерять, RTO сколько времени можно не работать; оба считаются по худшему случаю и включают всё, а не одну команду.
Осталось понять, из чего складывается план.
Копии, запасные пулы и запасные каналы
Хороший план опирается на то, что лежит отдельно от основной системы:
- Копии данных: дампы и физические копии базы вне того сервера, который копируют. 31 января 2017 года у GitLab при ручной работе удалили данные на основной базе. По их разбору, из нескольких способов копирования ни один не оказался рабочим, и восстанавливались с копии, которой было около шести часов. Копия, из которой ни разу не восстанавливались, это не копия, а надежда.
- Копии кода и документации: репозиторий, инфраструктура как код, runbook и схемы должны быть доступны, даже если недоступна ваша площадка. Если инструкция по восстановлению лежит на самом упавшем сервисе, она бесполезна.
- Несколько пулов узлов: приложение работает на нескольких группах серверов (в Kubernetes это пулы узлов, в разных зонах), чтобы потеря одной группы не останавливала сервис.
- Резервные каналы связи: если основной мессенджер или почта лежат вместе с аварией, команде нужен запасной способ связаться (другой мессенджер, телефонный список).
И главное: план проверяют. Восстановление из копий и переключение на запасной канал связи полезно репетировать хотя бы раз в квартал: такие учения находят сломанные копии, устаревшие инструкции и недоступные пароли, пока нет настоящей аварии. Отличие плана аварийного восстановления (DRP) от обычной инструкции: DRP описывает самые тяжёлые сценарии (потеряна площадка, данные), у него есть цели RPO и RTO, роли и проверки, а инструкция на одно действие отвечает на узкий сбой.
Проверь понимание: у «Магазина» заказы лежат в Postgres, корзины в Redis без тома, дашборды Grafana в git. Для какого из компонентов вы бы назначили самый жёсткий RPO?
Для Postgres: потерянные заказы это деньги покупателей. Корзину в Redis можно потерять, покупатель соберёт её заново, а дашборды восстановятся из git. Именно так появляется таблица целей: у каждого компонента свои RPO и RTO.
Главное: копии и инструкции хранят отдельно от основной системы, а план проверяют регулярно, иначе он не план.
Для любопытных: чем частые копии дороже
Чем меньше RPO, тем чаще копии и тем больше нагрузка и места. RPO минуты требует не периодических дампов, а потока журнала изменений (WAL) в другое место: это сложнее и дороже. Поэтому цель RPO ставят по цене потери для бизнеса, а не по принципу «чем меньше, тем лучше». Подробности про физические копии и восстановление на момент времени: DevOps, урок 9.5.
Практика
Всё идёт на стенде «Магазин» с профилем monitoring. Числа в выводе ниже пример: у тебя они будут другими, важна форма картины. «Плохая выкатка» на стенде это новая версия оплаты, которая отвечает медленнее и с отказами: на лету это включается через /admin/config (урок 3.1).
1. Папка, скрипты выката и отката
Заведи папку и два скрипта. Каждый делает две вещи: меняет поведение оплаты и ставит на дашборд Grafana аннотацию (отметку на графиках, что здесь произошло изменение).
mkdir -p ~/monitoring-lab/05-reliability/04-release && cd ~/monitoring-lab/05-reliability/04-release
cat > release.sh <<'EOF'
#!/usr/bin/env bash
# release.sh: «выкатка payment v2»: оплата медленнее и с отказами, плюс отметка в Grafana
set -eu
curl -fsS -X POST localhost:8001/admin/config -H 'Content-Type: application/json' \
-d '{"delay_ms":300,"fail_rate":0.6}'
echo
curl -fsS -X POST localhost:3000/api/annotations -H 'Content-Type: application/json' \
-d "{\"dashboardUID\":\"shop-overview\",\"time\":$(date +%s)000,\"tags\":[\"deploy\"],\"text\":\"выкатка payment v2\"}"
echo
date +%s > .release-at
EOF
cat > rollback.sh <<'EOF'
#!/usr/bin/env bash
# rollback.sh: откат на payment v1: прежние задержка и доля отказов, плюс отметка в Grafana
set -eu
curl -fsS -X POST localhost:8001/admin/config -H 'Content-Type: application/json' \
-d '{"delay_ms":50,"fail_rate":0}'
echo
curl -fsS -X POST localhost:3000/api/annotations -H 'Content-Type: application/json' \
-d "{\"dashboardUID\":\"shop-overview\",\"time\":$(date +%s)000,\"tags\":[\"deploy\"],\"text\":\"откат payment v2\"}"
echo
date +%s > .rollback-at
EOF
chmod +x release.sh rollback.sh
Скрипты пишутся через cat > файл <<'EOF': всё до строки EOF попадает в файл без подстановок, поэтому $(date +%s)000 вычислится при запуске, а не сейчас. date +%s это текущее время в секундах, добавленные 000 делают из него миллисекунды, которые ждёт Grafana. -fsS заставляет curl вернуть ошибку при ответе 4xx и 5xx и показать её. Запись в .release-at понадобится для расчёта бюджета.
Что должно получиться: скрипты лежат в папке и исполняемые.
release.sh rollback.sh
Типичные ошибки:
curl: (22) The requested URL returned error: 401при вызове Grafana: Grafana на стенде открыта без пароля, поэтому проверь, что отвечает именно она:curl -s localhost:3000/api/health.- Отметка не видна на графиках: в настройках дашборда (Settings, Annotations) должен быть включён встроенный запрос «Annotations & Alerts», он показывает отметки этого дашборда. Скрипт ставит
dashboardUID:"shop-overview", поэтому отметки видно только на дашборде «Магазин: обзор (эталон)».
2. Базовая линия: покупатели и спокойные графики
Открой дашборд «Магазин: обзор (эталон)» на http://localhost:3000, период Last 15 minutes, обновление 5 секунд. Запусти восьмёрых «покупателей» из урока 3.1 на 12 минут и убедись, что оплата в норме:
ORD=~/monitoring-lab/03-dashboards-alerts/orders.sh
for i in 1 2 3 4 5 6 7 8; do $ORD "$i" 720 & done
curl -s -X POST localhost:8001/admin/config -H 'Content-Type: application/json' -d '{"delay_ms":50,"fail_rate":0}'
Первая строка запоминает путь к скрипту, вторая запускает восемь копий в фоне, третья выставляет «нормальную» оплату (50 мс, без отказов), чтобы начать с чистого листа. Подожди три минуты и запиши в заметки базовую линию: долю 5xx, p95 заказа, число запросов в секунду.
Что должно получиться (пример):
{"delay_ms":50.0,"fail_rate":0.0}
Дашборд: 5xx около нуля, p95 заказов в десятках или сотнях миллисекунд, запросов в секунду много (в моём примере около 60).
3. Плохая выкатка: читаем графики до и после
Через три минуты после старта покупателей «выкати» новую версию оплаты:
cd ~/monitoring-lab/05-reliability/04-release
./release.sh
Скрипт включает медленную и отказывающую оплату (300 мс и 60% отказов выбраны с запасом, чтобы критерий отката ниже точно сработал) и ставит на графики отметку «выкатка payment v2». Смотри дашборд: линия отметки пересекает все графики, и по обе стороны от неё видно «до» и «после». Это главный приём разбора выкатки: не «что-то стало плохо», а «ровно после отметки стало плохо».
Вот как выглядит такая выкатка на панелях (пример, данные подобраны под расчёт ниже). Сначала доля ответов 5xx:
График показывает чёткую границу: до отметки ошибок почти нет, сразу после неё доля 5xx около 6,5%. Выше порога 2% она держится с 14:07 до отката. Такой скачок сразу за отметкой выкатки почти всегда виновата сама выкатка.
Теперь задержка заказа:
Заказ стал дольше секунды: оплата отвечает по 300 мс, при отказе магазин повторяет её до четырёх раз без паузы, а заказ в это время держит соединение пула. Покупатели занимают пять соединений, и остальные ждут. Это ровно то, что ты видел в уроке 3.1, только теперь вызвано выкаткой, а не вручную включённой поломкой.
Сводка до и после на панелях Stat:
Плохая выкатка видна сразу по всем золотым сигналам: растут ошибки и задержка, падает число запросов (пул занят ожиданием), появляется очередь. Если у тебя на дашборде меняется один из четырёх, а остальные нет, причина скорее в чём-то другом.
Теперь загляни в логи ошибок заказов. В Explore, источник Loki:
В логах одна и та же причина: «payment failed», то есть оплата отказала на всех повторах. Это подтверждает, что виновата выкатка оплаты, а не база или сеть. Трейс одного такого запроса показывает, куда ушло время:
Четыре попытки по 300 мс дают более полутора секунд, и это почти весь заказ. Простая арифметика объясняет и долю ошибок: при отказе оплаты в 60% все четыре попытки провалятся с вероятностью 0,6 в четвёртой степени, это около 13% заказов. А заказы это примерно половина всех запросов, поэтому общая доля 5xx получается около 6,5%.
Как читать вывод: сначала смотри на отметку выкатки и сравнивай «до» и «после» по четырём сигналам, потом логи: одна ли причина, потом трейс: где время.
Типичные ошибки:
- Графики не изменились: оплата не переключилась. Проверь
curl -s localhost:8001/admin/config: должно быть{"delay_ms":300.0,"fail_rate":0.6}. - Ошибок меньше расчётных: слишком мало покупателей или период 1 минута шумит. Оставь 8 копий
orders.shи смотри окно в 5 минут.
4. Критерий отката: скрипт check-release.sh
Критерий из теории превратим в проверку, которая сама спрашивает Prometheus стенда (localhost:9090):
cat > check-release.sh <<'EOF'
#!/usr/bin/env bash
# check-release.sh: критерий отката: 5xx выше 2% три минуты подряд или p95 заказа выше 1 с
PROM=${PROM:-http://localhost:9090}
q() { curl -fsS "$PROM/api/v1/query" --data-urlencode "query=$1" | jq -r '.data.result[0].value[1] // "0"'; }
ERR='100 * sum(rate(http_requests_total{status=~"5.."}[1m])) / sum(rate(http_requests_total[1m]))'
P95='histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket{route="/api/orders",method="POST"}[1m])))'
err=$(q "min_over_time(($ERR)[3m:15s])")
p95=$(q "min_over_time(($P95)[3m:15s])")
if awk -v e="$err" -v p="$p95" 'BEGIN { exit !(e > 2 || p > 1) }'; then
echo "ОТКАТ: 5xx $err% (порог 2), p95 заказа $p95 с (порог 1)"
else
echo "ЖДЁМ: 5xx $err%, p95 заказа $p95 с"
fi
EOF
chmod +x check-release.sh
while true; do ./check-release.sh; sleep 15; done
Скрипт разобран по частям. Функция q посылает запрос PromQL в API и достаёт число через jq (// "0" подставляет ноль, если ответ пуст). min_over_time((...)[3m:15s]) берёт значение выражения каждые 15 секунд за последние три минуты и выбирает самое маленькое: если даже оно выше порога, значит условие держится все три минуты подряд. awk сравнивает числа, потому что bash дробные не сравнивает. Цикл в конце печатает вердикт каждые 15 секунд, остановить его можно Ctrl+C.
Что должно получиться (пример, вывод по ходу выкатки):
ЖДЁМ: 5xx 0.12%, p95 заказа 0.13 с
ЖДЁМ: 5xx 0.12%, p95 заказа 0.13 с
ЖДЁМ: 5xx 2.4%, p95 заказа 0.9 с
ОТКАТ: 5xx 4.8%, p95 заказа 1.4 с
Как читать вывод: пока строка начинается с «ЖДЁМ», критерий не выполнен. Первая строка «ОТКАТ» это момент, когда по твоему правилу пора откатывать. Заметь задержку: из-за окна в три минуты скрипт срабатывает не сразу после выкатки, а на несколько минут позже. Это цена защиты от ложных тревог, и именно её видно на графике «жизни алерта».
Сначала алерт ждёт (pending), потому что одна плохая точка может быть случайной, и только после трёх подряд он загорается. Это три минуты, которые ты платишь за уверенность, поэтому для критических выкаток окно выбирают короче, а для шумных метрик длиннее.
Типичные ошибки:
- Всегда
ЖДЁМс нулями: нет трафика или вrouteдругое значение. Проверьcurl -s localhost:9090/api/v1/label/route/values | jq. NaNв выводе: за окно не было запросов, доля делит ноль на ноль. Запусти покупателей.
5. Откат и расход бюджета ошибок
Как только скрипт напечатает «ОТКАТ», откати:
./rollback.sh
Скрипт возвращает оплату в норму и ставит на графики отметку «откат payment v2». Через минуту-две доля 5xx и p95 на дашборде вернутся к базовой линии. Проверь, что оплата в норме: curl -s localhost:8001/admin/config покажет {"delay_ms":50.0,"fail_rate":0.0}.
Теперь посчитаем, сколько бюджета выкатка съела. Допустим SLO 99% за 30 дней, то есть 432 минуты. Формула: расход в процентах равен доле ошибок в процентах, умноженной на минуты и делённой на 432. Скрипт берёт отметки времени выкатки и отката, спрашивает у Prometheus число ошибок и запросов за это окно и считает:
cat > budget.sh <<'EOF'
#!/usr/bin/env bash
# budget.sh: сколько месячного бюджета ошибок (SLO 99%, 30 дней = 432 минуты) съела выкатка
set -eu
PROM=${PROM:-http://localhost:9090}
START=$(cat .release-at); END=$(cat .rollback-at); SECS=$((END - START))
q() { curl -fsS "$PROM/api/v1/query" --data-urlencode "query=$1" --data-urlencode "time=$END" | jq -r '.data.result[0].value[1] // "0"'; }
bad=$(q "sum(increase(http_requests_total{status=~\"5..\"}[${SECS}s]))")
all=$(q "sum(increase(http_requests_total[${SECS}s]))")
awk -v b="$bad" -v a="$all" -v s="$SECS" 'BEGIN { r = a > 0 ? b / a * 100 : 0; m = s / 60;
printf "ошибок %.0f из %.0f запросов: %.2f%%, минут %.1f, бюджета %.3f%%\n", b, a, r, m, r * m / 432 }'
EOF
chmod +x budget.sh
./budget.sh
Скрипт читает моменты выкатки и отката из файлов, спрашивает Prometheus на момент отката (time=$END), сколько ошибок и запросов было за окно (increase считает прирост счётчика), и применяет формулу.
Что должно получиться (пример):
ошибок 322 из 4960 запросов: 6.49%, минут 5.2, бюджета 0.078%
Как читать вывод: доля 6,49% при длительности 5,2 минуты дала 0,078% месячного бюджета, то есть мелочь. Но если бы выкатку заметили через 30 минут, было бы около 0,45%, а ночью без алерта за 8 часов около 7,2%. Тот же темп сгорания 6,5 раза быстрее нормы выедает весь месячный бюджет примерно за 4,6 суток. Вывод для SRE: короткий заметный сбой дёшев, дорог незамеченный долгий.
Во сколько раз отличаются строки, видно сразу: время обнаружения важнее самой силы сбоя, поэтому и нужен критерий отката и алерт на симптом.
Типичные ошибки:
cat: .release-at: No such file or directory: ты запускалrelease.shиз другой папки. Выполняй скрипты в04-release.- Бюджет заметно отличается от примера: у тебя другой трафик. Сверь формулу на своих числах:
доля × минуты / 432.
6. Мини-учения по восстановлению: шаг проекта
Проверим, что копия базы «Магазина» не просто есть, а восстанавливается, и замерим время. Восстанавливаем не поверх рабочей базы, а в отдельную shop_drill:
cd ~/learning/load-tester/project/shop
START=$(date +%s)
docker compose exec -T postgres pg_dump -U shop -Fc shop > ~/monitoring-lab/05-reliability/04-release/shop.dump
docker compose exec -T postgres psql -U shop -d postgres -c 'DROP DATABASE IF EXISTS shop_drill' -c 'CREATE DATABASE shop_drill'
docker compose exec -T postgres pg_restore -U shop -d shop_drill --no-owner < ~/monitoring-lab/05-reliability/04-release/shop.dump
docker compose exec -T postgres psql -U shop -d shop_drill -tAc 'SELECT count(*) FROM orders'
echo "прошло $(( $(date +%s) - START )) с"
Первая команда выгружает базу в сжатый файл (-Fc это формат custom, из него можно восстанавливать выборочно). Вторая создаёт пустую учебную базу. Третья восстанавливает дамп в неё. Четвёртая считает заказы в восстановленной базе, чтобы убедиться, что данные на месте, а не просто команда не упала. Последняя печатает время. Параметр -T нужен, чтобы docker compose exec работал с перенаправлением ввода и вывода.
Что должно получиться (пример, число заказов у тебя другое):
DROP DATABASE
CREATE DATABASE
2318
прошло 4 с
Как читать вывод: число строк в orders должно совпасть с числом в рабочей базе на момент дампа (SELECT count(*) FROM orders в базе shop). Это и есть проверка «копия читается». Время на маленьком стенде мало, на настоящей базе оно будет часами: именно его измеряют, чтобы честно записать RTO.
Теперь запиши план в dr.md в той же папке: таблицу целей для компонентов «Магазина». Пример заполнения:
| Компонент | Что хранит | RPO | RTO | Откуда восстанавливаем |
|---|---|---|---|---|
| Postgres | заказы, товары, пользователи | 15 мин | 45 мин | дамп и журнал изменений |
| Redis | корзины, без тома | не гарантируем | 5 мин | запускаем пустой |
| Grafana | дашборды, алерты | 0 | 30 мин | файлы в git |
| Prometheus | метрики за 15 дней | сутки | 2 ч | пустая база, история потеряна |
Заполни цели сам и объясни каждую строку одной фразой: что потеряет покупатель, если ты потеряешь этот компонент. Допиши в dr.md три строки: где лежит этот файл вне стенда, кто проверяет план и когда следующая проверка (раз в квартал).
Если пользуешься нейросетью для заполнения таблицы, проверь, что цели реалистичны: ИИ любит ставить RPO в ноль, не спрашивая о цене.
Типичные ошибки:
service "postgres" is not running: стенд не запущен или ты не в папке стенда. Перейди в~/learning/load-tester/project/shopи проверьdocker compose ps.pg_restore: error: ... already exists: учебная база уже была и в ней остались объекты. КомандаDROP DATABASE IF EXISTSперед восстановлением это решает.
Шаг проекта: в ~/monitoring-lab/05-reliability/04-release лежат release.sh, rollback.sh, check-release.sh, budget.sh, dr.md. Загляни в git status своего ~/monitoring-lab и сделай коммит с этой папкой.
Сломай и почини
Сломаем откат так, чтобы он выглядел выполненным.
Симптом
Ты выкатил v2, критерий сработал, и ты откатил оплату вручную, но поправил только задержку:
curl -s -X POST localhost:8001/admin/config -H 'Content-Type: application/json' -d '{"delay_ms":50}'
Команда вернула 200, p95 заказа упал, но доля 5xx на дашборде всё ещё около 6% и алерт горит.
Гипотезы
- Откат не дошёл до payment.
- Сбой не связан с выкаткой.
- Откатилась только часть настроек.
Проверки
curl -s localhost:8001/admin/config
Что должно получиться (пример):
{"delay_ms":50.0,"fail_rate":0.6}
Как читать вывод: задержка уже нормальная, а доля отказов осталась 0,6. Значит откат дошёл (гипотеза 1 отпала), сбой связан с выкаткой (гипотеза 2 отпала), а откатилось только половина изменения.
Исправление
Разбор
Верна гипотеза 3. Эндпоинт /admin/config меняет только переданные поля, а непереданные оставляет как есть (в коде это exclude_none), поэтому откат одного поля оставил второе. Исправление: передать оба значения, {"delay_ms":50,"fail_rate":0}, или просто запустить ./rollback.sh.
Урок общий: откат должен возвращать полное предыдущее состояние, а не набор отдельных правок по памяти. Поэтому выкатку и откат хранят как два скрипта, а не как «команды, которые помню». И после отката всегда проверяй метрики, а не только код ответа команды: 200 значит «принято», а не «вылечено».
ИИ в помощь
Нейросеть быстро набросает критерий отката и чек-лист учений, но выдумывает пороги и предлагает откатывать то, что откату не поддаётся (например, миграцию данных). Общие правила: ИИ-помощник.
Задача: составить критерий отката.
Сервис «Магазин»: SLO 99% по доле успешных запросов за 30 дней.
Метрики Prometheus: http_requests_total{route,status}, http_request_duration_seconds_bucket.
Составь критерий автоматического отката для canary: три условия с порогами и окнами,
по каждому дай запрос PromQL. Ответ: таблица «условие, порог, окно, запрос», до 10 строк.
Проверь ответ: выполни каждый запрос в Prometheus стенда, результат не должен быть пустым. Типичные ошибки: пороги «с потолка» без связи с SLO, окно в одну минуту, которое шумит, метрики всего сервиса вместо метрик канарейки.
Задача: составить план учений (game day).
Составь план game day на 1,5 часа для сервиса «Магазин» (shop, payment, postgres, redis).
Сценарий: оплата отвечает по 5 секунд. Нужны: цель учений, кто в какой роли, шаги ведущего,
что должен сделать дежурный, как понять, что учения прошли успешно. До 20 строк.
Проверь ответ: каждый шаг выполним на стенде (есть команда). Нейросеть любит добавлять сценарии, для которых на стенде нет средств (например, отказ зоны): вычеркни их.
Задача: проверить план восстановления.
Вот таблица целей RPO и RTO для моего сервиса (вставь свою). Найди в ней слабые места:
цели, которые нечем подтвердить, и компоненты без восстановления. Ответ: список вопросов, до 10.
Проверь ответ: ответь на каждый вопрос данными: временем из своего учебного восстановления, а не предположением.
Словарик урока
| Термин | Простыми словами |
|---|---|
| Политика бюджета ошибок | Заранее согласованное правило, что меняется в выкатках, когда бюджета мало |
| Canary (канарейка) | Выкатка новой версии на малую долю трафика с наблюдением |
| A/B-тест | Сравнение двух версий по бизнес-метрике, идёт дни и недели |
| Откат (rollback) | Возврат к предыдущей рабочей версии |
helm --atomic |
Выкатка, которая откатывается сама, если не стала здоровой за время ожидания |
helm rollback |
Команда возврата релиза на предыдущую ревизию |
| readiness, liveness | Пробы: готов ли принимать трафик, и жив ли процесс |
| Критерий отката | Заранее записанное условие по метрикам, при котором откатываем без споров |
| Preprod | Окружение, похожее на боевое, для проверки изменений |
| Хаос-тест | Намеренная поломка части системы, чтобы проверить устойчивость |
| Game day | Учения: команда отрабатывает заранее подготовленный сбой |
| DR | Аварийное восстановление: план возврата сервиса после тяжёлой потери |
| RPO | Сколько данных (во времени) готовы потерять |
| RTO | Сколько времени готовы быть недоступны |
Вопросы с собеседований
Раздел для повторения: ответь вслух, потом открой ответ. Короткие вопросы с пометкой [на скорость] тренируй на время: ответ за 30 секунд.
1. [junior] [часто] Что такое бюджет ошибок и что делают, когда он кончился?
Ответ
Бюджет ошибок это допустимая доля сбоев за период, которую оставляет SLO: при 99% за 30 дней это 1%, то есть 432 минуты полной недоступности (урок 1.2). Пока он есть, команда выкатывает смело. Когда он тает, действует заранее согласованная политика: например, при 90% расхода выкатываются только исправления надёжности и безопасности, при превышении идёт разбор причин.
Что хотят услышать: бюджет это разрешение на риск, политика записана заранее и подписана командой и владельцем продукта, ступени вместо «стоп или вперёд».
Красный флаг: бюджет называют «квотой на баги», а заморозку объявляют по настроению в момент кризиса.
2. [junior] [часто] Какая роль у SRE в релизном цикле?
Ответ
SRE не привратник, который говорит «нет», а тот, кто делает безопасный путь простым: помогает выбрать метрики выкатки и критерий отката, настраивает canary и автоматический откат, следит за бюджетом ошибок и участвует в разборе, если изменение всё же сломало. Решение «можно ли выкатывать сейчас» опирается на согласованную политику бюджета, а не на мнение одного человека.
Что хотят услышать: помощь и автоматика вместо запретов, критерий отката заранее, ссылка на политику бюджета, разбор без поиска виноватых (урок 5.2).
Красный флаг: «SRE утверждает каждый релиз вручную» или «SRE отвечает за откат, остальные не при чём».
3. [junior] [часто] По каким признакам решают, что выкатку пора откатывать?
Ответ
По заранее записанному критерию на симптомы покупателя: например, доля 5xx выше 2% три минуты подряд или p95 оформления заказа выше секунды. Дополнительно смотрят, началось ли ухудшение сразу после отметки выкатки, есть ли в логах следы изменённого кода и растёт ли проблема. Если сомневаешься и изменение свежее, откатывают, а причину ищут потом: откат дёшев, а каждая минута сбоя тратит бюджет.
Что хотят услышать: критерий измерим и написан заранее, сравнение «до и после» отметки выкатки, откат по умолчанию при сомнении.
Красный флаг: «Подождём ещё, может само пройдёт» без срока и порога, или откат без проверки, что метрики вернулись.
4. [middle] Чем canary отличается от A/B-теста?
Ответ
Canary выкатывает новую версию на малую долю трафика, чтобы проверить, что она не сломана: смотрят ошибки и задержку именно этой версии, ступени 5%, 25%, 50%, 100%, всё занимает минуты. A/B-тест делит пользователей, чтобы выбрать версию по бизнес-метрике (конверсия, чек), идёт дни и недели, обе версии заведомо рабочие. Технически трафик делится весами в обоих случаях. Метрики канарейки смотрят отдельно, иначе плохие ответы 5% трафика растворятся в общем графике (DevOps 9.6).
Что хотят услышать: разная цель и длительность, метрики канарейки отдельно по версии, автоматизация через Argo Rollouts или Flagger.
Красный флаг: считают их одним и тем же или судят о надёжности канарейки по общему графику сервиса.
5. [middle] Как устроен откат в Helm и чем --atomic отличается от helm rollback?
Ответ
helm upgrade --install --atomic --timeout 5m откатывает релиз сам, если за время ожидания приложение не стало готовым (в Helm 4 флаг называется --rollback-on-failure). helm history показывает ревизии, helm rollback <релиз> 0 возвращает предыдущую ревизию в любой момент, а не только при неудачном запуске. Откат оформляют кнопкой в CI (when: manual в GitLab CI), чтобы не вспоминать команды ночью. Откат Helm возвращает манифесты, но не данные: миграцию базы он не отменит (DevOps 5.9).
Что хотят услышать: --atomic для неудачного запуска, rollback для любой прошлой ревизии, ручная кнопка в CI, откат не отменяет миграции данных.
Красный флаг: «откат всегда безопасен» или откат, который ни разу не пробовали до аварии.
6. [middle] Почему откат вручную в GitLab CI оформляют отдельным шагом, и что туда кладут?
Ответ
Отдельная задача с when: manual превращает откат в кнопку: человек нажимает её в интерфейсе, не вспоминая команд, прав и параметров в три часа ночи. Внутри лежит helm rollback на предыдущую ревизию с ожиданием готовности, а ссылка на задачу есть в runbook. Кнопку проверяют заранее на тестовом окружении, а доступ ограничивают ролями.
Что хотят услышать: кнопка вместо ручных команд, проверка до аварии, ссылка в runbook, ограничение доступа.
Красный флаг: откат живёт только в голове одного инженера или в заметках, которые никто не открывал.
7. [junior] В чём разница между пробами readiness и liveness?
Ответ
readiness отвечает «готов ли под принимать трафик»: если нет, Kubernetes убирает его из балансировки, запросы идут на остальные. liveness отвечает «жив ли процесс»: если нет, под перезапускают. При выкатке readiness не пускает трафик на новую версию, пока она не запустилась. Перезапуск по liveness не лечит перегрузку, поэтому её проба должна быть проще и надёжнее (DevOps 5.7).
Что хотят услышать: два разных вопроса и две разные реакции: балансировка и перезапуск, readiness защищает выкатку.
Красный флаг: смешивают пробы или ставят в liveness проверку зависимостей, из-за чего поды перезапускаются по чужой вине.
8. [middle] Чем отличаются HPA и VPA, и что ещё автоматизируют в реакции на предсказуемые сбои?
Ответ
HPA добавляет или убирает копии приложения по нагрузке, VPA подбирает CPU и память одной копии (DevOps 5.11). Кроме них автоматизируют перезапуск упавших процессов, убирание неготовых подов из балансировки, откат неудачной выкатки и рутину инцидента: канал, вызов дежурного, шаблон статуса, ссылка на runbook. У автоматики есть предохранители, чтобы она не устроила шторм, и за ней тоже следят.
Что хотят услышать: предсказуемое отдаём машине, но с ограничениями и мониторингом самой автоматики.
Красный флаг: автоматизируют всё подряд без лимитов или не следят за срабатываниями автоматики.
9. [middle] Зачем нужен preprod и когда он бесполезен? Что такое хаос-тест и game day?
Ответ
Preprod это окружение для интеграционных проверок: сервисы работают вместе, как у покупателей. Он полезен, только если похож на продакшен: версии, объём данных и трафик. Пустой preprod с одним запросом в минуту не покажет ни исчерпание пула, ни шторм повторов. Хаос-тест намеренно ломает часть системы (под, сеть, зависимость) и проверяет гипотезу об устойчивости; для Kubernetes есть Litmus и Chaos Mesh. Game day это учения команды: отрабатываются алерт, дежурный, откат, связь. Начинают с малого радиуса поражения и записанной гипотезы.
Что хотят услышать: похожесть на продакшен, гипотеза и малый радиус у хаоса, game day проверяет людей и инструкции.
Красный флаг: хаос запускают в продакшене без гипотезы и без возможности остановить, а preprod считают проверкой «на всякий случай».
10. [junior] [часто] [на скорость] Что такое RPO и RTO? Назови по одной фразе.
Ответ
RPO (recovery point objective) это сколько данных, измеренных во времени, готовы потерять: RPO 15 минут значит потерю записей последних 15 минут. RTO (recovery time objective) это сколько времени готовы быть недоступны, и оно включает всё: заметить, собрать людей, найти копию, восстановить, проверить, переключить трафик (DevOps 10.3).
Что хотят услышать: RPO про данные, RTO про время, оба по худшему случаю, RTO это не только команда восстановления.
Красный флаг: путают с SLA и SLO или считают RTO временем одной команды pg_restore.
11. [middle] Чем план аварийного восстановления (DRP) отличается от инструкции на сбой, и что в нём должно быть?
Ответ
Инструкция отвечает на узкий сбой («перезапусти оплату»). DRP описывает тяжёлые сценарии: потеряна база, площадка, кластер. В нём есть цели RPO и RTO для каждого компонента, роли, копии кода, документации и данных вне основной системы, несколько пулов узлов или площадок, запасные каналы связи и расписание проверок: восстановление из копии и переключение на запасной канал полезно репетировать раз в квартал. Копия, из которой ни разу не восстанавливались, это надежда, а не копия.
Что хотят услышать: цели по компонентам, хранение отдельно от основной системы, проверка по расписанию, замер времени восстановления.
Красный флаг: план лежит на упавшем сервисе, цели «ноль потерь» без цены, проверка «когда-нибудь».
Проверено на версиях
Стенд «Магазин» из load-tester/project/shop: Prometheus 3.15 (prom/prometheus:v3.15.0), Grafana 13.2 (grafana/grafana:13.2.3), Loki 3.7 (grafana/loki:3.7.8), Tempo 2.10 (grafana/tempo:2.10.8), Alloy 1.20 (grafana/alloy:v1.20.1), Alertmanager 0.34 (prom/alertmanager:v0.34.1), PostgreSQL 18.6 (postgres:18.6), Redis 8.10 (redis:8.10.2), Python 3.14 (python:3.14.8-slim), Docker Compose v2, jq 1.7. Октябрь 2026.
Итог урока: ты умеешь
- Объяснить, почему частые маленькие релизы безопаснее больших, и как искать виновного.
- Описать политику бюджета ошибок и что меняется, когда бюджет кончается.
- Отличить canary от A/B и сказать, почему метрики канарейки смотрят отдельно.
- Объяснить откат:
helm --atomic,helm rollback, ручную кнопку в CI, пробаreadiness. - Записать критерий отката по симптомам и принять решение по графикам до и после выкатки.
- Посчитать расход бюджета ошибок и показать, почему время обнаружения важнее силы сбоя.
- Назвать, что автоматизируют, а что нет, и зачем preprod, хаос-тесты и game day.
- Объяснить RPO и RTO, составить таблицу целей и проверить восстановление из копии.
Где это применить
- DevOps, урок 9.6: прогрессивная доставка: canary и откат по метрикам инструментами Argo Rollouts и Flagger.
- DevOps, урок 5.9: Helm:
helm upgrade --atomic, история ревизий иhelm rollbackна настоящем кластере. - DevOps, урок 8.11: паттерны надёжности и burn rate: алерты по сгоранию бюджета и политика, привязанная к ним.
- DevOps, урок 10.3: бэкап, DR и ёмкость: RPO, RTO, учения по восстановлению и правило трёх копий.
- load-tester, урок 7.6: алерты и инцидент: алерты стенда и первый инцидент по хронологии.
Дальше: тема 5 закончена, дальше ты применяешь её на курсах DevOps и нагрузочного тестирования. Возьми свой dr.md и критерий отката в проект «Заметки» из курса DevOps и проверь их там на настоящем Kubernetes.
Проверь себя
Короткий тест по уроку: 5 вопросов из банка в 30. Засчитывается только полностью правильный ответ, порог 60%. Каждая новая попытка даёт другие вопросы, пока банк не закончится. Ответы видны после проверки.
Тест работает с включённым JavaScript.