Lab: Deployments vs StatefulSets (Side-by-Side)
Lab Goal
In this lab, you will deploy the same application two ways:
- Once using a Deployment
- Once using a StatefulSet
You will then:
- Scale both
- Delete pods
- Observe naming, ordering, and persistence behavior
By the end, the difference between the two controllers will be obvious.
Prerequisites
- Access to a Kubernetes or OpenShift cluster
kubectlorocCLI configured- A namespace you can work in
Create a fresh namespace:
oc create namespace workload-lab
oc config set-context --current --namespace=workload-labPart 1: Deployment (Stateless Workload)
Step 1: Create the Deployment
Create a file named deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-deployment
spec:
replicas: 3
selector:
matchLabels:
app: demo
template:
metadata:
labels:
app: demo
spec:
containers:
- name: app
image: nginx
ports:
- containerPort: 80Apply it:
oc apply -f deployment.yamlStep 2: Observe the Pods
oc get podsExample output:
demo-deployment-6f9c5c8c8b-4n7qx
demo-deployment-6f9c5c8c8b-hkz9m
demo-deployment-6f9c5c8c8b-qpl2sObservations:
- Pod names are random
- Pods are interchangeable
- Kubernetes doesn’t care which pod is which
Step 3: Delete a Pod
oc delete pod demo-deployment-6f9c5c8c8b-4n7qxThen:
oc get podsWhat happens:
- A new pod is created
- It has a different name
- Kubernetes replaces capacity, not identity
Step 4: Scale the Deployment
oc scale deployment demo-deployment --replicas=5
oc get podsKey takeaway:
Scaling is fast, parallel, and unordered.
Part 2: StatefulSet (Stateful Workload)
Step 1: Create a Headless Service
StatefulSets require a stable network identity.
Create service.yaml:
apiVersion: v1
kind: Service
metadata:
name: demo-stateful
spec:
clusterIP: None
selector:
app: demo-statefulApply it:
oc apply -f service.yamlStep 2: Create the StatefulSet
Create statefulset.yaml:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: demo-stateful
spec:
serviceName: demo-stateful
replicas: 3
selector:
matchLabels:
app: demo-stateful
template:
metadata:
labels:
app: demo-stateful
spec:
containers:
- name: app
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: data
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1GiApply it:
oc apply -f statefulset.yamlStep 3: Observe Pod Creation Order
oc get pods -wYou will see:
demo-stateful-0
demo-stateful-1
demo-stateful-2Created one at a time, in order.
Step 4: Delete a Stateful Pod
oc delete pod demo-stateful-1Then:
oc get podsWhat happens:
demo-stateful-1is recreated- The name stays the same
- Its PersistentVolume is reused
This is identity preservation.
Step 5: Scale the StatefulSet
oc scale statefulset demo-stateful --replicas=5Watch carefully:
oc get pods -wPods are created:
demo-stateful-3
demo-stateful-4Part 3: Side-by-Side Comparison
| Behavior | Deployment | StatefulSet |
|---|---|---|
| Pod names | Random | Predictable (-0, -1, -2) |
| Pod replacement | New identity | Same identity |
| Storage | Optional/shared | One volume per pod |
| Scaling | Parallel | Sequential |
| Best for | Stateless apps | Databases, clustered systems |
Key Takeaways
- Deployments treat pods as cattle
- StatefulSets treat pods as individuals
- Identity and storage are the deciding factors
- If you don’t need StatefulSets — don’t use them
Cleanup
oc delete deployment demo-deployment
oc delete statefulset demo-stateful
oc delete service demo-stateful
oc delete pvc --all