๐Ÿ“– Read-only preview โ€” lessons, diagrams, and quizzes only. The hands-on labs, live grading, and progress tracking require running the real course locally against a Kubernetes cluster.Run it locally โ†’

Module 7 ยท Lesson 7.3

StatefulSets

Everything since Module 3 has assumed pods are interchangeable: a Deployment's pods have random suffixes, any one can replace any other, and none of them keep anything a replacement wouldn't also have. That's exactly wrong for a database replica, a Kafka broker, or anything where which one you're talking to and what's on its disk both matter.

What a StatefulSet actually guarantees

Deployment pods vs. StatefulSet pods

Deployment

web-7d9f-abc
vol: attached
web-7d9f-def
vol: attached

StatefulSet

db-0
vol: data-db-0
db-1
vol: data-db-1
Delete a pod in each. The Deployment's replacement is a stranger with a new name and an empty disk. The StatefulSet's replacement is the same pod, same name, same volume โ€” it just picks up where it left off.

A StatefulSet gives you two things a Deployment never will:

  • Stable, predictable names: db-0, db-1, db-2 โ€” not random suffixes. Pods are created and scaled in strict ordinal order (0 first, then 1, then 2), and scaled down in reverse.
  • Stable storage per pod: volumeClaimTemplates creates one PVC per pod, named after it (data-db-0, data-db-1...). Delete db-0, and its replacement comes back as db-0, reattached to the same data-db-0 PVC โ€” not a fresh, empty volume.

This is the piece that matters most: a StatefulSet doesn't make storage magically safer, it makes the pairing between a pod's identity and its storage durable across restarts.

Headless Services: stable network identity too

A StatefulSet is paired with a headless Service (clusterIP: None). Instead of load-balancing across pods like a normal Service, it gives each pod its own stable DNS name: db-0.db.<namespace>.svc.cluster.local. For something like a database replica set where clients need to talk to a specific member (the primary, say), this is what makes that possible.

When you actually need this

Not every stateful-ish workload needs a StatefulSet โ€” a cache that rebuilds itself from scratch on restart is fine as a Deployment with a PVC nobody cares about losing. Reach for a StatefulSet specifically when identity matters: each replica needs to know who it is (ordinal-based config, like Kafka broker IDs) or needs its own durable, reattachable storage, not a shared or disposable one.

The infrastructure analogy

This is the difference between cattle and pets, made concrete: a Deployment's pods are cattle (identical, disposable, replace freely); a StatefulSet's pods are pets (each one has a name and history you care about preserving across restarts) โ€” while still being fully Kubernetes-managed, not hand-maintained snowflakes.

In the lab, you'll prove the storage half of this directly: write data to one pod, delete it, and watch the replacement come back with that same data already there.

๐Ÿงช Lab: lab-15-statefulsets

Preview only

Goal

Prove to yourself that a StatefulSet gives pods a stable identity โ€” name and storage โ€” that a Deployment never would, the same way you proved the reconciliation loop for real back in Module 1.

Tasks

  1. Apply the manifests: kubectl apply -f manifests/
  2. Watch pods come up in strict order: kubectl get pods -n lab-15-statefulsets -w โ€” db-0, then db-1, then db-2. Compare this to a Deployment's pods, which all get random suffixes and come up in no particular order.
  3. Check storage: kubectl get pvc -n lab-15-statefulsets โ€” one PVC per pod, named data-db-0, data-db-1, data-db-2. Each pod owns its own volume; they are not shared.
  4. Write a marker into db-0's volume: kubectl exec -n lab-15-statefulsets db-0 -- sh -c 'echo persisted > /data/marker.txt'
  5. Delete that pod: kubectl delete pod db-0 -n lab-15-statefulsets
  6. Watch it come back: kubectl get pods -n lab-15-statefulsets -w โ€” it comes back as db-0 again (not db-3), because the StatefulSet controller always fills the lowest missing ordinal.
  7. Prove the volume came back with it, untouched: kubectl exec -n lab-15-statefulsets db-0 -- cat /data/marker.txt should still print persisted. A Deployment's replacement pod would have gotten a brand-new, empty volume.

Check

Run the check once db-0 is back Running after the delete, with /data/marker.txt containing persisted.

This lab runs against a real local Kubernetes cluster with an automated grader โ€” clone the repo and run make start to do it for real.

๐Ÿ“ Quiz

1. A StatefulSet pod named `db-1` is deleted. What's its replacement named?

2. What does `volumeClaimTemplates` actually create?

3. You delete db-0 in a StatefulSet. Compare to deleting a pod in a Deployment with a PVC in its pod template (not volumeClaimTemplates) โ€” what's the key difference in what comes back?scenario

4. What does a headless Service (clusterIP: None) paired with a StatefulSet actually give you?

5. A cache rebuilds its entire contents from a backing database on every restart, and no replica needs to be individually addressable. Deployment or StatefulSet?scenario

Progress isn't saved in this preview โ€” run the course locally to track completion and grade labs for real.