How to run stateful workloads with a Kubernetes StatefulSet
StatefulSets give pods stable names, stable DNS, and per-pod persistent volumes via volumeClaimTemplates and a headless Service. Pods scale and update in order, preserving each pod's storage.
Stateful workloads with StatefulSets
A StatefulSet manages pods that need stable identities and durable storage, such as databases and clustered systems. Unlike a Deployment, each pod gets a stable name (app-0, app-1), a stable DNS record, and its own persistent volume that survives rescheduling.
Prerequisites
- A StorageClass that can dynamically provision volumes.
- Familiarity with Deployments and Services.
Steps
1. Create a headless Service
A headless Service (no cluster IP) gives each pod a stable DNS name:
apiVersion: v1
kind: Service
metadata:
name: db
spec:
clusterIP: None
selector:
app: db
ports:
- port: 5432
2. Define the StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: db
spec:
serviceName: db
replicas: 3
selector:
matchLabels:
app: db
template:
metadata:
labels:
app: db
spec:
containers:
- name: postgres
image: postgres:16
ports:
- containerPort: 5432
3. Add volumeClaimTemplates
Each pod gets its own PersistentVolumeClaim:
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
Mount it in the container at the data directory.
4. Verify stable identities
kubectl get pods -l app=db
kubectl get pvc
Pods are created in order and named db-0, db-1, db-2, each addressable at db-0.db.
5. Scale the StatefulSet
kubectl scale statefulset db --replicas=5
Pods scale up in order and down in reverse order, preserving each pod's volume.
6. Update with rolling strategy
The default RollingUpdate strategy replaces pods from the highest ordinal down. Use partition to stage updates across replicas.
Verification
Confirm each pod has its own PVC with kubectl get pvc. Write data to db-0, delete the pod, and confirm it reschedules with the same name and reattaches its volume so the data remains. Resolve db-0.db from another pod to confirm stable DNS.
Next Steps
For production databases, prefer a purpose-built operator that handles failover, backups, and replication. Add PodDisruptionBudgets and anti-affinity rules so replicas spread across nodes.
Prerequisites
- A cluster with a default StorageClass
- Understanding of Deployments
- kubectl access
Steps
- 1Create a headless Service
- 2Define the StatefulSet
- 3Add volumeClaimTemplates
- 4Verify stable identities
- 5Scale the StatefulSet
- 6Update with rolling strategy