Skip to main content

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.

Difficulty
Advanced
Duration
45 minutes
Steps
6

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

  • 1
    Create a headless Service
  • 2
    Define the StatefulSet
  • 3
    Add volumeClaimTemplates
  • 4
    Verify stable identities
  • 5
    Scale the StatefulSet
  • 6
    Update with rolling strategy

Category

Containers