Module 16 ยท Lesson 16.1
Capstone: Multi-Tier App
This is the course's one integrative project: a realistic three-tier app, built from nothing but things you've already learned, wired together the way a real small production app actually looks.
Capstone: three tiers, one boundary
The architecture, and where each piece came from
- frontend (nginx) โ a Deployment serving static content from a ConfigMap (Module 5), with liveness/readiness probes (Module 6) and proper resource requests/limits for a sane QoS class (Module 6).
- api (standing in for real backend logic) โ a Deployment reading database credentials from a Secret (Module 5), fronted by a Service (Module 4), scaled by a HorizontalPodAutoscaler (Module 14), with its own probes and resources.
- db (redis) โ a StatefulSet with a PersistentVolumeClaim via
volumeClaimTemplates(Module 7), so it keeps its data and identity across restarts the way a Deployment's interchangeable pods never would. - An Ingress (Module 8) routes
/to the frontend and/apito the api tier โ one entry point, two backends, the pattern you practiced with Traefik. - A NetworkPolicy (Module 11) enforces that only the
apitier โ not the frontend, not anything else in the cluster โ can reach the database on its port. This is real enforcement on this cluster, not a paper rule: the grader actually tries the forbidden connection and confirms it's blocked, the same way you verified it in Module 11.
Why this shape, not something simpler
Every one of these pieces exists because of a real production concern you already have the vocabulary for: Secrets because credentials shouldn't be baked into images or plain env strings in your YAML; a StatefulSet because a database restarting onto a fresh, empty volume would be catastrophic; an HPA because traffic isn't flat; a NetworkPolicy because "the database is only reachable by the one service that's supposed to talk to it" is a basic blast-radius argument, not paranoia. None of this is Kubernetes trivia โ it's the actual shape of "does this survive a bad day in production," which is the whole point of everything from Module 3 onward.
Grading
Unlike every other lab, this one's check.sh grades 8 independent
dimensions separately and reports partial credit โ you'll see some PASS
and some FAIL as you work through it, not an all-or-nothing wall. That
mirrors how you'll actually debug a real multi-tier app: one thing wrong
at a time, verified independently, not "redeploy everything and pray."
๐งช Lab: lab-33-capstone
Preview onlyGoal
Fix a realistic multi-tier app โ frontend, API, database โ that's wired together but has six separate, independent bugs spread across six different concerns you've learned across the whole course. Nothing here is new; it's all a recombination of Modules 3-14.
The app: a frontend (nginx, serving a ConfigMap-backed page) behind an
Ingress, an api Deployment (also nginx, standing in for real backend
logic) with an HorizontalPodAutoscaler, and a db (redis) StatefulSet
with its own PersistentVolumeClaim, fed credentials from a Secret. A
NetworkPolicy is supposed to make sure only the api tier can reach the
db tier.
check.sh grades 8 independent dimensions and tells you exactly which ones
are still broken โ you don't have to fix everything before you start
seeing some PASS lines.
Tasks
- Apply the starting manifests:
kubectl apply -f manifests/ - Run the check โ read every FAIL line, each names the specific problem:
make check LAB=lab-33-capstone(or the lab page's Run Check button) - Work through the dimensions one at a time. Suggested order (easiest
diagnosis first): probes โ autoscaling โ ingress โ
secrets โ resources-and-qos โ network-policy. For each one:
kubectl describethe relevant object (pod, hpa, ingress, statefulset) โ the Events section or the object's own status almost always names the exact mismatch, same structured-debugging approach from earlier break-fix labs.- Fix the YAML under
manifests/, thenkubectl apply -f manifests/again. - For network-policy specifically: there's no existing policy to
fix โ you have to write one from scratch (a
default-deny+ a scopedallow from app=apiis the pattern from Module 11).
- Re-run the check after each fix and watch dimensions flip to PASS.
Check
All 8 dimensions must show PASS for the overall verdict to be PASS.
This lab runs against a real local Kubernetes cluster with an automated grader โ clone the repo and run make start to do it for real.
๐ Quiz
1. The api Deployment's pods are stuck 0/2 Ready, and api-svc has zero Endpoints. The HPA also can't scale anything. Are these the same bug?scenario
2. The HPA's own `kubectl describe` shows a condition like 'FailedGetScale' naming a Deployment that doesn't exist. What's the actual bug?scenario
3. A pod that mounts a Secret key which doesn't exist on the Secret object shows what kind of failure?
4. After writing a NetworkPolicy for the db tier, `kubectl exec` from a random non-api pod can still reach db:6379. The policy object applied without error. What's the most likely mistake?scenario
5. You fix every FAIL line check.sh reported, but it still prints an overall FAIL. What should you do?scenario
Progress isn't saved in this preview โ run the course locally to track completion and grade labs for real.