awesome-everything EN
↑ Обратно к восхождению

Деплой и инфра

Стратегии выката: размен радиуса поражения на стоимость ресурсов и скорость отката

Суть Recreate, rolling, blue-green, canary — четыре способа выкатить новую версию. Выбор — это размен между радиусом поражения, стоимостью ресурсов и скоростью отката, и все четыре несущие, только если держатся health-чеки, план отката и совместимость схемы.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на junior-высоте — поверхность
◷ 16 min

Rolling update выкатывается в 14:00. Дашборды зелёные — Deployment рапортует «available», все реплики подняты. И тут 30% запросов начинают отдавать 502. Новые поды загрузились, Kubernetes пометил их ready в тот же миг, как стартанул контейнер, и трафик пошёл туда раньше, чем приложение подключилось к базе. Readiness-пробы не было. Выкат «успешно» зашёл прямо в тихий частичный отказ, и понадобилось 20 нервных минут, чтобы понять — причина в деплое.

Четыре стратегии и чего стоит каждая

Релиз может принять ровно четыре формы, и выбор одной — это инженерный размен, а не дефолт.

Recreate убивает все старые инстансы, потом стартует новые. Просто, без пересечения версий — что важно, когда две версии действительно не могут сосуществовать (несовместимое in-place изменение схемы, singleton-джоба). Цена — downtime: окно, когда ничего не обслуживает. Допустимо только для не-HA сервисов или окон обслуживания.

Rolling update — дефолт Kubernetes. Заменяет поды постепенно — подними несколько новых, слей несколько старых, повтори — так сервис никогда не падает полностью. Настраивается двумя ручками: maxSurge (сколько лишних подов сверх желаемого количества может существовать в процессе выката) и maxUnavailable (сколько может отсутствовать). Оба по умолчанию 25%.

Blue-green держит два полных окружения. «Blue» обслуживает прод, пока «green» получает новую версию, полностью развёрнутую и прогретую; затем ты атомарно переключаешь роутер. Откат мгновенный — переключи обратно. Цена — примерно двойные ресурсы во время переключения, плюс проблема совместимости с базой (ниже).

Canary направляет небольшой срез трафика — обычно 5%, потом 25%, потом 50% — на новую версию, смотрит метрики на каждом шаге и наращивает только если error rate и latency остаются здоровыми. Самый маленький радиус поражения, но нужны traffic-shaping и реальная observability. Инструменты вроде Argo Rollouts и Flagger автоматизируют шаги и метрические гейты (progressive delivery).

Rolling update: readiness-проба не опциональна

Отказ из Hook — каноничный провал rolling update. Kubernetes отправляет трафик в новый под в тот момент, когда он ready — а по умолчанию под считается ready, как только стартует процесс контейнера. Если приложению нужны три секунды, чтобы открыть соединения с БД и прогреть кэш, это трёхсекундное окно на каждый под, в котором ты направляешь живой трафик в процесс, который не может обслуживать.

Корректная readiness-проба закрывает это окно: Kubernetes придерживает трафик, пока проба не пройдёт (и не истёк minReadySeconds). Без неё maxUnavailable: 25% тебя не защищает — четверть мощности может быть одновременно «ready» и мёртвой. Безопасный для сеньора конфиг для zero-downtime: maxSurge: 1, maxUnavailable: 0 плюс настоящая readiness-проба — никогда не падать ниже полной мощности и никогда не слать трафик в под, который не доказал, что может отвечать.

Почему это работает

Readiness-проба и liveness-проба — не одно и то же, и путаница вызывает отказы. Liveness перезапускает под, который считает мёртвым — наведи её на медленную зависимость, и икота бэкенда вызовет шторм рестартов. Readiness лишь убирает под из ротации балансировщика. Во время выката трафик гейтит именно readiness; liveness-проба, делающая двойную работу, радостно поубивает поды, которые были просто заняты.

Blue-green: мгновенный откат, но база не переключается

Главный козырь blue-green — атомарное переключение и мгновенный откат, который оно даёт. Ловушка в том, что ты переключаешь приложение атомарно, но база общая — она не переключается. В день, когда green выкатывает миграцию, дропающую или переименовывающую колонку, blue (всё ещё твоя цель отката) теперь сломан против живой схемы. Переключишь обратно — упадёт. Твой «мгновенный откат» испарился ровно тогда, когда он нужен.

