Managing StatefulSets
1. Creating StatefulSet
Example: StatefulSet with PVC template
apiVersion: apps/v1
kind: StatefulSet
metadata: { name: db }
spec:
serviceName: db # headless service for stable DNS
replicas: 3
selector: { matchLabels: { app: db } }
template:
metadata: { labels: { app: db } }
spec:
containers:
- name: postgres
image: postgres:16
volumeMounts: [{ name: data, mountPath: /var/lib/postgresql/data }]
volumeClaimTemplates:
- metadata: { name: data }
spec:
accessModes: [ReadWriteOnce]
storageClassName: gp3
resources: { requests: { storage: 50Gi } }
2. Listing StatefulSets
kubectl get sts
kubectl get sts,svc,pvc -l app=db
| Column | Meaning |
| READY | ready/desired replicas |
| AGE | Creation time |
3. Describing StatefulSet Details
| Field | Meaning |
| Pod Management Policy | OrderedReady / Parallel |
| Update Strategy | RollingUpdate / OnDelete |
| Volume Claims | Templates & bound PVCs |
4. Scaling StatefulSet
kubectl scale sts db --replicas=5
kubectl patch sts db --type=json -p='[{"op":"replace","path":"/spec/replicas","value":5}]'
| Direction | Order |
| Scale up | Lowest ordinal first (db-0, db-1, ...) |
| Scale down | Highest ordinal first (last in, first out) |
Warning: PVCs are not deleted on scale-down. Reclaim manually or with persistentVolumeClaimRetentionPolicy.
5. Understanding Ordered Pod Creation
| Phase | Detail |
| Sequential | db-N waits for db-(N-1) Ready |
| Ordinal | 0,1,2,... in pod name |
| DNS | db-0.db.NS.svc.cluster.local |
6. Using Parallel Pod Management
spec:
podManagementPolicy: Parallel # create/delete all at once
| Policy | When |
| OrderedReady (default) | Apps requiring strict startup ordering |
| Parallel | Independent replicas (faster scale) |
7. Configuring Volume Claim Templates
| Property | Detail |
| Naming | <template-name>-<sts-name>-<ordinal> |
| Lifecycle | Outlives pod by default |
| retentionPolicy | whenDeleted, whenScaled (Retain/Delete) |
persistentVolumeClaimRetentionPolicy:
whenDeleted: Retain
whenScaled: Delete
8. Using Headless Services
apiVersion: v1
kind: Service
metadata: { name: db }
spec:
clusterIP: None
selector: { app: db }
ports: [{ port: 5432, name: pg }]
| Effect | Detail |
| clusterIP: None | No VIP; DNS returns pod IPs |
| Per-pod DNS | POD-NAME.SVC.NS.svc.cluster.local |
9. Understanding Stable Network IDs
| Identity | Persistence |
| Pod name | Stable across reschedules (db-0 stays db-0) |
| DNS | Stable via headless service |
| Storage | Same PVC re-attaches |
| Pod IP | NOT stable; changes per restart |
10. Updating StatefulSets
| updateStrategy | Behavior |
| RollingUpdate | Highest ordinal first; one at a time |
| OnDelete | Manual: kill pod to update |
| partition: N | Only update ordinals ≥N (canary) |
| maxUnavailable NEW | ≥1.27 — concurrent updates |
updateStrategy:
type: RollingUpdate
rollingUpdate: { partition: 2, maxUnavailable: 1 }
11. Deleting StatefulSets
kubectl delete sts db
kubectl delete sts db --cascade=orphan # keep pods
kubectl delete pvc -l app=db # explicit PVC cleanup
Warning: Default delete does NOT remove PVCs. Data persists until PVCs are deleted.
12. Troubleshooting StatefulSet Issues
| Symptom | Common Cause |
| Pod stuck Pending | PVC unbound (no PV / StorageClass issue) |
| db-1 never starts | db-0 not Ready (ordered policy) |
| Volume reattach fails | RWO volume on wrong AZ (zone-pinned) |
| DNS resolution fails | Headless service missing/mismatched |