Amazon EKS — StatefulSets & PVCs
StatefulSets & Persistent Volume Claims
StatefulSets are the Kubernetes workload for stateful applications — databases, message queues, and any app that needs stable identity and persistent storage.
StatefulSet vs Deployment
| Feature | Deployment | StatefulSet |
|---|---|---|
| Pod names | Random (web-7abc123-xyz) |
Ordered (db-0, db-1, db-2) |
| Storage | Shared or none | Each pod gets its own PVC |
| Scaling | All at once | One at a time (ordered) |
| Deletion | All at once | Reverse order |
| DNS | Via Service only | Individual pod DNS |
StatefulSet with EBS
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15
ports:
- containerPort: 5432
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: ebs-gp3
resources:
requests:
storage: 20Gi
This creates:
postgres-0,postgres-1,postgres-2- Each with its own PVC:
data-postgres-0,data-postgres-1,data-postgres-2
Headless Service for StatefulSet
apiVersion: v1
kind: Service
metadata:
name: postgres
spec:
clusterIP: None # Headless!
selector:
app: postgres
ports:
- port: 5432
With headless Service, each pod gets a DNS name:
postgres-0.postgres.default.svc.cluster.local
postgres-1.postgres.default.svc.cluster.local
postgres-2.postgres.default.svc.cluster.local
Common Mistakes
| Mistake | Impact |
|---|---|
| Using Deployment for databases | Pods share storage, data corruption |
| Forgetting headless Service | Can’t address individual pods |
| Deleting PVCs accidentally | Data loss (use Retain reclaim policy) |
| Not setting resource requests | Pod evicted under memory pressure |
What’s Next?
High-performance storage: FSx for Lustre.