Files
ced4568andClaude Sonnet 5 7f6e1857c0 feat(curriculum): Phase 6C module upgrades, security assessment bank, ROOT 11 orientation
Upgrades six PARTIAL modules to the gold-module standard (lesson/demonstration/
knowledge-check/guided-exercise/lab(s)/reflection), preserving every existing lab
activity_id and scenario_id: root-06-m03 (jobs/cronjobs/daemonsets), root-07-m04
(ingress/networkpolicy), root-07-m02 (configuration/secrets, converted in place
from a bare 5-lab bank), root-09-m02 (serviceaccounts/rbac), root-09-m03
(network/supply-chain security), root-10-m03 (troubleshooting framework).

root-05-m01 (20-task kubectl-fluency bank) gets a minimal bookending lesson +
reflection rather than a full redesign, since each task already carries its own
explanation. root-12-m01, root-capstone-m01, and root-09-m04 are promoted to
READY via documented exceptions (no new activities) where adding one would
misrepresent their intentional design.

Wires a new rootnode-security-assessment (exam, 60min, hint_policy disabled)
using the existing Phase 3B assessment engine: 3 required hands-on CORE
scenarios + 4 random-draw pools covering SecurityContext, RBAC, network
policy, and the 7 previously-unwired CKS MCQs. Wires the previously-unwired
readiness-probe-task scenario as an OPTIONAL practice lab in root-10-m01,
using the existing is_required model.

Adds root-11-m01-devops-platform-thinking — an honest, lesson-only ROOT 11
orientation module naming DevOps/platform engineering practices already
exercised in ROOT 05-10/12, explicit that GitOps/CI-CD/IaC/observability need
lab infrastructure this platform doesn't yet provide. No fake labs.

Adds infra/scripts/validate-course-content.js: cross-checks the DB against
scenario/content files for duplicate ids, orphans, invalid references, cycles,
sequence collisions, instructor-notes leakage, and (new) self-paced content
deferring explanation to a live instructor. 0 errors against the resulting
22 courses/modules, 163 activities, 98 scenario files.

No application code changed — every gap was satisfiable with existing tables
(course_modules, module_activities, assessment_definitions) and the existing
content-delivery pipeline.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 11:20:17 -05:00

73 lines
3.2 KiB
Markdown

# Demonstration: Tracing a Request Through Ingress
## The setup
An Ingress `web-ingress` routes `app.example.com/` to Service `web-svc`, which fronts a
Deployment `web-app`. Nothing works yet from outside the cluster — let's see why, step by step.
## Step 1: is the Ingress object even doing anything?
```
$ kubectl get ingress web-ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
web-ingress traefik app.example.com 80 2m
```
`ADDRESS` is empty. On a real cluster, this column fills in once the Ingress controller has
actually processed the object and assigned it a reachable address — an empty address after a
couple of minutes is the first sign to check the controller itself, not your YAML.
## Step 2: is the controller running at all?
```
$ kubectl get pods -n kube-system -l app.kubernetes.io/name=traefik
NAME READY STATUS RESTARTS AGE
traefik-7d8f9c6b5d-abcde 1/1 Running 0 10d
```
Running fine — so the ADDRESS delay in this case is transient, not a missing controller. (If
this returned no Pods at all, THAT would be the actual root cause — no controller means no
Ingress object ever gets acted on, exactly like the demonstration in ROOT 07's Ingress lesson
described.)
## Step 3: once ADDRESS populates, does the route actually work?
```
$ kubectl get ingress web-ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
web-ingress traefik app.example.com 10.0.1.50 80 3m
$ curl -H "Host: app.example.com" http://10.0.1.50/
<html>...web-app's real response...</html>
```
Success — but notice the `-H "Host: app.example.com"` header. Ingress routes by HOSTNAME, not
just by IP — hitting the Ingress controller's address WITHOUT the matching Host header would
route differently (or not at all), because that's literally what the Ingress rule is matching
on.
## The general shape
Symptom (nothing reachable from outside) has at least three DIFFERENT possible layers: the
Ingress object itself, the controller processing it, and the Service/Pod chain underneath it
(already covered in ROOT 07's Services module). Check them in that order — Ingress ADDRESS,
then controller health, then the underlying Service — rather than guessing at DNS or firewall
issues first.
## Instructor Notes
**Demo script:** If a real Ingress controller is available in the demo environment, run this
live including the Host-header nuance — students are frequently surprised that `curl <ip>`
alone doesn't work the way they expect.
**Approximate timing:** 8-10 minutes live; 5-7 minutes self-paced.
**Common misconception to preempt:** students often expect an Ingress's IP/address to work like
a Service's ClusterIP (reachable directly, no extra header needed). Reinforce that Ingress
routing is fundamentally HOSTNAME/PATH-based, which is exactly what makes one Ingress able to
route many different domains through one entry point.
**Optional extension:** ask what would happen if TWO Ingress objects both claimed the same host
+ path — a good forward pointer to why Ingress configuration conflicts are a real operational
concern on a shared cluster, without needing to build a hands-on lab around it here.