Hands-On Labs · The Capstone

Build your own cert tracker, start to finish

Reading about GitOps, a mesh, an admission policy and a telemetry pipeline is not the same as watching your own cluster do all four at once. This hub is where that gap closes. You'll build kubestronaut-tracker — a small internal API that tracks your own progress through the sixteen-exam ladder — from a bare git repo holding nothing but application code, through five connected parts, to a service any platform team would recognize: delivered by GitOps, rolled out progressively, wrapped in a mesh, gated by policy, watched end to end, and listed in a developer portal. Each part states exactly what "done" looks like before you start it. If you only have an afternoon, the fast path below still gets you real reps across all five.

☺ Explain it like I'm 10

Movie astronauts just climb into the rocket and fly. Real ones spend years first learning to build and check every system that keeps the rocket alive — the fuel line, the guidance computer, the oxygen gauge. This lab is that shift for you. Instead of only reading about the systems a real platform team runs, you build a tiny one yourself: a small app delivered automatically from a git repo the way real mission software is, protected by rules a strict inspector would insist on, watched by gauges the way real telemetry is watched, and finally listed in a directory anyone on the team could find it in. Five systems, one small app, built with your own hands instead of imagined from a diagram.

🦫Your host for this track: Benny the Beaver — the builder. He hands each part to the right specialist (Recon, Timmy, Owl, Ellie, Mira) and won't call a part "done" until its own done-when line is actually true. The whole crew is on call.
⚠ Before you start

Every part below is local and throwaway — nothing here touches production or costs real money. You'll want Docker (or Podman), a local Kubernetes cluster via kind (minikube works too — translate the commands), kubectl, helm, the argocd and istioctl CLIs, and git. If kubectl still feels shaky, skim The Kubernetes Baseline You Need first — this capstone assumes it, not teaches it. Commands, chart versions, and each project's own domain weights drift over time — always check current docs and each certification's own page before you register for anything. Tear everything down when you're done (kind delete cluster --name kubestronaut-dev, docker rm -f registry) and nothing lingers.

The world you're building

☺ Like you're 10: Before any building starts, here's the map: one cluster, one small app, two drawers to keep things tidy in, and one repo that grows a new room every part.

The hub you're reading and all five parts build inside one continuous project, so nothing you set up in Part 1 goes stale by Part 5. Here is the whole world, once, so you never have to re-derive it:

kubestronaut-dev (kind cluster)
├── namespace: platform          # Argo CD, Argo Rollouts controller, istiod, Kyverno, kube-prometheus-stack, OTel Collector, Backstage…
├── namespace: tracker            # the kubestronaut-tracker Deployment/Rollout, Service, Postgres, ServiceMonitor…
└── (git) kubestronaut-tracker/
    ├── app/, tests/, Dockerfile        # the bare repo you start with
    ├── deploy/argocd/                  # Part 1 — GitOps foundation (Argo CD Application)
    ├── deploy/rollout/                 # Part 2 — progressive delivery (Argo Rollouts canary)
    ├── mesh/, policy/                  # Part 3 — mesh & policy (Istio, Kyverno)
    ├── observability/                  # Part 4 — observability (Prometheus, Grafana, OTel)
    └── catalog-info.yaml, portal/      # Part 5 — the portal (Backstage entity + TechDocs)

One manifest ties the whole loop together from the very first part — everything from here on is Argo CD noticing that this repo changed and reconciling your cluster to match it:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: kubestronaut-tracker
  namespace: platform
spec:
  project: default
  source:
    repoURL: https://github.com/you/kubestronaut-tracker.git
    targetRevision: main
    path: deploy/argocd
  destination:
    server: https://kubernetes.default.svc
    namespace: tracker
  syncPolicy:
    automated:
      prune: true      # remove anything deleted from git
      selfHeal: true    # revert anything changed out-of-band
    syncOptions:
      - CreateNamespace=true
◆ Key idea

