Lesson: Pods, Deployments, DaemonSets & StatefulSets
What you'll learn
- What a Pod is and why it is the smallest thing Kubernetes runs.
- How Deployments use ReplicaSets to keep copies running, scale, and roll out new versions.
- What a DaemonSet is and why "one per node" is useful.
- What a StatefulSet is and when sticky identity and storage matter.
Skill gained: you can pick the right workload object and run, scale, and update it on the lab cluster.
The lesson
A "workload" is just a thing that runs on the cluster. Kubernetes gives you several workload objects, each shaped for a different job. You will use Deployments most, but you should recognise all four.
1. The Pod — the smallest unit
A Pod is one or more containers that always run together on the same node, sharing a network address and (optionally) storage. Usually a Pod is just one container. Kubernetes never schedules a bare container — it always wraps it in a Pod.
apiVersion: v1
kind: Pod
metadata:
name: web
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
The catch: a bare Pod is fragile. If its node dies, the Pod is gone forever — nothing recreates it. That is why you almost never create Pods directly. You let a higher-level controller create them for you.
2. ReplicaSet and Deployment
A ReplicaSet is a control loop that keeps N identical Pods running. If you ask for 3 and one dies, it makes a new one.
You rarely write a ReplicaSet by hand either. Instead you write a Deployment, which manages ReplicaSets for you and adds rolling updates and rollbacks. This is the workhorse for stateless apps (web servers, APIs).
Deployment
|
| manages
v
ReplicaSet (desired: 3)
|
| creates
v
Pod Pod Pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template: # the Pod blueprint
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
Note the two label spots: selector.matchLabels tells the Deployment which Pods it owns, and the template.metadata.labels stamps those labels onto the Pods it creates. They must match.
Scaling — change the number:
kubectl apply -f web.yaml # create
kubectl get deploy web # READY 3/3 when ready
kubectl scale deploy web --replicas=5
Rolling update — change the image and apply again. The Deployment brings up new Pods and removes old ones gradually, so there is no downtime:
kubectl set image deploy/web nginx=nginx:1.28
kubectl rollout status deploy/web # watch progress
kubectl rollout history deploy/web # see revisions
kubectl rollout undo deploy/web # roll back if it broke
3. DaemonSet — one Pod per node
A DaemonSet ensures exactly one copy of a Pod runs on every node (or every node matching a filter). When a new node joins the cluster, it automatically gets one too. This is for node-level agents: log shippers, metrics collectors, network plugins. In the lab, the Calico CNI runs as a DaemonSet — that is why every worker (10.100.100.8/.9/.10) has networking.
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-logger
spec:
selector:
matchLabels:
app: node-logger
template:
metadata:
labels:
app: node-logger
spec:
containers:
- name: logger
image: busybox:1.36
command: ["sh", "-c", "while true; do echo tick; sleep 60; done"]
You do not set replicas on a DaemonSet — the count is "however many nodes there are."
kubectl get pods -o wide # note one node-logger per node, spread across nodes
4. StatefulSet — sticky identity and storage
A Deployment treats its Pods as interchangeable cattle: web-7f9c-abcde is a random name and any Pod can replace any other. That breaks for stateful systems like databases, where each member needs a stable name and its own persistent disk.
A StatefulSet gives Pods:
- Stable, ordered names —
db-0,db-1,db-2(not random). - Stable storage — each Pod keeps its own volume across restarts, via a
volumeClaimTemplate. - Ordered startup/shutdown —
db-0beforedb-1, useful for clustered databases.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: db
spec:
serviceName: db
replicas: 2
selector:
matchLabels:
app: db
template:
metadata:
labels:
app: db
spec:
containers:
- name: pg
image: postgres:16
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
You will learn what volumeClaimTemplates and accessModes mean in the Persistent Storage lesson. For now, just know: use a StatefulSet when each Pod is unique and must keep its own data. The lab's NFS StorageClass (10.100.100.12) can back these claims.
5. Choosing the right one
Need it on EVERY node? -> DaemonSet
Each Pod unique + own disk? -> StatefulSet
Stateless, interchangeable copies-> Deployment (default choice)
Just experimenting, one-off Pod -> bare Pod (knows it won't self-heal)
When in doubt, reach for a Deployment. Most internship work is stateless web/API services, and a Deployment gives you scaling, self-healing, and zero-downtime updates for free.
6. Inspecting workloads
kubectl get deploy,rs,pods # see the chain Deployment -> ReplicaSet -> Pods
kubectl describe deploy web # events, replica counts, update strategy
kubectl logs deploy/web # logs from a Pod of the Deployment
kubectl delete deploy web # deletes the ReplicaSet and Pods too
Try deleting a single Pod created by your Deployment (kubectl delete pod <name>) and immediately run kubectl get pods. You will watch the control loop create a replacement within seconds — self-healing in action.
Dig deeper
Search terms
kubernetes pod vs deploymentkubernetes rolling update explainedkubectl scale deploymentkubernetes daemonset use casekubernetes statefulset vs deployment
Check yourself
- Why should you almost never create a bare Pod for a real app?
- What does a ReplicaSet do, and which object normally manages it for you?
- How do you roll back a bad Deployment update in one command?
- What is a DaemonSet used for, and why don't you set
replicason it? - Give two things a StatefulSet provides that a Deployment does not.
No comments to display
No comments to display