open atlas
↑ К треку
CI/CD-пайплайны CICD · 03 · 01

Continuous delivery против deployment и стратегии релиза

Continuous delivery держит release-ready артефакт, а деплой жмёт человек; continuous deployment авто-отгружает каждый зелёный коммит. Дальше выбери стратегию выката: blue-green, canary, rolling или за флагом — у каждой своя скорость отката, цена инфры и совместимость с БД.

CICD Middle ◷ 17 min
Уровень
ОсновыJuniorMiddleSenior

В 14:02 команда щёлкает blue-green переключателем: трафик одним изменением на балансировщике уходит со старого окружения на новое. Латентность ровная, ошибки ровные — деплой выглядит идеально. В 14:09 очередь в поддержку взрывается. Новый релиз прогнал миграцию, удалившую колонку, в которую старый код всё ещё писал, и хвалёный «мгновенный откат» теперь бесполезен: переключение назад шлёт живой трафик в код, запрашивающий колонку, которой в базе больше нет. Стратегия деплоя была здравой. Совместимость с базой — нет, и именно на этой линии чаще всего ломаются стратегии релиза.

Две буквы D: delivery решает кто жмёт «пуск», deployment убирает кнопку

Эти два термина постоянно путают, а разница — в одном предложении. Continuous delivery означает, что каждое изменение, прошедшее пайплайн, даёт артефакт, который всегда готов к релизу; доставка его в прод — осознанное действие человека: кто-то жмёт «деплой». Continuous deployment убирает этот клик: каждый коммит, прошедший весь пайплайн зелёным, едет в прод автоматически, без человека в цикле.

Разрыв между ними — не инструменты, а доверие. Один и тот же пайплайн стоит за обоими; deployment — это просто delivery с таким покрытием тестами, мониторингом и быстрым откатом, что ты позволяешь машине жать «пуск». Важно: delivery против deployment — это отдельная ось от того, какую стратегию выката ты используешь. Ты решаешь, кто жмёт «пуск» (delivery против deployment), и затем — независимо — как новая версия доходит до пользователей (blue-green, canary, rolling или за флагом). Команда может вести continuous deployment с canary-выкатом или continuous delivery с blue-green переключением; два выбора комбинируются.

Blue-green: два окружения, переключение на балансировщике

Blue-green держит два идентичных прод-окружения. Blue обслуживает живой трафик; новую версию ты деплоишь на простаивающий Green, smoke-тестируешь его вне линии, потом переключаешь балансировщик — весь трафик разом уходит на Green. Откат — то же переключение наоборот, назад на Blue, — поэтому он по сути мгновенный, порядка секунд, без пересборки и передеплоя.

Счёт состоит из двух частей. Первая — цена: во время перекрытия ты гоняешь примерно 2× инфраструктуры, потому что оба полных окружения существуют одновременно (облачный автоскейлинг смягчает это, но простаивающее окружение — реальные траты). Вторая, и она-то и кусается: база общая, и схема должна быть совместима сразу с обеими версиями. Переключение мгновенно меняет код приложения; оно не раздваивает базу. Если релиз Green прогоняет деструктивную миграцию — удаляет колонку, переименовывает таблицу, сужает тип, — то в момент, когда тебе нужно откатиться на Blue, всё ещё работающий код Blue упирается в схему, которую больше не понимает, и твой мгновенный откат испаряется. Дисциплина, делающая blue-green безопасным, — паттерн expand/contract (parallel change): сначала расширь схему аддитивно (добавь новую колонку, сохрани старую), задеплой код, читающий обе, перенеси данные, и только сожми — удали старую колонку — релизом позже, когда из неё уже никто не читает. Никогда не отгружай несовместимое назад изменение схемы в том же релизе, в котором переключаешься.

Canary: пусти срез, смотри метрики, наращивай или откатывай

Canary-релиз отправляет новую версию сначала на малую долю трафика — частый разгон 1% → 5% → 25% → 50% → 100% — пока ты сравниваешь её частоту ошибок и латентность со старой версией на остальном. Если canary выглядит здоровым, ты наращиваешь; если он пробивает порог, ты возвращаешь всех на стабильную версию, успев подставить под баг лишь этот малый срез.

Самое важное слово здесь — автоматический. Canary без автоматического метрик-гейта — это просто ручной деплой, который ты нянчишь: инженер косится в дашборд Grafana, моргнёт, уйдёт на обед или примет шум за сигнал. Настоящий canarying завязывает выкат на твои SLO — задай окно и минимальный размер выборки (например, окно в 10 минут, ≥5000 запросов, чтобы не решать на статистическом шуме), пороги вроде рост частоты ошибок > 0,3% над контролем или p99 латентности +5% и автоматический триггер отката при пробое. Тонкость, которую команды упускают: меряй частоту отказов внутри canary-среза, а не глобально. Если canary держит 5% трафика, полный обвал этих пользователей едва шевельнёт глобальную частоту ошибок — при том что 100% canary-пользователей падают. Сравнивай canary и контроль на одном знаменателе, иначе гейт тебе врёт.

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

Почему ручной canary так опасен? Потому что он ощущается безопасным — ты «всего лишь» послал 5% трафика на новую версию, — а на деле убирает то самое, что делает canarying рабочим: быстрое, объективное, всегда наблюдающее решение. Вся ценность в том, чтобы «поймать плохой релиз на 5% пользователей за минуты и авто-откатить». Человек, заглядывающий в дашборд время от времени, превращает это в «может, поймаю, может, через час, может, после того как дашборд уже пролистал всплеск». Если ты не можешь подключить метрик-гейт, blue-green переключение, откатываемое за секунды, нередко честнее, чем canary, за которым ты подсматриваешь глазами.