Every part opens by stating exactly what state your cluster and repo are in when you arrive (inherited from the part before) and what state they're in when you leave (handed to the next one). If a part ever feels like it's starting from nothing, re-read its opening paragraph — you're missing something the part before was supposed to leave behind.

The five parts

☺ Like you're 10: Five chapters of the same story. Each one hands the next chapter a repo and a cluster that are a little more finished than the ones before.

Work them in order — each part hands the next one a piece it depends on, and each pairs with real hands-on reps toward specific project certifications this course covers, at the tool that certification actually tests.

kubestronaut-tracker (git) the source of truth ① GitOps Foundation Argo CD syncs the repo pairs: CGOA ② Progressive Delivery Rollouts canary 20% → 50% → 100% pairs: CAPA ③ Mesh & Policy Istio strict mTLS + Kyverno enforce pairs: ICA + KCA ④ Observability Prometheus, Grafana, OTel Collector pairs: OTCA + PCA ⑤ The Portal Backstage catalog entry + TechDocs pairs: CBA catalog-info.yaml describes the service and links back to this repo One app. One loop. Five specialists, in order.
#PartPairs withDone when
1GitOps Foundation — 🤖 ReconCGOA — GitOps Principles 30% · Patterns 20%a manual kubectl edit to a watched resource is reverted within one sync interval, and a resource deleted from git is pruned live.
2Progressive Delivery — 🦫 Benny & 🐘 EllieCAPA — Argo Rollouts, 18% of the exama healthy build promotes through every canary step unattended, and a broken one aborts back to stable with nobody touching a button.
3Mesh & Policy — 🦉 Owl & 🐢 TimmyICA + KCAplaintext traffic to a mesh pod is refused, and a manifest with :latest or a root user is rejected at admission, not just logged.
4Observability — 🐘 EllieOTCA + PCAyour dashboard shows real traffic on all four golden signals, an alert fires on an injected fault, and one trace shows a request's full path across the mesh.
5The Portal — 🦋 MiraCBAkubestronaut-tracker appears in your Backstage catalog with correct ownership, its TechDocs render, and a teammate could reach its dashboard from the catalog page alone.

Deep-dive the concept behind any part via its linked lesson before or after you build — the lesson explains why, the part makes you prove it works: GitOps Philosophy, Service Mesh Architecture, Policy-as-Code Philosophy, The OpenTelemetry Data Model, The Prometheus Model, and The Backstage Portal Model.

The fast path — for an afternoon

☺ Like you're 10: No time for five deep parts? Here's the one-page summary of the whole story, still worth doing.

The five parts are the deep version of this track — real manifests, real breakage, real triage. If you only have an afternoon, or you want one condensed pass before you sit any of these exams, work this shorter seven-item version instead. It touches every part at a lighter depth, using the exact same kubestronaut-tracker/kubestronaut-dev world as the parts above, so nothing you build here is wasted if you come back and go deep later.

