Deployments против StatefulSets в Kubernetes: практическое руководство по выбору контроллера (2026) | AdminWiki

Deployments против StatefulSets в Kubernetes: практическое руководство по выбору контроллера (2026)

25 августа 2026 9 мин. чтения

Введение: зачем нужны контроллеры в Kubernetes

Контроллеры в Kubernetes управляют жизненным циклом подов. Они следят за текущим состоянием кластера и приводят его к желаемому, описанному в YAML-манифесте. Если под падает, контроллер пересоздаёт его. Если нужно больше реплик, контроллер добавляет их. Без контроллеров поды были бы просто запущенными контейнерами без самовосстановления и масштабирования.

Deployment и StatefulSet - два основных контроллера для долгоживущих сервисов. Deployment создан для stateless-приложений, где поды взаимозаменяемы. StatefulSet решает задачи stateful-приложений, которым нужны стабильные идентификаторы, постоянное хранилище и упорядоченное развертывание. Выбор между ними определяет архитектуру вашего сервиса, поведение при обновлениях и сохранность данных.

Эта статья даёт практический алгоритм выбора. Вы получите критерии, примеры манифестов и таблицы сравнения, чтобы принимать решение за минуты, а не часы.

Ключевые различия между Deployment и StatefulSet

Главное различие - в отношении к идентичности пода. Deployment считает поды взаимозаменяемыми единицами. StatefulSet присваивает каждому поду уникальный, предсказуемый идентификатор, который сохраняется при перезапусках и пересозданиях. Это различие пронизывает все аспекты: порядок развертывания, работу с хранилищем и сетевые имена.

Идентичность подов: одинаковые против уникальных

Deployment создаёт поды с случайными суффиксами, например nginx-deployment-7d8c6f9b4c-abcde. Имя генерируется хешем от шаблона пода и ReplicaSet. При пересоздании пода имя меняется. Поды не хранят состояние: если один упал, другой с тем же шаблоном заменит его без потери функциональности.

StatefulSet создаёт поды с предсказуемыми именами: web-0, web-1, web-2. Порядковый номер (ordinal) присваивается при создании и сохраняется. Если под web-1 упадёт, StatefulSet создаст новый под с тем же именем web-1. Идентичность сохраняется, что критично для кластеров, где узлы знают друг друга по именам.

Порядок развертывания и обновления

Deployment создаёт и обновляет поды параллельно. При rolling update новые реплики запускаются одновременно, старые удаляются по мере готовности. Порядок не гарантирован: под с индексом 5 может обновиться раньше пода с индексом 1.

StatefulSet действует последовательно. Поды создаются по порядку: web-0 должен стать Ready, прежде чем запустится web-1. При удалении порядок обратный: сначала удаляется под с наибольшим номером. Обновление также идёт по одному поду за раз, от большего номера к меньшему. Это защищает кластеры от одновременного выхода из строя нескольких узлов.

Управление хранилищем: общее против выделенного

Deployment использует один PersistentVolumeClaim (PVC) на все реплики или пустое хранилище emptyDir. Все поды читают и пишут в одно место. При удалении пода данные в emptyDir теряются. Общий PVC создаёт конкуренцию за доступ и не подходит для приложений, которым нужна изоляция данных.

StatefulSet использует volumeClaimTemplates. Для каждого пода автоматически создаётся отдельный PVC. Под web-0 получает свой диск, под web-1 - свой. При пересоздании пода PVC сохраняется, данные не теряются. Это ключевое преимущество для баз данных и распределённых систем.

Сетевые идентификаторы: стабильные DNS-имена

Deployment работает через Service с балансировкой нагрузки. Поды доступны по общему IP сервиса, но IP конкретного пода меняется при пересоздании. Для связи между подами это неудобно: клиент не знает, к какому именно поду он обращается.

StatefulSet требует headless service (сервис с clusterIP: None). Каждый под получает стабильное DNS-имя вида web-0.nginx.default.svc.cluster.local. Другие поды могут обращаться к конкретному узлу кластера по имени, что необходимо для репликации и выборов лидера.

ПараметрDeploymentStatefulSet
Идентичность подовСлучайные имена, взаимозаменяемыПредсказуемые имена (web-0, web-1), уникальны
Порядок развертыванияПараллельныйПоследовательный (0, 1, 2...)
Порядок удаленияПараллельныйОбратный (N-1, N-2...)
ХранилищеОбщий PVC или emptyDirОтдельный PVC на каждый под через volumeClaimTemplates
Сетевые именаОбщий IP сервисаСтабильное DNS-имя каждого пода через headless service
ОбновлениеRolling update с maxSurge/maxUnavailableПоследовательное, с partition или onDelete