Rolling и за флагом: дешёвая и расцепляющая

Rolling-деплой заменяет инстансы пачка за пачкой — гасит несколько старых подов, поднимает новые, повторяет — пока весь флот не перейдёт на новую версию. Это самая дешёвая стратегия и дефолт Kubernetes: ни второго окружения, ни 2× инфры. Цена двойная. Первая — смешанные версии работают одновременно во время выката, старые и новые инстансы обслуживают запросы бок о бок, а значит несовместимое назад изменение API или схемы — это живой баг: старый под и новый под оба должны уметь обработать любой запрос и читать одну базу, иначе пользователи ловят ошибки посреди выката. Вторая — откат медленный: переключения нет; приходится катить вперёд (или назад) пачка за пачкой заново, и это так же долго, как и сам деплой.

Релиз за фича-флагом бьёт по другой проблеме: он расцепляет деплой и релиз. Ты отгружаешь новый код в прод тёмным — задеплоенным, но за рантайм-флагом, который выключен, — а потом включаешь его по когортам (внутренние пользователи, затем 1%, затем регион) переключением флага, без передеплоя. Выключить фичу — это изменение конфига, вступающее в силу за секунды, и это самый быстрый «откат» из всех, потому что ничего не передеплоивается. Флаги также дают тёмные запуски: гонять новый путь кода на реальном трафике, но отбрасывать его результат, сравнивая производительность и частоту ошибок до того, как кто-то из пользователей это увидит. Цена — стоимость владения и сложность: каждый живой флаг — это ветка в коде и комбинаторная поверхность тестирования, а протухшие флаги гниют в мины, поэтому у флага должен быть владелец и срок жизни.

СтратегияСкорость откатаДоп. инфраСмешанные версии живут?Фирменный режим отказа
Blue-greenСекунды (переключить назад)~2× (два полных окружения)Нет (переключение разом)Деструктивная миграция ломает откат
CanaryСекунды–минуты (перенаправить срез)Малая (одна лишняя версия)Да (во время разгона)Нет авто-гейта → ручное нянченье
RollingМедленно (откат пачка за пачкой)НетДа (весь выкат)Несовместимое назад API/схема в выкате
Фича-флагМгновенно (флаг, без передеплоя)Нет (сервис флагов)Н/Д (деплой ≠ релиз)Гниение флагов, комбинаторика тестов

Canary-гейт в CI/CD — это обычно метрик-запрос к твоей системе мониторинга, с выкатом на паузе до прохождения. Концептуально:

# canary в стиле argo-rollouts с SLO-гейтом (набросок)
strategy:
  canary:
    steps:
      - setWeight: 5        # 5% трафика на новую версию
      - pause: { duration: 10m }   # наблюдай реальное окно
      - analysis:           # автоматический гейт, не человек
          templates: [error-rate]
          # шаблон error-rate: провал, если 5xx(canary) - 5xx(stable) > 0.3%
          # на >=5000 запросов -> авто-откат, прервать разгон
      - setWeight: 25
      - pause: { duration: 10m }
      - setWeight: 100      # промоут
# антипаттерн ручного нянченья, который это заменяет:
kubectl set image deploy/api api=api:v2   # 5% canary по числу реплик
# ...а потом инженер пялится в дашборд и надеется заметить всплеск
Выбери лучший вариант

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

Викторина

Вышел blue-green деплой, потом всплыл критический баг. Команда переключается назад на Blue — но приложение теперь кидает ошибки БД на каждом запросе. Что вероятнее всего произошло?

Вспомните перед уходом
  1. 01
    Отличи continuous delivery от continuous deployment и объясни, почему стратегия выката — отдельный выбор.
  2. 02
    Назови фирменный режим отказа blue-green, canary и rolling и единственный фикс для каждого.
Итог

Continuous delivery и continuous deployment различаются одним шагом: delivery держит всегда готовый к релизу артефакт, и деплой жмёт человек, а deployment авто-отгружает каждый зелёный коммит — тот же пайплайн, где deployment заслужен покрытием тестами, мониторингом и быстрым откатом. Этот выбор не зависит от стратегии выката, которую ты выбираешь по своим причинам. Blue-green гоняет два идентичных окружения и переключает трафик на балансировщике ради отката за секунды, ценой ~2× инфры и жёсткого правила, что общая схема должна подходить обеим версиям, — деструктивная миграция убивает откат, если не использовать expand/contract. Canary пускает малый срез (скажем, 1%→5%→25%→100%) и сравнивает его со стабильной версией, но работает только с автоматическим метрик-гейтом, завязанным на SLO и меряемым внутри canary-среза; без гейта это ручной деплой, который ты нянчишь. Rolling заменяет инстансы пачка за пачкой при нулевой доп-инфре, принимая живые смешанные версии (поэтому изменения должны быть совместимы назад) и медленный откат. Фича-флаги расцепляют деплой и релиз целиком: отгрузи тёмным, включай по когортам в рантайме, откатывай за секунды переключением флага — оплачивая это стоимостью владения и гниением протухших флагов. Подбирай стратегию под свои потребности в откате, бюджет инфры и — прежде всего — совместимость с базой данных. Теперь, когда встретишь пост-мортем с фразой «мгновенный откат не сработал», первым делом спроси: а прошла ли миграция? Ответ сразу покажет, какая стратегия была выбрана не для того случая.

Практика

Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 5 завершено
Связанные уроки

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

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

Trademarks belong to their respective owners. Editorial reference only.