๐Ÿ“– Read-only preview โ€” lessons, diagrams, and quizzes only. The hands-on labs, live grading, and progress tracking require running the real course locally against a Kubernetes cluster.Run it locally โ†’

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

NetworkPolicy: api-onlyusersIngresstraefik โ€” / and /apifrontendConfigMap + probesapiSecret + HPA + probesdb (redis)StatefulSet + PVC
Ingress routes '/' to the frontend and '/api' to the API tier. Only the API tier is allowed through the NetworkPolicy boundary around the database โ€” everything else, including the frontend, is denied.

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 /api to the api tier โ€” one entry point, two backends, the pattern you practiced with Traefik.
  • A NetworkPolicy (Module 11) enforces that only the api tier โ€” 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 only

Goal

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

  1. Apply the starting manifests: kubectl apply -f manifests/
  2. 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)
  3. 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 describe the 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/, then kubectl 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 scoped allow from app=api is the pattern from Module 11).
  4. 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.