Deployment и ReplicaSet
Что нужно знать перед уроком
- M1.01 — Pod и контейнеры — нужно понимать Pod, restartPolicy, requests/limits
Что нужно знать перед уроком
M1 урок 1 — что такое Pod, фазы и состояния, graceful shutdown. Здесь мы разбираем, кто и как поддерживает нужное количество Pod’ов и управляет их обновлением.
Теория
Зачем нужен ReplicaSet, если есть Pod
Если создать Pod напрямую (как в прошлом уроке) и он упадёт (узел отказал, процесс убит OOM Killer’ом) — Kubernetes не создаст его заново. Голый Pod — это одноразовый объект без самовосстановления. Чтобы гарантировать «у меня всегда N работающих копий этого контейнера», нужен контроллер, который:
- Непрерывно сверяет фактическое число Pod’ов, подходящих под
selector, с желаемымreplicas; - При недостатке — создаёт новые Pod’ы по шаблону (
template); - При избытке — удаляет лишние.
Это и есть ReplicaSet. Но ReplicaSet сам по себе не умеет декларативно обновлять версию приложения (поменять образ) без даунтайма — для этого нужен ещё один уровень.
Зачем нужен Deployment поверх ReplicaSet
Deployment — контроллер, управляющий ReplicaSet’ами. При изменении template (например, новый тег образа) Deployment не редактирует старый ReplicaSet «на месте», а создаёт новый ReplicaSet с обновлённым шаблоном и постепенно переключает трафик со старого на новый по стратегии обновления. Это даёт: историю ревизий (можно откатиться), нулевой (или контролируемый) даунтайм при обновлении, и явную декларативность («хочу версию v2» вместо императивных шагов).
Иммутабельность spec.selector
Частая ошибка новичков: попытка поменять spec.selector.matchLabels у уже существующего Deployment. Kubernetes запрещает это на уровне API-валидации — selector иммутабелен после создания. Причина — селектор однозначно определяет, какие Pod’ы «принадлежат» этому Deployment (через созданные им ReplicaSet’ы); если бы селектор можно было менять на лету, Deployment мог бы внезапно «потерять» или «захватить чужие» Pod’ы. Если действительно нужно поменять лейблы, определяющие принадлежность, — единственный путь — пересоздать Deployment целиком (удалить и создать новый с новым selector), явно продумав, как это повлияет на доступность.
RollingUpdate: maxUnavailable/maxSurge
Стратегия обновления по умолчанию — RollingUpdate (альтернатива — Recreate, убивает все старые Pod’ы перед созданием новых — используется редко, когда старая и новая версия не могут работать одновременно). У RollingUpdate два параметра, оба — абсолютное число или процент от replicas:
maxUnavailable(по умолчанию25%) — сколько Pod’ов может быть недоступно относительно желаемого числа реплик в процессе обновления;maxSurge(по умолчанию25%) — сколько «лишних» Pod’ов сверхreplicasможет быть создано одновременно.
| |
Жёсткое правило API: maxUnavailable не может быть 0, если maxSurge тоже 0 — иначе обновление физически не сможет продвинуться (нельзя ни создать новый Pod сверх лимита, ни временно уменьшить число доступных).
Чтение kubectl describe deployment
| |
Видно буквально то, что показано на диаграмме выше: новый ReplicaSet «надувается» шаг за шагом, старый — «сдувается», в пределах maxSurge/maxUnavailable на каждом шаге.
revisionHistoryLimit и откат
Deployment хранит историю старых ReplicaSet’ов (по умолчанию 10 последних, настраивается revisionHistoryLimit) именно для возможности откатиться:
| |
Частые ошибки и подводные камни
- Попытка изменить
spec.selectorу существующего Deployment — API вернёт ошибку валидации. Единственный путь — пересоздание объекта. maxUnavailable: 0иmaxSurge: 0одновременно — невалидная конфигурация, обновление зависнет/будет отклонено.- Не следить за
revisionHistoryLimit— если поставить0, откатkubectl rollout undoстанет невозможен (нет сохранённой истории). - Путать масштабирование (
kubectl scale) с обновлением версии — масштабирование меняетreplicasу того же ReplicaSet, обновление версии создаёт новый.
Linux / Сети / Docker
RollingUpdate — это причина, по которой ваше приложение обязано штатно обрабатывать одновременную работу двух версий (старой и новой) в течение всего периода обновления: в момент rollout часть трафика идёт на старые Pod’ы, часть — на новые. Если версии несовместимы по схеме БД или формату API между собой — RollingUpdate приведёт к ошибкам у части пользователей. Это первое соприкосновение с темой обратной совместимости при деплое, к которой мы вернёмся в M6 уроке 4 (миграции БД перед деплоем новой версии).
Практика в кластере
Homer — статический дашборд-стартовая страница (чистый HTML/JS/YAML-конфиг), чуть сложнее Excalidraw за счёт конфигурации через volume — но volumes мы разберём подробно в уроке 6, здесь используем emptyDir для затравки, не углубляясь.
- Создайте Deployment:
| |
- Проверьте ReplicaSet, созданный Deployment’ом, и его связь через
ownerReferences:
| |
- Обновите версию образа и наблюдайте RollingUpdate в реальном времени:
| |
- Откатите обновление и убедитесь, что версия вернулась:
| |
- Попробуйте (и получите закономерную ошибку) изменить
selector:
| |
Практика разработки
Образ b4bz/homer — готовый, собственной сборки в этом уроке нет; первая сборка своими руками — в M3.
Шпаргалка команд урока
| |
Вопросы для самопроверки
Новый ReplicaSet на каждое изменение template — основа механизма ревизий и откатов Deployment.
Источник: Kubernetes — deployment
selector Deployment иммутабелен — единственный способ поменять принадлежность Pod'ов по лейблам — пересоздание объекта.
Источник: Kubernetes — deployment
Одновременный ноль у обоих параметров не позволяет обновлению продвигаться: нельзя ни создать Pod сверх лимита, ни временно снизить доступность.
Источник: Kubernetes — deployment
revisionHistoryLimit определяет, сколько старых ReplicaSet'ов (ревизий) хранится для возможного отката.
Источник: Kubernetes — deployment
Масштабирование не меняет template Pod'а и работает в рамках текущего ReplicaSet; изменение образа меняет template, что запускает создание нового ReplicaSet.
Источник: Kubernetes — deployment
Рекомендуемая литература
Официальная документация
Статьи и блоги
- Kubernetes для начинающих: что такое Pod и как с ним работать — Flant на Habr.
- Основные концепции сетевой архитектуры Kubernetes — Habr.
- Миграция с ingress-nginx: выбор нового контроллера — Habr.
Книги
- Marko Lukša. Kubernetes in Action. 2nd ed., 2022. ISBN 978-1617297618.
- Kelsey Hightower, Brendan Burns, Joe Beda. Kubernetes: Up and Running. 3rd ed., 2022. ISBN 978-1098110201.
- Michael Hausenblas, Stefan Schimanski. Programming Kubernetes. 2019. ISBN 978-1492047107.
Связанные материалы
- Предыдущий урок: M1.01 — Pod и контейнеры.
- Следующий урок: M1.03 — Service и порты.
- Глоссарий: Deployment.
✓ Урок пройден — все вопросы самопроверки отвечены верно