root-06-m02-deployments-scaling-updates — a new, full gold-standard- pattern module: why Deployments/ReplicaSets exist, how a rolling update actually progresses, and what rollback restores. Lesson, demonstration (a healthy rollout vs. one stalled on ImagePullBackOff), knowledge check, guided exercise (planning a safe rollout strategy), real Labs (rolling-update-task, deployment-rollback), and a reflection. root-06-m03-jobs-cronjobs-daemonsets — a new PARTIAL module: Jobs, CronJobs, and DaemonSets as distinct workload shapes from a Deployment's always-on model. Lesson + knowledge check + real Labs (job-task, cronjob-task). Co-Authored-By: Claude Sonnet 5 <[email protected]>
82 lines
4.4 KiB
Markdown
82 lines
4.4 KiB
Markdown
# Why Deployments Exist & How a Rolling Update Progresses
|
|
|
|
## The problem a bare Pod doesn't solve
|
|
|
|
A Pod, on its own, has no self-healing and no concept of "there should be more than one of
|
|
these." If a Pod crashes, nothing recreates it. If you need 3 copies for capacity, you'd have to
|
|
create 3 separately-named Pods by hand and keep track of all of them yourself. If you need to
|
|
update the container image, you'd have to delete and recreate every one of them manually,
|
|
almost certainly causing a visible outage while you do it.
|
|
|
|
**A Deployment solves all three problems at once**: it declares how many replicas of a Pod
|
|
template should exist, keeps that count true continuously (the exact desired-state mechanism
|
|
from ROOT 05), and knows how to change the Pod template over time — a version upgrade — without
|
|
just deleting everything and starting over.
|
|
|
|
## ReplicaSets: the layer underneath, briefly
|
|
|
|
You'll rarely touch a ReplicaSet directly, but understanding it clarifies what a Deployment
|
|
actually does. A Deployment doesn't manage Pods directly — it manages a ReplicaSet, which is
|
|
what actually keeps N Pods matching a label selector running. When you update a Deployment's
|
|
Pod template (like changing the image), the Deployment creates a NEW ReplicaSet with the new
|
|
template and gradually shifts replicas from the old ReplicaSet to the new one. The old
|
|
ReplicaSet isn't deleted — it's scaled to zero and kept around, which is exactly what makes
|
|
rollback possible (more on that below).
|
|
|
|
## How a rolling update actually progresses
|
|
|
|
By default, a Deployment updates using the `RollingUpdate` strategy: it doesn't take all old
|
|
Pods down and bring all new ones up at once (that would cause an outage). Instead, it
|
|
incrementally creates new-version Pods and removes old-version ones, always keeping enough
|
|
capacity available:
|
|
|
|
```
|
|
Before: [v1] [v1] [v1]
|
|
Step 1: [v1] [v1] [v1] [v2] <- one new Pod created
|
|
Step 2: [v1] [v1] [v2] <- one old Pod removed once new one is Ready
|
|
Step 3: [v1] [v1] [v2] [v2]
|
|
Step 4: [v1] [v2] [v2]
|
|
...
|
|
After: [v2] [v2] [v2]
|
|
```
|
|
|
|
Crucially, a new Pod only counts as "up" for the purposes of proceeding once it passes its
|
|
readiness probe (see ROOT 10's gold-standard module) — this is exactly why a misconfigured
|
|
readiness probe can make a rollout hang indefinitely instead of failing fast: Kubernetes is
|
|
correctly waiting for a "ready" signal that will never come.
|
|
|
|
## Rollback: what it actually restores
|
|
|
|
`kubectl rollout undo` doesn't magically know how to "undo" arbitrary changes — it works because
|
|
of the old ReplicaSet still sitting around at zero replicas, from the mechanism described above.
|
|
Rolling back means: scale the OLD ReplicaSet back up and the current (broken) one back down,
|
|
using the exact same rolling mechanism as a forward update. This is why rollback is fast and
|
|
safe — it's not a special operation, it's the same well-tested rolling-update machinery running
|
|
in reverse, against a Pod template that's already known to have worked before.
|
|
|
|
## Instructor Notes
|
|
|
|
**Approximate timing:** 15 minutes read, 10-12 minutes live with the ReplicaSet diagram.
|
|
|
|
**Demo plan:** Draw (or show) the ReplicaSet-swap diagram above on a whiteboard before the
|
|
demonstration activity — students who see the "old ReplicaSet scaled to zero, not deleted"
|
|
detail up front connect rollback to rollout much faster.
|
|
|
|
**Likely misconceptions to watch for:**
|
|
- Students often think rollback "restores a backup" or reverts a Git-style diff. Correct this:
|
|
it's scaling an existing (still-present) ReplicaSet back up, nothing is being restored from
|
|
storage.
|
|
- "Rolling update" is sometimes assumed to mean "one Pod at a time, always." The actual pace is
|
|
controlled by `maxSurge`/`maxUnavailable` (not covered in depth here, but worth naming so
|
|
students don't over-generalize from the simplified diagram).
|
|
|
|
**Discussion question:** "Why does a rolling update need readiness probes to work correctly,
|
|
specifically?" (Answer: without a readiness signal, Kubernetes has no way to know when a new
|
|
Pod is actually safe to receive traffic before removing an old one — it would either guess via a
|
|
fixed delay, unreliable, or not wait at all, unsafe.)
|
|
|
|
**Optional extension:** ask what would happen to an in-progress rollout if the new image simply
|
|
doesn't exist (a typo in the tag) — a good bridge to real troubleshooting: the rollout stalls
|
|
indefinitely with `ImagePullBackOff` on the new Pods, never completing and never rolling back on
|
|
its own.
|