Что такое StatefulSet и чем он отличается от Deployment?

Что такое StatefulSet

StatefulSet — это контроллер в Kubernetes для управления набором Pod’ов, которым нужна устойчивая идентичность и/или персистентное локальное хранилище. В отличие от Deployment/ReplicaSet, где реплики взаимозаменяемы, Pod’ы в StatefulSet обладают стабильными именами, стабильными сетевыми идентификаторами и (опционально) собственными PVC, привязанными к конкретному индексу (ordinal).

Ключевые гарантии StatefulSet

  • Стабильные имена Pod: Pod получают имена в виде <statefulset-name>-<ordinal> (например web-0, web-1), и этот формат сохраняется при перезапусках/пересозданиях.

  • Стабильные сетевые идентификаторы: при использовании headless Service у каждого Pod предсказуемый DNS-имя podname.servicename.namespace.svc.cluster.local.

  • Стабильное хранилище: при volumeClaimTemplates каждому Pod создаётся свой PVC (например data-web-0), который остаётся привязанным к этому ordinal и не переиспользуется для других Pod.

  • Упорядоченные операции: по умолчанию Pod создаются, обновляются и удаляются в порядке ordinal (OrderedReady) — контроллер дождётся, пока web-0 станет Ready, прежде чем создать web-1. Есть опция Parallel для параллельного управления.

Основные параметры и поведение

  • serviceName обычно указывает на headless Service (без ClusterIP) для DNS-based discovery.

  • volumeClaimTemplates — шаблоны PVC; Kubernetes автоматически создаёт PVC для каждого Pod-индекса.

  • podManagementPolicy: OrderedReady (дефолт) или Parallel.

  • updateStrategy: RollingUpdate (по-умолчанию) или OnDelete. RollingUpdate в StatefulSet обновляет Pod’ы по одному в порядке ordinals и ждёт readiness. Есть опция partition для частичного обновления (canary-like).

Пример (упрощённо)

apiVersion: apps/v1
kind: StatefulSet
metadata: { name: web }
spec:
serviceName: "web-headless"
replicas: 3
selector:
matchLabels: { app: web }
template:
metadata: { labels: { app: web } }
spec:
containers:
\- name: nginx
image: nginx
volumeMounts:
\- name: data
mountPath: /var/www
volumeClaimTemplates:
\- metadata: { name: data }
spec:
accessModes: \["ReadWriteOnce"\]
resources: { requests: { storage: 5Gi } }

В результате для web-0 будет PVC data-web-0, для web-1 — data-web-1 и т.д.

В чём ключевые отличия от Deployment

  • Идентичность vs взаимозаменяемость: Deployment создаёт взаимозаменяемые Pod’ы (stateless), StatefulSet — POD’ы с уникальной идентичностью.

  • Стабильность хранилища: StatefulSet умеет автоматически создавать per-pod PVC через volumeClaimTemplates. Deployment обычно использует общие PVC или динамическое PV, но не создаёт уникальные PVC для каждой реплики.

  • Порядок создания/удаления/обновления: Deployment —/не гарантирует/ упорядоченности, заменяет реплики по стратегии rolling, ориентируясь на ReplicaSet; StatefulSet по умолчанию делает это последовательно (ordinal).

  • Сетевые имена и discovery: StatefulSet интегрируется с headless Service для стабильных DNS-имён; у Deployment нет встроенной стабильной сетевой идентичности для каждого пода.

  • Сценарии использования: StatefulSet — для баз данных и кластерных систем (Cassandra, Zookeeper, CockroachDB, MySQL cluster и т.п.), где важны persistent storage и фиксированные идентификаторы; Deployment — для типичных stateless-сервисов (web, api).

  • Удаление и сохранность PVC: PVC, созданные volumeClaimTemplates, обычно не удаляются автоматически при удалении StatefulSet — это сделано, чтобы не терять данные; у Deployment такого поведения по умолчанию нет, потому что обычно используются другие подходы к хранению.

  • Поддержка масштабирования: при scale up/scale down StatefulSet создаёт/удаляет Pod’ы в конце (по высшему ordinal), Deployment просто поддерживает желаемое число реплик без порядка.

Когда использовать StatefulSet

  • Нужна стабильная сеть/идентичность пода (stateful clustering).

  • Требуются отдельные per-pod persistent volumes.

  • Нужен упорядоченный старт/остановка/обновление Pod’ов.