In this guide, weโll walk through deploying a Kubernetes StatefulSet, attaching persistent volumes, and exposing it via a headless service in Google Kubernetes Engine (GKE).
Weโll also explore what happens when StatefulSet Pods are deleted โ and how Kubernetes ensures state persistence.
๐ง Step 01: Introduction
In this demo, you will:
โ
Create and deploy a StatefulSet
โ
Create a Headless Service to access StatefulSet pods
โ
Verify pod identity, storage persistence, and behavior during pod recreation
๐งฉ Step 02: Review 01-kubernetes-statefulset.yaml
Each StatefulSet Pod will get its own PersistentVolumeClaim (PVC).
Here, we use the premium-rwo storage class in GKE.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: myapp1-sts
spec:
selector:
matchLabels:
app: nginx
serviceName: "myapp1-hs-svc"
replicas: 3
minReadySeconds: 10
template:
metadata:
labels:
app: nginx
spec:
terminationGracePeriodSeconds: 10
initContainers:
- name: init-pass-hostname
image: alpine
command: ["/bin/sh", "-c", "echo POD_HOSTNAME: $HOSTNAME > /usr/share/nginx/html/index.html"]
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
containers:
- name: nginx
image: ghcr.io/stacksimplify/kubenginx:1.0.0
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "premium-rwo"
resources:
requests:
storage: 1Gi
๐ Key Points:
- Each Pod gets its own unique PVC using volumeClaimTemplates
- Pods are created one by one, not simultaneously
- The init container writes its hostname to /usr/share/nginx/html/index.html
๐ง Step 03: Review 02-kubernetes-headless-service.yaml
A Headless Service gives each StatefulSet Pod a unique DNS entry instead of load balancing them.
apiVersion: v1
kind: Service
metadata:
name: myapp1-hs-svc
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
๐ Key Points:
- clusterIP: None makes it headless
- Each Pod gets its own resolvable DNS name
Example:
- myapp1-sts-0.myapp1-hs-svc.default.svc.cluster.local
- myapp1-sts-1.myapp1-hs-svc.default.svc.cluster.local
๐ง Step 04: Review 03-curl-pod.yaml
Weโll use this simple pod to test the headless service connectivity.
apiVersion: v1
kind: Pod
metadata:
name: curl-pod
spec:
containers:
- name: curl
image: curlimages/curl
command: [ "sleep", "600" ]
โ๏ธ Step 05: Deploy StatefulSet and Verify
# Deploy Kubernetes manifests
kubectl apply -f kube-manifests/01-kubernetes-statefulset.yaml
kubectl apply -f kube-manifests/02-kubernetes-headless-service.yaml
kubectl apply -f kube-manifests/03-curl-pod.yaml
# List Pods
kubectl get pods
๐งฉ Observations:
- Pods are created one after another.
- Each Pod gets its own PVC automatically.
kubectl get statefulset
kubectl describe sts myapp1-sts
โ Youโll see:
- PVC created for Pod-0, then Pod-0 starts
- PVC created for Pod-1, then Pod-1 starts
- PVC created for Pod-2, then Pod-2 starts
๐๏ธ Step 06: Verify Persistent Volumes
kubectl get pvc
kubectl get pv
Then, go to Google Cloud Console โ Compute Engine โ Disks
๐งฉ Observation:
Youโll see 3 Persistent Disks automatically created โ one for each StatefulSet pod.
๐ Step 07: Verify Headless Service
kubectl get svc
kubectl describe svc myapp1-hs-svc
kubectl get endpoints myapp1-hs-svc
๐งฉ Observation:
Endpoints look like:
10.124.0.11:80, 10.124.1.12:80, 10.124.2.11:80
Test using curl-pod
kubectl exec -it curl-pod -- /bin/sh
Inside curl-pod, run:
curl myapp1-hs-svc.default.svc.cluster.local
Or continuously:
while true; do curl -s "http://myapp1-hs-svc.default.svc.cluster.local"; sleep 1; done
๐งฉ Observation:
Youโll see responses from multiple Pods, confirming traffic distribution.
Test individual Pod endpoints
# nslookup test
nslookup myapp1-sts-0.myapp1-hs-svc.default.svc.cluster.local
nslookup myapp1-sts-1.myapp1-hs-svc.default.svc.cluster.local
nslookup myapp1-sts-2.myapp1-hs-svc.default.svc.cluster.local
# curl test
curl myapp1-sts-0.myapp1-hs-svc.default.svc.cluster.local
curl myapp1-sts-1.myapp1-hs-svc.default.svc.cluster.local
curl myapp1-sts-2.myapp1-hs-svc.default.svc.cluster.local
๐งฉ Observation:
- Each request goes directly to the specific Pod. (Perfect for databases like MySQL master/replica setups.)
๐ Step 08: Delete a Pod and Observe Behavior
kubectl get pods
kubectl delete pod myapp1-sts-0
kubectl get pods
๐งฉ Observation:
The Pod is automatically recreated with the same name (myapp1-sts-0)
It reattaches the same PersistentVolumeClaim
Verify:
kubectl describe pod myapp1-sts-0
โ
Youโll see the same claim name:
ClaimName: www-myapp1-sts-0
๐งน Step 09: Clean-Up
# Delete manifests
kubectl delete -f kube-manifests/01-kubernetes-statefulset.yaml
kubectl delete -f kube-manifests/02-kubernetes-headless-service.yaml
kubectl delete -f kube-manifests/03-curl-pod.yaml
๐งฉ Observation:
PVCs and PVs still remain โ Persistent data survives even after StatefulSet deletion.
To fully clean up:
kubectl delete pvc www-myapp1-sts-0
kubectl delete pvc www-myapp1-sts-1
kubectl delete pvc www-myapp1-sts-2
Then confirm:
kubectl get pvc
kubectl get pv
๐งฉ Observation:
- Volumes will take a couple of minutes to delete.
- Check in GCP โ Compute Engine โ Disks to verify deletion.
โ Summary
| Concept | Description |
|---|---|
| StatefulSet | Manages Pods with stable identity and storage |
| Headless Service | Provides DNS-based access to individual Pods |
| PVC/PV | Ensures persistent data even if Pods restart |
| Deletion Behavior | Pods recreate with the same name and storage |
๐ก Real-World Use Cases
- Databases (MySQL, PostgreSQL)
- Message Brokers (Kafka, RabbitMQ)
- Caching Systems (Redis)
- Search Engines (Elasticsearch)
- Coordination Services (Zookeeper, Cassandra)
๐ฏ Final Thoughts
StatefulSets are essential when your workloads require stable identity, ordered deployment, and persistent storage.
They ensure data integrity and reliable scaling for stateful workloads โ a cornerstone of modern cloud-native database and messaging systems.
๐ Thanks for reading! If this post added value, a like โค๏ธ, follow, or share would encourage me to keep creating more content.
โ Latchu | Senior DevOps & Cloud Engineer
โ๏ธ AWS | GCP | โธ๏ธ Kubernetes | ๐ Security | โก Automation
๐ Sharing hands-on guides, best practices & real-world cloud solutions







Top comments (0)