Стратегии деплоя: blue-green, canary и откат
Сценарный вопрос уровня middle+: интервьюер хочет услышать не список стратегий, а обоснованный выбор под конкретные условия.
Вопрос: «Какие стратегии деплоя вы знаете? Какую выберете для платёжного сервиса, а какую — для внутренней админки, и почему?»
Что на самом деле проверяет интервьюер
Проверяют инженерное мышление: понимаете ли вы, что каждая стратегия — это размен между стоимостью инфраструктуры, скоростью выкатки и радиусом поражения при ошибке. Второй, более глубокий слой — знаете ли вы, что все эти стратегии красиво работают только для stateless-приложений, а миграции базы данных ломают любую из них, если не проектировать их обратно совместимыми.
Развёрнутый ответ: четыре стратегии
Recreate
Погасить всё старое, поднять всё новое. Простота ценой простоя. Единственный вариант, когда две версии физически не могут работать одновременно: например, приложение держит эксклюзивную блокировку или несовместимую схему данных. Для внутренней админки, где минута простоя ночью никого не смущает, это вполне разумный выбор.
Rolling update
Поштучная замена реплик — стратегия по умолчанию в Kubernetes, разобрана в предыдущем разделе. Простоя нет, дополнительной инфраструктуры почти не нужно. Минусы: некоторое время в проде работают обе версии одновременно (значит, API и схема данных обязаны быть совместимы), а откат — это ещё одна такая же поштучная выкатка, то есть небыстро.
Blue-green
Поднимается полная копия окружения с новой версией (green) рядом с текущей (blue). После прогона проверок трафик переключается целиком — на балансировщике или сменой селектора Service. Старое окружение остаётся нетронутым.
# версия зашита в метку пода, Service выбирает нужный цвет
kubectl apply -f deploy-green.yaml # поднять новую версию рядом
kubectl port-forward deploy/api-green 8080:8080 # проверить вживую
# переключение всего трафика одной командой
kubectl patch svc api -p '{"spec":{"selector":{"app":"api","version":"green"}}}'
# откат — обратный patch, секунды
kubectl patch svc api -p '{"spec":{"selector":{"app":"api","version":"blue"}}}'
Плюсы: мгновенный откат и возможность полноценно проверить новую версию до подачи трафика. Минус: на время выкатки нужен двойной запас мощности, а это деньги. Отдельный нюанс — долгоживущие соединения и сессии: при резком переключении их нужно куда-то деть, поэтому состояние сессий выносят в общий Redis.
Canary
Новая версия получает маленькую долю реального трафика — 1%, 5%, 25% — и на каждом шаге сравниваются метрики ошибок и задержек с контрольной группой. Если всё в порядке, доля растёт; если метрики поплыли, трафик возвращается на старую версию.
Это лучший вариант для платёжного сервиса: радиус поражения минимален. Ошибку, которую не поймали тесты, увидит 1% пользователей, а не все. Цена — сложность: нужны маршрутизация по весам (Ingress с весами, service mesh, Argo Rollouts или Flagger) и, главное, метрики, по которым автоматика принимает решение. Canary без автоматического анализа метрик — это просто «выкатили и смотрим в графики руками».
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: api
spec:
replicas: 10
strategy:
canary:
analysis:
templates:
- templateName: error-rate # автооткат по метрике ошибок
steps:
- setWeight: 5
- pause: { duration: 5m }
- setWeight: 25
- pause: { duration: 10m }
- setWeight: 50
- pause: { duration: 10m }
Сравнительная таблица
| Стратегия | Простой | Доп. мощности | Скорость отката | Радиус поражения |
| Recreate | есть | нет | медленно | 100% |
| Rolling | нет | небольшие | средне | растёт постепенно |
| Blue-green | нет | ×2 | секунды | 100% после переключения |
| Canary | нет | небольшие | быстро | минимальный |
Отдельно: feature flags и миграции БД
Сильный ход в ответе — разделить деплой (код доехал до сервера) и релиз (функциональность стала доступна пользователям). Feature flag позволяет выкатить код выключенным и включить его отдельным действием, мгновенно погасив при проблемах — без всякой пересборки.
И главный подводный камень всех стратегий: откат кода не откатывает базу данных. Если миграция удалила колонку, старая версия приложения после отката просто не заработает. Отсюда практика expand-contract: сначала расширяем схему обратно совместимо (добавили колонку, пишем в обе), выкатываем код, убеждаемся, что всё хорошо, и только следующим релизом удаляем старое. Каждая миграция при этом должна пережить одновременную работу двух версий приложения.
Типичные ошибки кандидатов
- Называют стратегии списком, но не могут объяснить, чем платят за каждую.
- Путают blue-green и canary: в первом трафик переключается целиком, во втором — долями.
- Забывают про удвоение ресурсов при blue-green.
- Предлагают canary там, где нет метрик и наблюдаемости — стратегия превращается в имитацию.
- Не упоминают миграции базы данных, хотя именно они чаще всего срывают откат.
- Не различают деплой и релиз, из-за чего любая правка требует полного цикла выкатки.
Как ответить кратко (20–30 секунд)
«Recreate — с простоем, для внутренних сервисов, где это допустимо. Rolling update — стандарт в Kubernetes: без простоя, но какое-то время работают две версии сразу и откат небыстрый. Blue-green — полная копия окружения и мгновенное переключение трафика, откат за секунды, но нужен двойной запас мощности. Canary — новая версия получает 1–5% трафика, метрики сравниваются автоматически, и при ухудшении идёт автооткат; для платёжного сервиса выберу именно её, потому что радиус поражения минимален. Для админки хватит rolling или recreate. И в любой стратегии помню, что откат кода не откатывает миграции — схему меняю по принципу expand-contract.»