Когда использовать Deployment: сценарии для stateless-приложений

Deployment - выбор по умолчанию для большинства сервисов. Если приложение не хранит локальное состояние, которое нужно сохранять между перезапусками, используйте Deployment. Признаки stateless-приложения: горизонтальное масштабирование простым добавлением реплик, отсутствие жёсткой привязки к конкретному поду, быстрые обновления без координации между экземплярами.

Типичные примеры: веб-серверы (Nginx, Apache), REST API, микросервисы без локального кэша, обработчики очередей без сохранения прогресса. Если под упал, новый под с тем же образом и конфигурацией полностью заменит его. Нет необходимости сохранять идентичность или данные.

Deployment также проще в эксплуатации. Масштабирование выполняется одной командой kubectl scale deployment nginx --replicas=10. Откат - kubectl rollout undo deployment nginx. Для команд, которые ценят скорость и простоту, Deployment снижает операционную нагрузку.

Пример манифеста Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80

Поле replicas задаёт количество подов. selector связывает Deployment с подами по метке app: nginx. template описывает под: контейнер nginx с портом 80. При масштабировании Deployment просто добавляет или удаляет одинаковые поды.

Когда использовать StatefulSet: сценарии для stateful-приложений

StatefulSet нужен, когда приложение требует хотя бы одного из трёх условий: стабильные сетевые идентификаторы, постоянное хранилище на каждый под, упорядоченное развертывание и удаление. Если ваше приложение - кластер, где узлы общаются друг с другом по именам и хранят свои данные локально, выбирайте StatefulSet.

Типичные примеры: базы данных (MySQL, PostgreSQL), распределённые системы (Kafka, Elasticsearch, ZooKeeper), хранилища данных (Cassandra, MongoDB с репликацией). Эти приложения требуют, чтобы каждый узел имел стабильное имя и собственный диск. Пересоздание пода без сохранения данных привело бы к потере части кластера.

StatefulSet сложнее в управлении, чем Deployment. Удаление StatefulSet не удаляет PVC, чтобы защитить данные. Обновление требует учёта порядка и возможных блокировок. Но для stateful-приложений эта сложность оправдана: она предотвращает потерю данных и рассинхронизацию кластера.

Пример манифеста StatefulSet

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql-headless
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        ports:
        - containerPort: 3306
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 10Gi

Поле serviceName указывает на headless service, который обеспечивает стабильные DNS-имена. volumeClaimTemplates создаёт отдельный PVC на каждый под. Под mysql-0 получит PVC data-mysql-0, под mysql-1 - data-mysql-1, и так далее. При пересоздании пода PVC остаётся, данные сохраняются.

Масштабирование и обновления: особенности каждого контроллера

Масштабирование Deployment - простая операция. Увеличьте replicas, и контроллер добавит поды параллельно. Уменьшите - удалит лишние. Нет ограничений на порядок: все поды одинаковы, любой может быть удалён.

Масштабирование StatefulSet идёт по порядку. При увеличении с 2 до 4 реплик сначала создаётся web-2, после его готовности - web-3. При уменьшении с 4 до 2 сначала удаляется web-3, затем web-2. Это гарантирует, что кластер не потеряет кворум при масштабировании.

Стратегии обновления Deployment

Deployment поддерживает две стратегии: RollingUpdate и Recreate. RollingUpdate - стратегия по умолчанию. Она постепенно заменяет старые поды новыми. Параметры maxSurge и maxUnavailable контролируют процесс. maxSurge: 1 разрешает создать на один под больше желаемого количества. maxUnavailable: 0 запрещает уменьшать количество доступных подов во время обновления. Это обеспечивает нулевой простой.

Recreate удаляет все старые поды перед созданием новых. Это вызывает простой, но подходит для приложений, которые не могут работать в двух версиях одновременно.

Стратегии обновления StatefulSet

StatefulSet поддерживает RollingUpdate и OnDelete. RollingUpdate обновляет поды по одному, в обратном порядке: сначала web-2, затем web-1, затем web-0. Параметр partition позволяет канареечное обновление. Если partition: 2, обновятся только поды с порядковым номером больше или равным 2. Поды web-0 и web-1 останутся на старой версии. Это полезно для тестирования новой версии на части кластера.

OnDelete даёт полный ручной контроль. StatefulSet не обновляет поды автоматически. Вы удаляете под вручную, и контроллер создаёт новый с обновлённым шаблоном. Это подходит для кластеров, где обновление требует ручной координации, например, для пересборки индексов Elasticsearch.

Сетевые идентификаторы и обнаружение сервисов