Фикс — паттерн expand-contract (parallel change): никогда не делай ломающее изменение схемы за один шаг.

ФазаДействие со схемойПочему обе версии выживают
ExpandДобавь новую колонку/таблицу; старую оставьСтарый код игнорирует новое поле; новый читает оба — аддитивное изменение обратносовместимо
MigrateБэкфилл данных; dual-write старое + новоеОбе формы заполнены, поэтому откат к старому коду всё ещё находит свои данные
ContractДропни старую колонку — в более позднем деплоеТолько после того, как старая версия полностью выведена и отката к ней не будет

Это и значит «обратносовместимые изменения схемы» на практике, и это применимо к rolling и canary тоже — любая стратегия с двумя живыми версиями приложения требует схему, которую читают обе.

Выбор: радиус поражения vs стоимость ресурсов vs скорость отката

Универсально лучшей стратегии нет; ты взвешиваешь три оси. Радиус поражения — скольких пользователей задевает плохой релиз до того, как ты его поймал: у canary самый маленький, у recreate — тотальный. Стоимость ресурсов — blue-green платит за два полных окружения; canary и rolling переиспользуют один пул; recreate дешевле всех. Скорость отката — blue-green и canary почти мгновенны (переключи роутер / уведи вес в ноль); rolling приходится катить назад под за подом; recreate — это второй downtime.

Решающий фактор — обычно качество твоей observability. Крошечный радиус поражения canary бесполезен, если ты не можешь по метрикам понять, что 5%-й срез падает — ты накатишь его до 100% вслепую. Без крепких дашбордов и алертов на основе SLO хорошо настроенный rolling update с readiness-пробой бьёт canary, который ты не можешь прочитать.

Выбери лучший вариант

Платёжный API на Kubernetes выкатывает рискованный рефакторинг. У тебя есть дашборды Prometheus и SLO-алерты, достаточная ёмкость кластера и нужно минимальное возможное влияние на пользователей, если что-то пойдёт не так. Выбери стратегию выката.

Викторина

Rolling update рапортует «available», но ~30% запросов отдают 502 сразу после деплоя. Какая самая вероятная корневая причина?

Викторина

Ты используешь blue-green и хочешь, чтобы откат оставался безопасным. Релиз green переименовывает колонку. Что делать?

Расставь шаги по порядку

Расставь шаги безопасного canary-выката рискованного изменения:

  1. 1 Выкати обратносовместимое (expand) изменение схемы, чтобы старая и новая версии обе работали
  2. 2 Направь 5% трафика на новую версию
  3. 3 Следи за error-rate и latency против SLO на этом шаге
  4. 4 Если здорово — наращивай 25% → 50% → 100%; если нет — верни вес в 0 (откат)
  5. 5 Когда полностью на новой версии и стабильно — contract: дропни старую схему в более позднем деплое
Вспомните перед уходом
  1. 01
    Rolling update рапортует успех, но пользователи видят периодические 502. Объясни почему и какое одно изменение это чинит.
  2. 02
    Почему «мгновенный откат» blue-green ломается, когда релиз меняет схему, и как expand-contract его восстанавливает?
Итог

Четыре формы выката, один размен. Recreate прост, но берёт downtime — годится только для не-HA сервисов. Rolling update — дефолт Kubernetes, настраивается через maxSurge и maxUnavailable (оба по умолчанию 25%), и он безопасен только с корректной readiness-пробой: без неё трафик идёт в поды, которые стартанули, но обслуживать не могут, давая «успешный» деплой прямо в тихий частичный отказ. Blue-green даёт атомарное переключение и мгновенный откат ценой двойных ресурсов — но общая база не переключается, поэтому ломающая миграция убивает твою цель отката, если не использовать expand-contract (добавь, dual-write, дропни позже). У canary самый маленький радиус поражения — 5% → 25% → 50% с гейтом по метрикам, автоматизируется через Argo Rollouts или Flagger — но он хорош ровно настолько, насколько хороша observability, читающая canary-срез. Выбирай, взвешивая радиус поражения против стоимости ресурсов против скорости отката, и помни несущий пререквизит под всеми четырьмя: health-чеки, план отката и обратносовместимые изменения схемы.

Продолжить восхождение ↑Rollout strategies: обзор с выбором ответа
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources4
expand
  1. 01
  2. 02
  3. 03
  4. 04

Trademarks belong to their respective owners. Editorial reference only.