StatefulSets
Pods with a name and a memory.
Deployments treat pods like identical, disposable workers. That is perfect for web servers. But a database cluster is different. Each member has its own role, its own name, and its own data. For these apps, Kubernetes offers the stateful set. In this lesson, you will see how it keeps identity and storage together.

- Deployment pods are interchangeable
- Some apps need a stable identity
- StatefulSets provide it
Deployment versus StatefulSet
Let's compare the two. A deployment gives pods random names, like web, dash, a random suffix. They start together, and share one volume, or none. A stateful set gives pods predictable names, with an index, db zero, db one, and db two. They start in order, one after another, and stop in reverse. And each pod gets its own personal volume, which follows it, even if the pod is rebuilt. Identity, order, and private storage are the three gifts.
Deployment
- Random pod names
- All start at once
- Shared or no storage
- Interchangeable pods
StatefulSet
- Stable names: db-0, db-1, db-2
- Ordered start and stop
- A private volume per pod
- Each pod keeps its identity
A StatefulSet in YAML
Here is a stateful set. It looks like a deployment, with a few new ideas. Service name points to a headless service, which gives each pod its own D N S name. We ask for three replicas. And at the bottom, volume claim templates, is a blueprint for claims. For every pod, Kubernetes stamps out a new claim from it, named after the pod, so db zero gets its own disk, db one gets another, and so on.
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: db
image: nginx:1.27
volumeMounts:
- name: data
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1GiNames that stick
Let's create it, together with its headless service. After a little while, the pods are running, and see their names. Zero, one, and two, and the claims, one for each pod. Now watch. We delete pod db one. The stateful set creates a replacement, with exactly the same name, db one, and it reconnects to the same claim, so its data is still there. Even the D N S name of the pod stays the same. Identity survives replacement.
kubectl apply -f sts.yaml service/db created statefulset.apps/db created Warning: spec.SessionAffinity is ignored for headless services kubectl get pods -l app=db NAME READY STATUS RESTARTS AGE db-0 1/1 Running 0 46s db-1 1/1 Running 0 44s db-2 1/1 Running 0 43s kubectl get pvc -o custom-columns=NAME:.metadata.name,STATUS:.status.phase,SIZE:.status.capacity.storage NAME STATUS SIZE data-db-0 Bound 1Gi data-db-1 Bound 1Gi data-db-2 Bound 1Gi kubectl delete pod db-1 --now pod "db-1" deleted from default namespace kubectl get pods -l app=db NAME READY STATUS RESTARTS AGE db-0 1/1 Running 0 55s db-1 1/1 Running 0 8s db-2 1/1 Running 0 52s
File used: sts.yaml
apiVersion: v1
kind: Service
metadata:
name: db
spec:
clusterIP: None
selector:
app: db
ports:
- port: 80
---
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: db
image: nginx:1.27
volumeMounts:
- name: data
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1GiSummary
Good. A stateful set gives pods stable names, ordered startup, and a private volume each. It is the right choice for databases and clustered systems. Next, a workload that puts one pod on every node, the daemon set.
Key takeaways- Stable names: db-0, db-1, db-2
- Ordered start, private volumes
- Replacement keeps the identity