0 / 7 fast-path items complete
0Stand up the ground — 🦉 Professor Owl
Install Docker, kind, kubectl, helm, the argocd and istioctl CLIs, and git. Create the cluster with kind create cluster --name kubestronaut-dev. Start a throwaway local registry (docker run -d -p 5000:5000 --name registry registry:2) and point registry.internal at 127.0.0.1 in your hosts file. Initialize the kubestronaut-tracker repo with a minimal app (GET /health, GET /certs), a Dockerfile, and one passing test — nothing else yet.
Done when: kubectl get nodes shows a Ready node, your local registry answers curl localhost:5000/v2/_catalog, and docker build && docker run serves /health on your laptop.
1A repo Argo CD actually watches — 🤖 Recon
Install Argo CD into platform. Apply the Application manifest above, pointing at deploy/argocd in your repo, with prune and selfHeal both true. Push a first commit with a working Deployment, Service, and Postgres StatefulSet for kubestronaut-tracker under that path and watch Argo CD bring it up on its own. Then break it on purpose: kubectl edit the Deployment's replica count by hand.
Done when: the Application shows Synced and Healthy, and your manual edit is reverted within one sync interval without you re-applying anything.
2Ship the canary, not the whole fleet — 🦫 Benny & 🐘 Ellie
Convert the Deployment to an Argo Rollouts canary: 20% → 50% → 100%, with a pause at each step and an AnalysisTemplate that queries a small Prometheus instance for the error rate on /certs and aborts automatically if it trips. Ship a good build through and watch it promote unattended. Ship a build that 500s on POST /certs/:id/complete and watch the rollout abort back to stable.
Done when: a healthy build promotes through every step on its own, and a broken build is rolled back before it reaches 100% — no manual intervention either way.
3Wrap it in a mesh and a gate — 🦉 Owl & 🐢 Timmy
Install Istio, enable sidecar injection on tracker, and set a STRICT PeerAuthentication so plaintext traffic is refused. Add Kyverno in enforce mode (not audit): block :latest image tags, require the sidecar-injection label, require non-root. Try to apply a manifest that violates one rule and watch admission refuse it outright.
Done when: a plaintext curl to a mesh pod fails, and a manifest with :latest or a root user is rejected at admission with a Kyverno policy message, not a silent pass-through.
4Put gauges on the whole thing — 🐘 Ellie
Install kube-prometheus-stack into platform. Add a ServiceMonitor for kubestronaut-tracker, a Grafana panel per golden signal, a PrometheusRule alerting on error rate, and an OpenTelemetry Collector pipeline exporting a trace for a request as it crosses the mesh. Inject a fault — drop the memory limit until it OOMKilleds, or point it at a bad DB host — and triage with your own dashboard and trace.
Done when: your dashboard shows real traffic on all four golden signals, the alert fires on the injected fault, and a single trace shows the request's full path across the mesh.
5List it where anyone can find it — 🦋 Mira
Write a catalog-info.yaml describing kubestronaut-tracker as a Backstage Component with correct ownership and a link to your Grafana dashboard, and wire up TechDocs from a docs/ folder in the repo. Register the entity in a locally-running Backstage instance.
Done when: the service shows up in the catalog with the right owner, its TechDocs render without a build error, and a teammate could find the dashboard link from the catalog page alone.
CapstoneAsk your own tracker how you're doing — 🦫 Benny & the whole crew
Call GET /progress on your own live kubestronaut-tracker and compare it, honestly, to your real study progress on the sixteen-exam ladder. Then count what this build actually earned you reps in: seven of the nine project certs this course covers — CGOA, CAPA, ICA, KCA, OTCA, PCA, CBA — not CCA or LFCS, which this stack never touches.
Done when: you can name, from your own running system and not from memory, which cert each part just gave you real hands-on reps toward — and which two this build never touched.
Concept: The Project Certifications — this is where every part above gets counted.
🦫 Benny's-eye view

"Whichever version you did — the fast path or the five deep parts — don't just tell me it worked. Ask the tracker. If GET /progress can't answer honestly, something above still needs fixing, not a better story about it. I've broken a staging cluster exactly once building this pattern, and the fix both times was the same: trust what the running system says, not what I remember building."

What you'll have built

☺ Like you're 10: By the end, your laptop holds a small working version of the whole mission-control room this course keeps describing — the reconciler, the launch pad, the shield, the gauges, and the directory.

