StatefulSets
StatefulSets
A Deployment treats its Pods as interchangeable: random names, random start order, one shared Service. Databases and clusters need the opposite.
graph TB
SS[StatefulSet db] --> P0[db-0<br/>PVC data-db-0]
SS --> P1[db-1<br/>PVC data-db-1]
SS --> P2[db-2<br/>PVC data-db-2]
H[Headless Service db<br/>clusterIP: None] -.-> P0
H -.-> P1
H -.-> P2
What you get that a Deployment cannot give you:
| Property | Meaning |
|---|---|
| Stable identity | Pods are db-0, db-1, db-2 - the name survives a restart |
| Stable network name | db-0.db.default.svc.cluster.local via a headless Service |
| Own storage | volumeClaimTemplates creates one PVC per Pod, kept on delete |
| Ordered operations | starts 0,1,2; terminates 2,1,0; rolling update in reverse order |
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: web-headless # the headless Service, required
replicas: 3
selector:
matchLabels: { app: web }
template:
metadata:
labels: { app: web }
spec:
containers:
- name: web
image: nginx:1.27
volumeMounts:
- name: data
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "" # no dynamic provisioning here
resources:
requests:
storage: 1Gi
With no StorageClass in this cluster, volumeClaimTemplates will sit Pending
until a matching PV exists for every replica - three replicas need three PVs.
That is exactly why the lab creates /storage1..3 as three PVs first.
Things that catch people out
- Deleting the StatefulSet does not delete the PVCs. That is deliberate -
your data survives. It also means a redeploy picks the old data back up, and
that cleaning up is a manual
kubectl delete pvc. - Scaling down leaves the PVCs behind too.
- A StatefulSet does not make your application clustered. It provides identity and storage; replication is the application’s job - which is what an operator automates.