๐ซ School Platform โ learn Kubernetes step-by-step
One real project โ a school management system with two services โ used to teach
every DevOps tool with a job to do. Complex ideas, explained like you're five, with school
analogies, diagrams and hands-on labs.
๐ณ Docker โธ๏ธ Kubernetes
๐๏ธ Terraform โ๏ธ AWS
๐ CircleCI ๐ค ArgoCD / GitOps
2 Take the 14 lessons
One git branch = one idea. Each lesson: ELI5 story, analogy, diagram, What/Why/How, and commands to try.
3 Go deeper
4K architecture diagrams, the production design doc, and a narrated video tour โ all below.
๐บ๏ธ The big picture โ one diagram, the whole school
All 26 lessons on one canvas. Click for the 4K version .
๐ The 26 lessons
๐
Not sure how to pace it? Follow the 9-week study plan โ sequence, time estimates, weekly milestones and a capstone, with progress saved in your browser.
Lessons live on branches โ branch 05 contains lessons 01โ05, so you can stop and
resume anywhere. Click a card to read the lesson right on GitHub (diagrams render there), or
check the branch out locally. Prefer pictures? All 14 lessons are also drawn as
numbered box-and-arrow diagrams on one page .
๐งฐ Part 3 โ running it for real (lessons 16โ26)
The cluster stands โ now learn to operate it: debug it, secure it,
schedule it, upgrade it, extend it, and watch it breathe. Same format, same school.
# take the course locally:
git clone https://github.com/BaluRaut/learn-kubernetes-school.git
cd learn-kubernetes-school
git checkout lesson-01-containers # then open lessons/01-containers/README.md
๐
Completely new to all of this? Do the
Before-You-Start checklist first โ 7 foundations
(terminal, git, HTTP, YAMLโฆ), each with a self-check and free resources. Your ticks are saved
in the browser.
โธ๏ธ The real k8s manifests
The actual YAML files the lessons teach โ every one heavily commented, in
k8s/ .
Read them in this order (it's also the apply order):
a
๐ช namespace.yaml The classroom everything else lives in โ apply this first. lesson 05Open file โ
b
๐ configmap.yaml Non-secret settings on the notice board: PORT, APP_VERSION. lesson 06Open file โ
c
๐ secret.example.yaml Locker-key template โ copy to git-ignored secret.yaml, fill in the DB password. lesson 06Open file โ
d
๐งโ๐ซ deployment.yaml The heart: 2 replicas, rolling updates, probes, resources โ 4 lessons in one file. lessons 03 ยท 07 ยท 08 ยท 11Open file โ
e
โ๏ธ service.yaml The reception desk: stable name + IP in front of the Node API pods. lesson 04Open file โ
f
๐ analytics-deployment.yaml Second service, same patterns โ calls the Node API by Service name. lessons 03 ยท 04Open file โ
g
โ๏ธ analytics-service.yaml Reception desk #2, for the Python analytics pods. lesson 04Open file โ
h
๐ hpa.yaml The transport manager: 2โ5 pods, more buses at 70% CPU. lesson 09Open file โ
i
๐ซ ingress.yaml The main gate: one ALB, /analytics โ Python, everything else โ Node. lesson 10Open file โ
โ๏ธ The AWS components under the cluster โ purpose, required or optional
"Is EC2 connected to Kubernetes?" โ completely: Kubernetes doesn't replace EC2,
it sits on top of it. Every node you see in kubectl get nodes IS an EC2 instance
(a rented desk ๐ฅ๏ธ); an EKS node group is an Auto Scaling Group of those desks; the HPA adds
pods and, when they no longer fit, the cluster autoscaler asks the ASG for more desks .
A NotReady node is usually an EC2 story underneath (spot reclaimed, instance died).
The map below shows every AWS piece this repo's terraform/
touches โ what each is for , and whether it's
REQUIRED or OPTIONAL .
Click for the 4K version .
Deep-dive on the two foundations (IAM & EC2) in the
AWS foundations course โ its lesson 12
is exactly this reveal.
๐บ๏ธ The architecture diagrams
The big numbered diagrams from the README, one after another โ readable right here;
click any to open the 4K version. Every one is also explained step-by-step
in the README .
1 ยท The big picture โ how all the tools fit together
2 ยท Docker โ image build & local compose
3 ยท Kubernetes โ pods, services, HPA in the cluster
4 ยท Terraform โ AWS โ VPC, EKS, ECR, RDS from code
5 ยท CI/CD โ test โ build โ approve โ deploy
6 ยท Multi-tenancy โ 100 schools, zero mix-ups
7 ยท Under the hood โ what docker run really does
8 ยท Under the hood โ how kubectl apply becomes a pod
9 ยท Under the hood โ the life of one HTTP request
10 ยท Before you start โ the 7 foundations
๐ Go deeper
Production design doc โ multi-tenancy for 100 schools, single-domain routing, backups & DR runbook, security checklists (English + เคฎเคฐเคพเค เฅ toggle)
๐ฌ Narrated video walkthrough (6 min, 4K) โ a guided tour through every numbered diagram
under-the-hood.md โ what really happens beneath docker run, kubectl apply, and one HTTP request
local-setup.md โ run everything on your machine in 3 levels, zero AWS cost
Main README โ the whole story in one page, with the setup checklists
๐ชช Course 0: Learn AWS School โ the foundations: IAM (who may do what) & EC2 (the desks EKS nodes really are)
๐ฑ Course 1: Learn Docker School โ 12 lessons on packing & shipping: images, layers, compose, multi-stage builds, registries & AWS ECR
๐ค Course 3: Learn ArgoCD School โ 12 lessons on deployment: without ArgoCD (by hand, CI/CD push) vs with ArgoCD (GitOps pull)
๐ The lesson diagrams โ follow the numbers
Every lesson as one numbered box-and-arrow diagram, one after another โ readable
right here. Also on a standalone page with jump navigation.
1 ๐ฑ Containers & images โ recipe โ lunchbox โ lunch
One recipe (Dockerfile) bakes one frozen lunchbox (image); every opened box (container) is identical.
๐ Dockerfile
the recipe card
๐ง Image
school-api:v1 โ frozen box
๐๏ธ Registry (ECR)
the shelf where images wait
๐ Running containers
box 1
box 2
box 3
1
docker build
2
docker push
3
docker run ร3 โ identical
2 ๐ช Pods โ one desk, one address, replace don't repair
Kubernetes never runs a bare container โ it always sits at a desk (Pod) with its own IP and shared shelf.
๐ Cluster network
callers
๐ช Pod โ IP 10.0.4.7
๐ฆ school-api
main container
๐ฆ sidecar
optional helper
๐๏ธ shared volume
1
talks to the Pod's IP
2
๐ช NEW Pod
new name, new IP 10.0.9.9
3
๐ฅ desks are replaced, never repaired
3 ๐งโ๐ซ Deployments โ declare a wish, the monitor enforces it forever
You say "always 2"; the ReplicaSet counts non-stop and replaces anything that dies.
๐งโ๐ซ You declare
replicas: 2 ยท image: v5
Deployment
school-api
ReplicaSet
the monitor ยท count = 2
๐ช pod โฆabc12
๐ฅ crashes!
๐ช pod โฆdef34
healthy
๐ช pod โฆxyz99
auto-created replacement
1
2
3
claims pods by label app: school-api
4
sees 1 missing โ makes a new one
4 โ๏ธ Services โ one number that never changes
Pods get new IPs all the time; callers dial the Service name and it forwards to whoever is present.
๐ analytics pod
calls http://school-api
โ๏ธ Service school-api
stable IP + DNS ยท port 80 โ 3000
๐ช pod 10.0.4.7
ready
๐ช pod 10.0.9.2
ready
๐ old pod
gone โ auto-removed
1
DNS finds the Service
2
picks a READY pod by label
3
5 ๐ช Namespaces โ classrooms inside one building
One shared cluster, partitioned into rooms โ names only need to be unique inside a room.
๐ซ One Kubernetes cluster โ the building
๐ช namespace: school
Deployments: school-api, analytics
Services ร2 ยท ConfigMap ยท Secret
HPA ยท Ingress
1
our room โ everything in this repo
๐ช kube-system
the school office:
CoreDNS ยท metrics-server
2
Kubernetes' own machinery
๐ช default
experiments land here
if you forget -n ๐
3
Same name in two rooms is fine โ "Aarav from 3A" vs "Aarav from 3B" ยท delete a room = clean sweep of only that room
6 ๐ ConfigMaps & Secrets โ settings live outside the lunchbox
Same image everywhere; the notice board (config) and locker key (secret) are injected at start-up.
๐ ConfigMap
PORT: 3000 ยท APP_VERSION
๐ Secret
DATABASE_URL (password!)
๐ช Pod at start-up
env: PORT, DATABASE_URLโฆ
app reads process.env
๐ฑ Image
identical in dev & prod
1
envFrom: configMapRef
2
secretKeyRef (never in git)
3
change settings โ restart pods โ same image, new behaviour
7 ๐ Health probes โ two questions, two very different consequences
Liveness failure restarts the container; readiness failure only pauses its traffic.
๐งโ๐ซ kubelet
asks every few seconds
GET /healthz โ alive?
liveness probe
GET /readyz โ ready?
readiness probe
๐ fails ร3 โ RESTART
same pod, fresh container
โธ๏ธ fails โ NO traffic
out of the Service list, no restart
1
2
3
4
mixing the two up is one of the most common Kubernetes mistakes!
8 ๐ Requests & limits โ promised plates and capped seconds
Requests are reservations the scheduler counts; limits are hard caps with different penalties for CPU vs memory.
๐ Scheduler
the cook counting plates
๐ฅ๏ธ Node โ 2 CPU ยท 4 Gi
๐ช school-api โ req 100m / 128Mi
limit 500m / 256Mi
๐ช analytics โ req 100m / 128Mi
limit 500m / 256Mi
๐ฉ unreserved โ room for more pods
๐ฒ CPU over limit
โ throttled (slower)
๐ซ RAM over limit
โ OOMKilled ๐
1
places pods only where requests fit
2
3
9 ๐ Autoscaling โ the transport manager watches the buses
Above 70% average CPU it adds pods (max 5); when quiet it parks them (never below 2).
๐ metrics-server
measures pod CPU
๐งโ๐ผ HPA
target 70% ยท min 2 ยท max 5
Deployment
replicas: โ edited
๐ 1
๐ 2
๐ 3
๐ 4
1
2
85% โ scale up!
3
scale-up is fast ยท scale-down is slow on purpose (don't park the bus the second the rain stops)
10 ๐ซ Ingress โ one gate, routed by the signboard
One load balancer for everything; the URL path decides which Service the visitor reaches.
๐ Internet
parent's browser
๐ซ Main gate โ ALB
built by the controller
๐ชง path?
the signboard
โ๏ธ analytics svc
/analytics/*
โ๏ธ school-api svc
/* everything else
1
2
3
4
specific paths first (/analytics before /) ยท health-checks reuse lesson 07's /healthz ยท one gate = one bill + one TLS setup
11 โฝ Rollouts โ substitute one player at a time, keep the bench
A full team is always on the field; the old version stays benched for instant rollback.
โฑ๏ธ during rollout
๐ช v1 pod โ playing โ
๐ช v1 pod โ playing โ
๐ v2 pod โ warming up
1
maxSurge: 1 extra allowed
๐ readiness gate
v2 gets traffic ONLY
after /readyz says yes
2
โ
done โ all v2
old pods left one by one,
never below full team
3
๐ช old ReplicaSet v1 โ scaled to 0, kept on the bench
kubectl rollout undo = "come back on!" โ a 10-second rollback
4
12 ๐ Storage โ backpacks vanish, library shelves survive
A PVC gives disposable pods a durable shelf; this repo goes one further and rents the library (RDS).
๐ช postgres pod v1
๐ฅ dies (backpack gone)
๐ช postgres pod v2
new desk, same books
๐ PVC
"I claim 10 Gi of shelf"
๐ PV = EBS disk
outlives every pod
1
2
same claim โ same data
3
๐๏ธ RDS โ the rented library
what THIS repo uses (terraform/rds.tf)
4
rule of thumb: stateless pods in the cluster, state in managed services outside
13 ๐ข Under the hood โ what kubectl apply really does
Five office roles, one register, one endless loop: wish โ record โ reconcile โ run โ report.
๐ง kubectl
"I wish: 2 pods"
๐งโ๐ผ API server
the ONLY door
๐ etcd
the sacred register
๐ controllers
wish โ reality? fix it
๐๏ธ scheduler
picks the best node
๐งโ๐ซ kubelet
runs it on the node
1
2
wish written down
3
sees Deployment โ
creates Pods (unassigned)
4
assigns each pod
a node
5
6
5: kubelet pulls the image ๐ฑ, starts the container, runs the probes ๐ ยท 6: "running & ready" reported back โ kubectl get pods shows 2/2 ๐
14 ๐ค Bonus: CI/CD & GitOps โ the homework robot and the caretaker robot
CI tests & builds on every push; ArgoCD lives inside the cluster and keeps it matching the plan book (git).
๐งโ๐ป dev
git push
๐ฎ Robot 1 โ CI pipeline
โ
test โ ๐ฑ build โ ๐๏ธ push to ECR
โ โ๏ธ manual approval
๐ git repo โ the master plan
k8s/ manifests = single source of truth
๐ซ Kubernetes cluster
๐ค Robot 2 โ ArgoCD
lives INSIDE, no outside key
๐ช school pods
1
2
CI commits the new image tag
3
pulls & compares every ~3 min
4
4: sync + self-heal โ hand-edits get reverted, deploys = git commits, rollback = git revert ยท the book always wins ๐
15 ๐ซ๐ซ Bonus: Multi-AZ & the scaling ladder
Never seat the whole class in one building โ and climb the cheapest rung first on exam day.
๐ ALB โ stands outside all buildings
sends visitors wherever is healthy
๐ซ building A โ AZ a
๐ฅ๏ธ desk
๐ช api-1
๐ช analytics-1
๐ฅ๏ธ new desk
added by the
autoscaler
2
๐ซ building B โ AZ b
๐ฅ๏ธ desk
๐ช api-2 ยท ๐ช analytics-2
3
topology spread: copies across buildings โ one fire โ down
1
๐ช the ladder
1 HPA: more pods โ seconds
2 autoscaler: more desks โ minutes
3 spread: across buildings
4 PDB: never all away at once
Pending pods = kids standing โ
the autoscaler's signal
4
16 ๐ฉบ Debugging โ the nurse's triage chart
Whatever walks in: describe first, Events always, logs --previous for crash loops.
๐ค sick pod something is wrong ๐ฉบ the nurse asks: 1 describe โ EVENTS 2 logs --previous ยท 3 exec 1 Pending ๐ช โ no desk fits: requests? taints? cluster full? (L08 ยท L15 ยท L20) ImagePullBackOff ๐ฑ โ wrong label, missing tag, or no registry permission (AWS L05) CrashLoopBackOff ๐ฅ โ starts, dies, repeats: logs --previous first, then config (L06) OOMKilled ๐ซ / Service silent โ๏ธ โ limit hit, or selector โ labels: get endpointslices (L04) 2 match the symptom the drill never changes: describe โ logs โ events โ exec 3
17 ๐ชช RBAC โ hall passes
Roles are passes, bindings hand them over, ServiceAccounts are the robots' cards.
๐ฅ who person ยท group ยท ๐ค ServiceAccount (pod card) ๐ RoleBinding hands the pass over ๐ชช Role โ one room get/list pods in school ๐ซ ClusterRole โ whole building view ยท edit ยท admin ยท cluster-admin ๐๏ธ 1 2 the API server checks the pass on EVERY request โ no pass, no entry ยท test: kubectl auth can-i --as=โฆ 3
18 โฐ Jobs & CronJobs โ homework and the bell
The bell creates homework; homework creates a kid; the kid finishes and that's the point.
๐ CronJob schedule: 0 2 * * * suspend: true = off-switch ๐ Job tonight's homework backoffLimit: 2 retries ๐ช pod pg_dump โ upload then EXITS 0 1 on schedule 2 โ
Completed โ kept for autopsy, tidied by history limits ๐งน ยท fire one now: kubectl create job --from=cronjob/school-db-backup 3
19 ๐ซ๐ NetworkPolicies โ passing-notes rules
Default-deny first, then exactly the conversations the app needs.
๐ณ default every pod whispers to every pod โ even the DB 1 default-deny no notes at all (selects every pod) 2 allow exactly what's needed analytics โ api :3000 ยท gate โ apps 1 ๐ซ anything else note intercepted โ dropped silently 2 โ ๏ธ needs a CNI that enforces policies (Calico / VPC CNI switch) โ no enforcer = rules silently ignored: always TEST 3
20 ๐ซ Taints & affinity โ assigned seating
Signs on desks push away; chits permit; wishes attract; anti-affinity separates twins.
๐ GPU desk taint: gpu=true:NoSchedule the sign that repels ๐ฅ๏ธ normal desks no signs โ anyone sits ๐ค ML pod toleration ๐ซ + nodeAffinity: allowed AND attracted ๐ช ordinary pod no chit โ repelled โ 1 2 ๐ฏ anti-affinity: never both twins on one desk โ HA at desk level 3
21 ๐งฏ DaemonSets โ one on every floor
No replica count: the node list IS the count. New desk, new extinguisher, automatically.
๐งฏ DaemonSet one per desk, always โ no replica count: nodes ARE it ๐ฅ๏ธ desk 1 ๐ช apps + ๐งฏ ๐ฅ๏ธ desk 2 ๐ช apps + ๐งฏ ๐ฅ๏ธ NEW desk (autoscaler, L15) ๐งฏ appears by itself 1 2 you already run them: kube-proxy (L04's routing!) and the CNI live in kube-system as DaemonSets ยท log collectors next (L26) 3
22 ๐ท๏ธ StatefulSets โ desks with name plates
Sticky name, sticky drawer, ordered arrival โ the whole difference from a Deployment.
๐ท๏ธ StatefulSet named, ordered kids: postgres-0, then -1, then -2 ๐ช postgres-0 dies โ replacement has the SAME name ๐๏ธ PVC data-postgres-0 ITS OWN drawer โ survives the pod, always reattaches 1 2 โ๏ธ headless Service: reach postgres-0 BY NAME, no load-balancing ยท HA needs an operator (L25) โ production stance unchanged: rent the library (RDS, L12) 3
23 ๐ฝ๏ธ QoS & evictions โ who leaves first
BestEffort, then over-promise Burstable, then Guaranteed โ your requests ARE your ranking.
๐ฅ๏ธ desk under pressure memory running out โ kubelet must free space ๐ฅ BestEffort โ no requests at all EVICTED FIRST ๐ฅ Burstable โ requests < limits next (our pods live here) ๐ฅ Guaranteed โ requests == limits evicted LAST 1 2 ๐ฎ PriorityClass: system staff basically never leaves 3
24 ๐๏ธ Cluster upgrades โ renovating while open
Office first, then desk by desk: cordon, drain (PDBs on guard), replace, uncordon.
๐ข 1 office first EKS control plane โ one Terraform change ๐ง cordon no new kids ๐ drain PDB guards ๐ฝ๏ธ ๐ฅ๏ธ replace desk fresh EC2 + kubelet 1 โ
uncordon next classroom 2 ๐ถ skew rule: desks may trail the office, never lead ยท one minor at a time 3
25 ๐ค CRDs & operators โ new words for the office
A word in the register plus a robot who makes it true โ ArgoCD demystified.
๐ CRD teach the office a new word: kind: BackupPlan + grammar ๐ข office / etcd stores your wishes โ kubectl & RBAC just work ๐ค controller watches the word, reconciles forever โ L03's loop, your noun 1 2 CRD + controller + expertise = an OPERATOR ยท you've used them all along: ArgoCD's Application, cert-manager's Certificate, CloudNativePG's Cluster โ words plus robots ๐คฏ 3
26 ๐ Observability โ eyes on everything
Report cards (metrics), diaries (logs), alarm bells (alerts) โ and one screen for all of it.
๐ช pods expose /metrics numbers on every door ๐งฏ log collector DaemonSet (L21) ships diaries ๐ Prometheus scrapes + keeps history ๐ log store diaries outlive desks ๐บ Grafana one screen: metrics + logs ๐ Alertmanager rules ring the on-call phone 1 2 start with: is it up ยท is it erroring ยท is it slow ยท is the cluster healthy โ four questions, one dashboard 3
Start Lesson 01 โ
๐๏ธ Study plan (9 weeks)
๐ All 26 lesson diagrams
๐งช Quiz
โฎ๏ธ Before & trade-offs
Check my foundations first
๐ฑ Course 1: Docker & ECR
๐ค Course 3: ArgoCD