Стратегии обновления и откат
Стратегия обновления определяет, как Deployment заменяет старые поды новыми — плавно или с простоем — и насколько безопасно вы сможете откатиться.
Стратегия обновления — правило, по которому Deployment выкатывает новую версию:
RollingUpdateзаменяет поды постепенно без простоя,Recreateсначала гасит все старые, потом поднимает новые.
Базовый Deployment вы уже умеете создавать и обновлять. Этот урок — про контроль над обновлением: как идёт замена подов, сколько лишних поднимается и сколько можно временно потерять, как откатиться на прошлую версию одной командой и как концептуально устроены blue-green и canary. Это та часть, которая отделяет «выкатил и надеюсь» от предсказуемого релиза без простоя.
RollingUpdate против Recreate
У Deployment две встроенные стратегии. RollingUpdate (по умолчанию) заменяет поды порциями: поднимает несколько новых, дожидается их готовности, гасит столько же старых — и так, пока вся выкатка не завершится. В каждый момент часть подов обслуживает трафик, поэтому простоя нет.
Recreate действует резко: сначала удаляет все старые поды, и лишь затем создаёт новые. Между этими шагами приложение недоступно. Это допустимо там, где две версии не могут работать одновременно — например, при несовместимой миграции схемы БД или при эксклюзивном захвате ресурса.
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 4
strategy:
type: Recreate # все старые поды гасятся до создания новых
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: web:2.0
maxSurge и maxUnavailable
Поведение RollingUpdate тонко настраивается двумя параметрами. Они задаются числом подов или процентом от replicas:
| Параметр | Смысл | По умолчанию |
maxSurge | Сколько подов сверх желаемого числа можно поднять во время выкатки | 25% |
maxUnavailable | Сколько подов из желаемого числа можно временно держать недоступными | 25% |
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # не более чем на 1 под больше нормы
maxUnavailable: 0 # ни одного пода не теряем во время выкатки
Комбинация maxUnavailable: 0 и maxSurge: 1 даёт самый бережный режим: Kubernetes сначала поднимает один лишний новый под, дожидается его готовности и только потом гасит один старый — мощность сервиса не проседает ни на секунду. Обратная крайность, maxUnavailable: 1, maxSurge: 0, обновляет «впритык», не превышая лимит подов, но временно теряя часть мощности. Выбор — это компромисс между запасом ресурсов и гарантированной ёмкостью во время релиза.
# Запустить обновление, сменив образ
kubectl set image deployment/web web=web:2.0
# Следить за ходом выкатки в реальном времени
kubectl rollout status deployment/web
Откат: rollout undo
Deployment хранит историю ревизий, поэтому неудачный релиз откатывается одной командой — это главная страховка при выкатке.
# Посмотреть историю ревизий
kubectl rollout history deployment/web
# Откатиться на предыдущую ревизию
kubectl rollout undo deployment/web
# Откатиться на конкретную ревизию
kubectl rollout undo deployment/web --to-revision=3
# Аварийно остановить и возобновить выкатку
kubectl rollout pause deployment/web
kubectl rollout resume deployment/web
Откат — это, по сути, та же выкатка, только к прошлому шаблону пода: Kubernetes возвращает предыдущий ReplicaSet и плавно переводит трафик на него по той же стратегии RollingUpdate. Глубину истории задаёт поле revisionHistoryLimit (по умолчанию 10 хранимых ReplicaSet).
Blue-green и canary концептуально
RollingUpdate и Recreate — встроенные стратегии. Blue-green и canary — это паттерны поверх Kubernetes: их собирают из нескольких Deployment и управления трафиком (через Service, Ingress или service mesh), а в проде обычно автоматизируют инструментами вроде Argo Rollouts или Flagger.
Blue-green
Поднимаются две полные среды: blue (текущая версия) и green (новая). Трафик идёт на blue. Когда green развёрнута и проверена, переключают Service с blue на green одним движением — мгновенный «перевод стрелки». Если что-то не так, так же мгновенно возвращаются на blue. Плюс — нулевой простой и быстрый откат; минус — нужно вдвое больше ресурсов, ведь обе среды работают одновременно.
Canary
Новая версия выкатывается постепенно: сначала на неё направляют, скажем, 5% трафика, наблюдают метрики (ошибки, задержки), затем поднимают долю до 25%, 50% и, если всё хорошо, до 100%. Так проблему ловят на малой части пользователей. Простейший canary имитируется и «голым» Kubernetes: рядом с основным Deployment поднимают второй, с новым образом и малым числом реплик, под тем же Service — и доля трафика на новую версию определяется соотношением подов. Точное процентное управление дают service mesh и специализированные контроллеры.
Как это работает под капотом
За кулисами Deployment управляет несколькими ReplicaSet. При обновлении создаётся новый ReplicaSet с новым шаблоном пода; контроллер постепенно увеличивает в нём число реплик и одновременно уменьшает их в старом, соблюдая maxSurge и maxUnavailable. Старые ReplicaSet не удаляются, а остаются с нулём реплик — именно они и образуют историю ревизий. Поэтому rollout undo работает мгновенно: контроллеру достаточно снова «надуть» прежний ReplicaSet и сдуть текущий.
Готовность новых подов определяют пробы (readinessProbe): пока под не прошёл readiness, он не считается доступным и выкатка не двигается дальше. Поэтому без корректных проб RollingUpdate может «считать» сырые поды рабочими и отправлять на них трафик раньше времени — пробы напрямую влияют на безопасность обновления.
Частые ошибки
- maxUnavailable и maxSurge одновременно в нуле. Так выкатка не сдвинется: нельзя ни поднять лишний под, ни погасить существующий. Хотя бы один параметр должен допускать движение.
- RollingUpdate при несовместимых версиях. Если новая и старая версии не могут сосуществовать (несовместимая схема БД, общий эксклюзивный ресурс), параллельная работа во время выкатки сломает приложение — здесь нужен
Recreateили blue-green. - Нет readiness-проб. Без них Kubernetes считает поды готовыми сразу после старта и переводит трафик на ещё не прогретое приложение — пользователи ловят ошибки прямо во время релиза.
- Расчёт на бесконечную историю откатов. Глубина ограничена
revisionHistoryLimit; слишком старую ревизию откатить уже не выйдет. - Путаница maxSurge и maxUnavailable.
maxSurge— про поды сверх нормы,maxUnavailable— про допустимую нехватку. Перепутав их, легко получить не тот профиль доступности.
Итоги
RollingUpdateзаменяет поды постепенно без простоя;Recreateгасит все старые до создания новых, с коротким простоем.maxSurge— сколько подов можно поднять сверх нормы,maxUnavailable— сколько можно временно потерять; вместе они задают профиль безопасности выкатки.kubectl rollout undoмгновенно откатывает релиз, возвращая предыдущий ReplicaSet;rollout status/history/pause/resumeуправляют выкаткой.- Blue-green переключает трафик между двумя полными средами; canary постепенно наращивает долю трафика на новую версию.
- Корректные readiness-пробы критичны: от них зависит, безопасно ли идёт обновление.