Deployment и ReplicaSet

Материал из llmdocs — справочник разработчика
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 и постепенно увеличивает его, одновременно уменьшая старый:

  1. Создаётся новый под (в пределах maxSurge).
  2. Когда он проходит readinessProbe, удаляется один старый (в пределах maxUnavailable).
  3. Шаги повторяются, пока все реплики не будут новыми.

Значения по умолчанию — 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 заменил его, добавив селекторы на основе множеств.

См. также

Источники

  1. Kubernetes Docs — Deployments
  2. Kubernetes Docs — ReplicaSet
  3. Kubernetes Docs — Controllers
  4. Kubernetes Docs — Labels and Selectors
  5. kubectl reference — rollout
  6. Kubernetes Docs — Disruptions (PodDisruptionBudget)