StatefulSet требует headless service для работы. Headless service - это Service с clusterIP: None. Он не балансирует нагрузку, а создаёт DNS-записи для каждого пода. Формат имени: <имя-пода>.<имя-сервиса>.<namespace>.svc.cluster.local. Для пода web-0 в сервисе nginx в namespace default полное имя будет web-0.nginx.default.svc.cluster.local.

Эти стабильные имена критичны для кластеров. Kafka использует их для bootstrap: клиенты подключаются к конкретным брокерам по именам. ZooKeeper использует их для выборов лидера: каждый узел должен знать адреса остальных. Без стабильных имён кластер не сможет пережить пересоздание подов.

Headless Service для StatefulSet

apiVersion: v1
kind: Service
metadata:
  name: mysql-headless
spec:
  clusterIP: None
  selector:
    app: mysql
  ports:
  - port: 3306
    targetPort: 3306

Поле clusterIP: None делает сервис headless. selector связывает его с подами StatefulSet. Теперь каждый под доступен по своему DNS-имени, а не через общий IP.

Управление хранилищем: PVC и volumeClaimTemplates

volumeClaimTemplates - ключевой механизм StatefulSet для автоматизации хранилища. Вы описываете шаблон PVC один раз, и контроллер создаёт отдельный PVC для каждого пода. Это избавляет от ручного создания PVC и привязки их к конкретным подам.

Каждый PVC получает имя по шаблону <имя-тома>-<имя-пода>. Для StatefulSet mysql с томом data под mysql-0 получит PVC data-mysql-0. Под mysql-1 - data-mysql-1. Привязка PVC к поду сохраняется при пересоздании пода.

Жизненный цикл PVC в StatefulSet

PVC, созданные через volumeClaimTemplates, не удаляются при удалении StatefulSet. Это защищает данные от случайной потери. Если вы удалите StatefulSet и создадите его заново с тем же именем, новые поды подключатся к существующим PVC. Данные сохранятся.

Чтобы удалить данные, нужно удалить PVC вручную: kubectl delete pvc data-mysql-0. Перед удалением StatefulSet рекомендуется сделать резервную копию данных. Для критичных систем настройте автоматическое резервное копирование через CronJob или внешние инструменты.

Практические рекомендации: как выбрать контроллер

Выбор сводится к трём вопросам. Нужно ли приложению стабильное сетевое имя для каждого экземпляра? Нужно ли постоянное хранилище на каждый под? Важен ли порядок развертывания и удаления? Если хотя бы на один вопрос ответ «да», используйте StatefulSet. Если все ответы «нет», выбирайте Deployment.

Для веб-серверов, API и микросервисов без локального состояния Deployment - правильный выбор. Он проще, быстрее масштабируется и легче обновляется. Для баз данных, очередей сообщений и распределённых систем StatefulSet обязателен. Попытка запустить PostgreSQL в Deployment приведёт к потере данных при пересоздании пода.

Существуют гибридные случаи. Приложение может быть в основном stateless, но хранить кэш, который можно пересоздать. В таком случае Deployment с общим PVC или emptyDir может быть достаточно. Но если кэш критичен для производительности и его потеря вызывает деградацию, рассмотрите StatefulSet.

Чек-лист для принятия решения

  • Нужно ли приложению стабильное DNS-имя для каждого экземпляра? Если да - StatefulSet.
  • Нужно ли постоянное хранилище на каждый под, которое сохраняется при пересоздании? Если да - StatefulSet.
  • Важен ли порядок запуска и остановки подов? Если да - StatefulSet.
  • Приложение не хранит состояние и может масштабироваться горизонтально? Если да - Deployment.
  • Обновления должны быть быстрыми и параллельными? Если да - Deployment.
  • Приложение - база данных, очередь сообщений или распределённая система? Если да - StatefulSet.

Для более широкого сравнения контроллеров Kubernetes, включая DaemonSet и Job, изучите практическое сравнение контроллеров. Если нужно глубже понять архитектуру control loop, обратитесь к руководству по архитектуре контроллеров.

Заключение

Deployment и StatefulSet решают разные задачи. Deployment управляет stateless-приложениями, где поды взаимозаменяемы и не хранят состояние. StatefulSet управляет stateful-приложениями, которым нужны стабильные идентификаторы, постоянное хранилище и упорядоченное развертывание. Ошибка в выборе контроллера приводит к потере данных или нестабильной работе кластера.

Используйте чек-лист из предыдущего раздела для быстрой оценки. Если приложение не требует уникальной идентичности и постоянного хранилища, начинайте с Deployment. Если требует - проектируйте StatefulSet с headless service и volumeClaimTemplates. Для деталей по конкретным сценариям изучите руководство по StatefulSet с примерами для PostgreSQL и MySQL и полное руководство по Deployment.

Поделиться:
Сохранить гайд? В закладки браузера