# Deployment и ReplicaSet

> Контроллеры Kubernetes для stateless-приложений — ReplicaSet поддерживает заданное число одинаковых подов, а Deployment управляет ReplicaSet'ами и выполняет плавные обновления и откаты.

Источник: https://llmdocs.ru/wiki/deployment-replicaset/ · обновлено 2026-11-09 · лицензия CC BY-SA 4.0

- **Тип**: объекты API Kubernetes (apps/v1)
- **Назначение**: stateless-приложения с N одинаковыми репликами
- **Стратегии обновления**: RollingUpdate (по умолчанию), Recreate
- **Параметры обновления**: maxSurge, maxUnavailable (по умолчанию 25%)
- **История ревизий**: revisionHistoryLimit (по умолчанию 10)
- **Предшественник**: ReplicationController
- **Альтернативы**: StatefulSet, DaemonSet, Job
**Deployment** и **ReplicaSet** — объекты [Kubernetes](https://llmdocs.ru/wiki/kubernetes.md), которые отвечают за работу приложений без собственного состояния (*stateless*): веб-серверов, API, воркеров очередей. **ReplicaSet** гарантирует, что в кластере всегда запущено заданное число одинаковых [подов](https://llmdocs.ru/wiki/pod.md). **Deployment** стоит уровнем выше: он создаёт ReplicaSet'ы и переключается между ними при обновлении версии, обеспечивая плавное обновление без простоя и откат.[1] На практике пишут именно Deployment, а ReplicaSet почти никогда не создают вручную.

## Принцип контроллера

Kubernetes построен на **цикле согласования** (*reconciliation loop*): пользователь описывает желаемое состояние, а контроллер постоянно сравнивает его с фактическим и устраняет расхождения.[3] Контроллер ReplicaSet считает поды, подходящие под его селектор меток, и если их меньше, чем `replicas`, создаёт новые по шаблону, а если больше — удаляет лишние.[2] Поэтому упавший узел или удалённый вручную под не нарушают работу: замена появится через несколько секунд на другом узле.

Связь между объектами держится на **метках** (*labels*) и **селекторах**.[4] Цепочка такая: Deployment → ReplicaSet (по одному на каждую версию шаблона) → Pod'ы.

## Пример

```yaml
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]

```bash
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)](https://llmdocs.ru/wiki/hpa.md)** меняет `replicas` автоматически по нагрузке на CPU или пользовательским метрикам.
- **PodDisruptionBudget** запрещает плановым операциям (обновлению узлов) одновременно снимать больше заданного числа подов.[6]
- **[Service](https://llmdocs.ru/wiki/service-ingress.md)** выбирает поды по тем же меткам, поэтому трафик автоматически идёт на новые реплики.
- Шаблоны манифестов для разных окружений часто упаковывают в чарты [Helm](https://llmdocs.ru/wiki/helm.md).

## Когда нужен не Deployment

| Объект | Для чего |
|---|---|
| StatefulSet | базы данных и кластеры: стабильные имена подов (`db-0`, `db-1`) и свой [том](https://llmdocs.ru/wiki/persistentvolume.md) у каждого |
| DaemonSet | по одному поду на каждом узле: агенты логов и мониторинга, сетевые плагины |
| Job / CronJob | разовые и периодические задачи, которые должны завершиться |

Исторически ту же роль выполнял ReplicationController; ReplicaSet заменил его, добавив селекторы на основе множеств.

## См. также

- [Pod](https://llmdocs.ru/wiki/pod.md)
- [kubectl](https://llmdocs.ru/wiki/kubectl.md)
- [CI/CD](https://llmdocs.ru/wiki/ci-cd.md)
- [Kubernetes](https://llmdocs.ru/wiki/kubernetes.md)

## Источники

1. [Kubernetes Docs — Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
2. [Kubernetes Docs — ReplicaSet](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/)
3. [Kubernetes Docs — Controllers](https://kubernetes.io/docs/concepts/architecture/controller/)
4. [Kubernetes Docs — Labels and Selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/)
5. [kubectl reference — rollout](https://kubernetes.io/docs/reference/kubectl/generated/kubectl_rollout/)
6. [Kubernetes Docs — Disruptions (PodDisruptionBudget)](https://kubernetes.io/docs/concepts/workloads/pods/disruptions/)
