Skip to content

StatefulSets

A Deployment gives you interchangeable Pods with random names. That is exactly right for a stateless web server, and exactly wrong for a database, where replica 2 must keep its identity — and its disk — across restarts.

A StatefulSet is the variant that gives each Pod a stable identity. In this course we cover it as a talking point rather than a lab, because if you can run a Deployment you can read a StatefulSet, and the one genuinely new idea is per-replica storage — which is covered by the Persistence lab. You should still recognise one, because you will meet them in every cluster.

Reference

What Is Different

DeploymentStatefulSet
Pod namesweb-7d9c4f-abcde — randomdb-0, db-1, db-2 — ordinal and permanent
Network identityA Service load-balances across themEach Pod gets stable DNS: db-0.db.default.svc.cluster.local
Start and stop orderAll at once, in any orderSequential: 0, then 1, then 2 — and the reverse for deletion
StorageShared, or nonevolumeClaimTemplates give each replica its own claim
When to useStateless, interchangeable replicasDatabases, queues, anything with identity or quorum

The Three Ideas

Identity. The db-1 Pod that comes back after a restart is still db-1, with the same name, the same DNS record and the same volume. Other members of the cluster can be configured to find each other by name — which is how a database forms a quorum without a discovery service.

Order. Pods are created in order and terminated in reverse. podManagementPolicy: Parallel opts out when your application does not care.

Per-replica storage. This is the part worth pausing on:

volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 5Gi

Each replica gets its own claim — data-db-0, data-db-1 — created from this template. Scale to five and you get five volumes. Scaling down does not delete the claims, deliberately: the data outlives the Pod, and if you scale back up the same volume is reattached. It also means a StatefulSet you scaled to zero still holds storage you are paying for.

Because each replica has its own volume, a StatefulSet needs a StorageClass whose volumes can attach to individual nodes — ReadWriteOnce is the normal choice.

Headless Services

A StatefulSet normally pairs with a headless Service (clusterIP: None). Instead of load-balancing, DNS for that Service returns one record per Pod, which is what makes db-0.db resolvable and lets clients address a specific replica.

apiVersion: v1
kind: Service
metadata:
  name: db
spec:
  clusterIP: None
  selector:
    app: db
  ports:
    - port: 5432

Seeing One in Action

Your cluster runs its own StatefulSets, so you can look at the real thing rather than a contrived example:

kubectl get statefulsets -A
kubectl get pvc -A | head
kubectl get pod -l app.kubernetes.io/name=... -o wide

Then watch the ordering for yourself:

kubectl get pods -w        # then delete db-1 and watch only db-1 come back

Rollouts, and the Reason for Partitions

StatefulSets update in reverse ordinal order — highest number first — one Pod at a time, waiting for each to become ready. That is slower than a Deployment on purpose: you are usually rolling out something with a schema or a quorum.

updateStrategy.rollingUpdate.partition lets you update only Pods with an ordinal greater than the partition. Set partition: 3 on a five-replica set and only db-4 and db-3 move to the new version — a canary with real teeth, and the standard way to test a risky change on one replica before committing.

What to Take Away

  • Reach for a StatefulSet when identity matters: a stable name, a stable volume, or ordered start and stop.
  • volumeClaimTemplates gives each replica its own storage, and that storage outlives both the Pod and a scale-down.
  • A headless Service is what makes per-replica DNS work.
  • Rollouts are slower and ordered by design. The partition field is how you stage them.