Finish the five parts (or the fast path) and you'll have hands-on reps across seven of the nine project certifications this course covers — CGOA, CAPA, ICA, KCA, OTCA, PCA, and CBA — each one earned from a real cluster doing the real thing the exam asks about, not from a definition you memorized. Domain names and weights above come from each project's published curriculum at the time this page was written; always verify current weights, format, and duration on that certification's own page — starting with The Project Certifications — before you register for anything. Two certs this build deliberately never touches: CCA (Cilium's eBPF data plane, a different networking layer from the Istio mesh built here) and LFCS (the Linux Foundation's performance-based exam on the operating system underneath the cluster, not the workloads running on it). Both are honestly out of scope for an application-level capstone — see their own pages for how to build reps toward them instead.

⚖ Mostly multiple-choice, but still worth building — Seven of the nine certs this capstone earns you reps toward are closed-book, knowledge-based exams: no lab, no terminal, no cluster to fix under a clock. So why build any of this? Because their scenario questions are written by people who assume you've done exactly what these five parts walk you through — a question about what selfHeal: true actually does reads very differently once you've watched Part 1 revert your own manual edit. Closed-book doesn't mean untested; it means the test happens at your own terminal, before you ever see the multiple-choice version of it.

🦫 Benny's challenge · going further

Already comfortable? Level up any part: add Cilium alongside Istio and compare their policy models, closing your CCA gap; harden the kind node itself with the systemd and cgroup habits LFCS tests, closing that gap too; fold in Argo Workflows and Argo Events so your pipeline itself runs as a DAG instead of a CI YAML file; sign your image with cosign and make Kyverno reject anything unsigned, not just anything on :latest; or add a Backstage software template so a teammate can spin up their own tracker instance with one form, not a cloned repo.

🎬 At Mission Control
🦊

Foxy: Five parts feels like a lot of ceremony for one small tracker app. Can't I just skim the fast path and call it a day?

🦫

Benny the Beaver: You can, Foxy, and you'll still walk away with real reps. But the fast path is the map — the five parts are the actual territory, with a rollout that really aborts and a policy that really refuses something.

👺

Gizmo the Gremlin: Or — just skip the mTLS step. It's plaintext on a local kind cluster, who's even listening? 🤑

🐢

Timmy the Turtle: Nice try, Gizmo. The point of Part 3 isn't the local cluster, it's proving you know how to make the mesh refuse something before it's ever near production. Skip it here and you'll skip it for real later.

🐘

Ellie the Elephant: And once Part 4 is running, none of that is a guess anymore. I can show you the exact request, the exact span, the exact metric that proves it.

🦋

Mira the Butterfly: Which is exactly what Part 5 puts in front of anyone who goes looking — the dashboard, the docs, the owner, all from one catalog entry. That's the difference between a demo and a service someone else can actually run.

🦉

Professor Owl: One repo, five parts, one loop. Go build it.

🐢 Timmy's checkpoint

1. Which part proves your GitOps loop is actually self-healing, and what two-part test proves it? 2. Which part stops a broken build from ever reaching 100% of traffic without a human pressing anything? 3. In Part 3, what's the practical difference between Kyverno running in "audit" mode and running in "enforce" mode, and which one does this capstone insist on? 4. Of the nine project certs this course covers, which two does this capstone never touch, and why not? 5. Once Part 5 is finished, where does the whole build point back to, so a teammate could find it without asking you directly?

Check your answers
  1. Part 1 — GitOps Foundation. The two-part test: a manual kubectl edit to a resource Argo CD watches gets reverted within one sync interval without you re-applying anything, and a resource you delete from the git repo gets pruned live from the cluster.
  2. Part 2 — Progressive Delivery. The canary's AnalysisTemplate checks error rate at each traffic step and auto-aborts back to the last stable version the moment it trips — nobody has to notice or press a rollback button.
  3. Audit mode only logs a policy violation and lets the resource through anyway; enforce mode actually refuses the request at admission. This capstone insists on enforce — a policy nobody actually blocks anything with isn't proving the thing Part 3 is meant to prove.
  4. CCA (Cilium's eBPF data plane — a different networking layer from the Istio mesh this build uses) and LFCS (the Linux Foundation's performance-based exam on the operating system underneath the cluster, not the application-level workloads this capstone builds). Both are honestly out of scope for an app-level build like this one.
  5. The Backstage catalog entry from Part 5 — its catalog-info.yaml carries the service's ownership, its TechDocs, and a link straight to the live Grafana dashboard, so anyone on the team can self-serve the whole picture from one page.