Why Deployments Aren't Enough for State
A Deployment treats its Pods as interchangeable: any replica can be killed and replaced by an identical one with a random name and no guaranteed identity. Stateful systems like PostgreSQL replicas, Kafka brokers, or Elasticsearch nodes need stable network identity (so peers can find them reliably at the same address after a restart), stable storage (each replica must reattach to its own specific disk, not a random one), and ordered, predictable deployment and scaling (a replica set's primary should come up before replicas start syncing). The StatefulSet controller was built specifically to provide these three guarantees.
Cricket analogy: A Deployment is like fielders being randomly repositioned on the field with no consistent role, while a StatefulSet is like a batting order where each player has a fixed position and comes in at exactly their number.
Stable Identity via Headless Services and Ordinal Names
A StatefulSet named 'kafka' with 3 replicas produces Pods named kafka-0, kafka-1, kafka-2 — never random suffixes — and each keeps that exact name across restarts and rescheduling. Paired with a headless Service (clusterIP: None), each Pod also gets a stable DNS name like kafka-0.kafka.default.svc.cluster.local, letting peers address a specific replica directly rather than load-balancing across the set, which is essential for protocols like Kafka's controller election or PostgreSQL's replication that need to talk to a specific node.
Cricket analogy: This is like a scorecard listing 'Player 1, Player 2, Player 3' by fixed batting position rather than jersey numbers being reshuffled each innings — commentators can always refer to 'number 3' reliably.
volumeClaimTemplates and Ordered Rollouts
Instead of a single shared PVC, a StatefulSet's volumeClaimTemplates field causes the controller to create one dedicated PVC per replica, named like data-kafka-0, data-kafka-1, following the same ordinal pattern as the Pods. When kafka-1 is rescheduled to a different node, it reattaches to data-kafka-1 specifically, never another replica's disk. By default, StatefulSets also scale and update in strict ordinal order (0, then 1, then 2) with each Pod required to become Ready before the next starts, though podManagementPolicy: Parallel can relax this when ordering isn't required, and updateStrategy: RollingUpdate with a partition value allows careful canary-style upgrades of just the highest-numbered replicas first.
Cricket analogy: This is like each specialist fielder having their own designated fielding kit bag — mid-on's bag never gets swapped with slip's bag — even when players rotate positions between overs.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: kafka
spec:
serviceName: kafka
replicas: 3
podManagementPolicy: OrderedReady
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0
selector:
matchLabels:
app: kafka
template:
metadata:
labels:
app: kafka
spec:
containers:
- name: kafka
image: confluentinc/cp-kafka:7.6.0
ports:
- containerPort: 9092
volumeMounts:
- name: data
mountPath: /var/lib/kafka/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: fast-ssd
resources:
requests:
storage: 100Gi
---
apiVersion: v1
kind: Service
metadata:
name: kafka
spec:
clusterIP: None
selector:
app: kafka
ports:
- port: 9092Deleting a StatefulSet does NOT delete its volumeClaimTemplates-generated PVCs by default — this is intentional, protecting stateful data from accidental deletion, but it means you must manually clean up orphaned PVCs like data-kafka-0 if you truly want to remove all traces of a decommissioned StatefulSet.
- StatefulSets give Pods stable, predictable names (name-0, name-1, ...) unlike Deployments' random suffixes.
- A headless Service (clusterIP: None) gives each Pod a stable, individually addressable DNS name.
- volumeClaimTemplates create one dedicated PVC per replica, reattached consistently on reschedule.
- Default OrderedReady policy scales and updates Pods strictly in order, waiting for Ready between steps.
- podManagementPolicy: Parallel relaxes ordering when it's not required by the workload.
- updateStrategy partition values enable canary-style partial rolling updates.
- StatefulSet deletion does not cascade-delete its PVCs, protecting stateful data by default.
Practice what you learned
1. What is the primary reason StatefulSets are used instead of Deployments for databases?
2. What kind of Service is typically paired with a StatefulSet to provide per-Pod DNS names?
3. What does volumeClaimTemplates achieve in a StatefulSet spec?
4. What happens to PVCs created via volumeClaimTemplates when the StatefulSet is deleted?
Was this page helpful?
You May Also Like
Persistent Volumes and Claims
Learn how Kubernetes decouples storage provisioning from storage consumption using PersistentVolume and PersistentVolumeClaim objects.
Storage Classes
Understand how StorageClass objects define provisioners, parameters, and policies that govern how storage is dynamically created in Kubernetes.
Volume Snapshots
Learn how the Kubernetes VolumeSnapshot API enables point-in-time backups and cloning of PersistentVolumes via the CSI snapshot controller.