Deployment и ReplicaSet
| Тип | объекты API Kubernetes (apps/v1) |
|---|---|
| Назначение | stateless-приложения с N одинаковыми репликами |
| Стратегии обновления | RollingUpdate (по умолчанию), Recreate |
| Параметры обновления | maxSurge, maxUnavailable (по умолчанию 25%) |
| История ревизий | revisionHistoryLimit (по умолчанию 10) |
| Предшественник | ReplicationController |
| Альтернативы | StatefulSet, DaemonSet, Job |
Deployment и ReplicaSet — объекты Kubernetes, которые отвечают за работу приложений без собственного состояния (stateless): веб-серверов, API, воркеров очередей. ReplicaSet гарантирует, что в кластере всегда запущено заданное число одинаковых подов. Deployment стоит уровнем выше: он создаёт ReplicaSet'ы и переключается между ними при обновлении версии, обеспечивая плавное обновление без простоя и откат.[1] На практике пишут именно Deployment, а ReplicaSet почти никогда не создают вручную.
Принцип контроллера
Kubernetes построен на цикле согласования (reconciliation loop): пользователь описывает желаемое состояние, а контроллер постоянно сравнивает его с фактическим и устраняет расхождения.[3] Контроллер ReplicaSet считает поды, подходящие под его селектор меток, и если их меньше, чем replicas, создаёт новые по шаблону, а если больше — удаляет лишние.[2] Поэтому упавший узел или удалённый вручную под не нарушают работу: замена появится через несколько секунд на другом узле.
Связь между объектами держится на метках (labels) и селекторах.[4] Цепочка такая: Deployment → ReplicaSet (по одному на каждую версию шаблона) → Pod'ы.
Пример
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # сколько подов сверх replicas можно создать
maxUnavailable: 0 # сколько может отсутствовать во время обновления
template:
metadata:
labels:
app: web
spec:
containers:
- name: app
image: ghcr.io/example/web:1.4.0
ports:
- containerPort: 8000
readinessProbe:
httpGet: {path: /healthz, port: 8000}
Секция template — это шаблон пода. Селектор matchLabels должен совпадать с метками шаблона и после создания не меняется.
Плавное обновление
Любое изменение шаблона пода (новый образ, переменная окружения, ресурсы) запускает выкатку (rollout). Deployment создаёт новый ReplicaSet и постепенно увеличивает его, одновременно уменьшая старый:
- Создаётся новый под (в пределах
maxSurge). - Когда он проходит
readinessProbe, удаляется один старый (в пределахmaxUnavailable). - Шаги повторяются, пока все реплики не будут новыми.
Значения по умолчанию — 25% для обоих параметров. Без readiness-пробы Kubernetes считает под готовым сразу после старта и может переключить трафик на ещё не готовое приложение.
Стратегия Recreate сначала удаляет все старые поды, потом создаёт новые — с простоем, но без одновременной работы двух версий (нужно, например, при несовместимой схеме базы).
Изменение только replicas не создаёт новую ревизию — это масштабирование, а не обновление.
Откат и история
Старые ReplicaSet'ы не удаляются, а остаются с нулём реплик — по ним можно откатиться. Сколько их хранить, задаёт revisionHistoryLimit.[5]
kubectl apply -f deployment.yaml
kubectl set image deployment/web app=ghcr.io/example/web:1.5.0
kubectl rollout status deployment/web # дождаться окончания
kubectl rollout history deployment/web
kubectl rollout undo deployment/web # вернуть предыдущую ревизию
kubectl rollout restart deployment/web # перезапустить поды без изменения образа
kubectl scale deployment/web --replicas=5
kubectl get rs -l app=web # ReplicaSet'ы всех ревизий
Если выкатка застряла (поды не становятся готовыми), Deployment по истечении progressDeadlineSeconds (600 секунд) помечает её как неуспешную, но сам не откатывается — это делают вручную или средствами CI/CD.
Связанные механизмы
- Автомасштабирование (HPA) меняет
replicasавтоматически по нагрузке на CPU или пользовательским метрикам. - PodDisruptionBudget запрещает плановым операциям (обновлению узлов) одновременно снимать больше заданного числа подов.[6]
- Service выбирает поды по тем же меткам, поэтому трафик автоматически идёт на новые реплики.
- Шаблоны манифестов для разных окружений часто упаковывают в чарты Helm.
Когда нужен не Deployment
| Объект | Для чего |
|---|---|
| StatefulSet | базы данных и кластеры: стабильные имена подов (db-0, db-1) и свой том у каждого |
| DaemonSet | по одному поду на каждом узле: агенты логов и мониторинга, сетевые плагины |
| Job / CronJob | разовые и периодические задачи, которые должны завершиться |
Исторически ту же роль выполнял ReplicationController; ReplicaSet заменил его, добавив селекторы на основе множеств.