StatefulSets

Kubernetes Intermediate/Advanced

Chapter 1 · StatefulSets

Course 1 closed with a deliberate simplification — a Deployment and a single PVC standing in for a proper database. This chapter is the payoff: what a StatefulSet actually adds, and why.

Restating the Problem — Why the Capstone's Database Was a Simplification

A plain Deployment treats all its replicas as interchangeable "cattle" — k8s1-3's own framing. Fine for stateless apps. Genuinely wrong for a database that might need multiple replicas, each with its own distinct identity and its own distinct, consistently-reattached storage.

What a StatefulSet Actually Guarantees

  • Stable, predictable network identity — each pod gets a predictable, persistent name like db-0, db-1, db-2 (not a random suffix, unlike a Deployment's pods), staying the same even if that specific pod is recreated or rescheduled.
  • Stable storage — each replica gets its own PersistentVolumeClaim (k8s1-8's material), and critically, when a pod is recreated, it's automatically reattached to the same PVC it had before, not a fresh or randomly assigned one.

This is the core value proposition, stated plainly: identity and storage that survive individual pod replacement, per-replica.

Ordered, Predictable Pod Creation & Deletion

StatefulSet pods are created and deleted in orderdb-0 before db-1 before db-2, and deleted in reverse — rather than in parallel or arbitrary order, unlike a Deployment. This matters for stateful systems where, for instance, a "primary" instance needs to exist and be ready before "replica" instances that depend on it start up — a genuine, real requirement for many clustered systems.

Headless Services — Enabling Direct Pod Addressing

A StatefulSet is typically paired with a headless Service (clusterIP: None). Rather than load-balancing across all matching pods the way a normal Service does (k8s1-6's material), a headless Service instead provides a DNS record for each individual pod directly — e.g. db-0.db-service.namespace.svc.cluster.local — letting other parts of the system address a specific replica by name, not just "any healthy one." Genuinely necessary when replicas aren't interchangeable — writes must go to a specific primary, for instance.

A Concrete StatefulSet YAML, Explained

apiVersion: apps/v1 kind: StatefulSet metadata: name: db spec: serviceName: db-service replicas: 3 selector: matchLabels: app: db template: metadata: labels: app: db spec: containers: - name: db image: postgres:16 volumeClaimTemplates: - metadata: name: data spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 10Gi

Same apps/v1 group as Deployment — a genuinely useful reminder that StatefulSet is a sibling controller, not an unrelated concept. spec.template and spec.selector are the same shape as a Deployment's. The genuinely new piece is volumeClaimTemplates — this automatically creates a unique PVC per replica (e.g. data-db-0, data-db-1, data-db-2), rather than the single shared PVC the capstone used.

A sibling of Deployment, not a separate concept
Everything about template/selector/labels from k8s1-5 transfers directly. StatefulSet only adds three things: predictable naming, per-replica storage via volumeClaimTemplates, and ordered creation/deletion.

Revisiting the Capstone's Database, Properly

With the StatefulSet above, db-0 keeps its own name and its own dedicated PVC (data-db-0) across any restart or rescheduling. Scaled to 3 replicas, db-1 and db-2 each get their own independent PVCs too, rather than sharing or conflicting over the capstone's single shared volume — exactly the gap Course 1's warn-box flagged.

When You Actually Need a StatefulSet

Honest framing, matching this course's own recurring convention: if only one replica needs persistent storage, k8s1-8's simple Deployment+single-PVC pattern (exactly what the capstone used) is genuinely fine and simpler. StatefulSets earn their added complexity specifically when multiple replicas each need their own distinct identity and storage — a multi-node database cluster where each node needs to know its own identity, a distributed system with leader election, or a message queue cluster with partition ownership tied to specific nodes.

Scaling down does not delete the removed replicas' PVCs
A deliberate data-safety measure: scaling a StatefulSet from 3 replicas down to 1 leaves data-db-1 and data-db-2 intact, untouched, and still billing — echoing cloud1-9's own orphaned-storage cost material. Storage can silently accumulate if these aren't cleaned up manually once genuinely no longer needed.

Hands-On Exercises

Exercise 1

Explain the two specific guarantees a StatefulSet provides that a Deployment does not, and explain why a multi-replica database genuinely needs both.

📄 View solution
Exercise 2

Explain what a headless Service is and why a StatefulSet typically needs one, specifically contrasting it with a normal Service's load-balancing behavior.

📄 View solution
Exercise 3

A team scales their StatefulSet down from 3 replicas to 1, then later scales back up to 3. Explain what happens to the PVCs of the two removed replicas during the scale-down, and what this means for the team's ongoing storage costs if they don't clean up manually.

📄 View solution

Chapter 1 Quick Reference

  • Stable identity (predictable names like db-0) + stable storage (reattached to the same PVC) — the two things a Deployment doesn't provide
  • Pods created/deleted in strict order — db-0 first, deleted last
  • Headless Service — DNS per individual pod, not load-balanced across all of them
  • volumeClaimTemplates — the StatefulSet-specific field auto-creating a unique PVC per replica
  • Same apps/v1 group and template/selector shape as Deployment — a sibling controller, not a new concept
  • Only worth the complexity when multiple replicas each need distinct identity/storage — a single-replica case doesn't need one
  • Scaling down leaves removed replicas' PVCs intact and billing — a real, easy-to-miss cost trap
  • Next chapter: DaemonSets & Jobs/CronJobs — node-level agents, batch and scheduled workloads