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.
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.
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:
- The cluster is created with
kind create cluster --name kubestronaut-devand stays up for the whole capstone (minikube is a fine substitute; translate the commands yourself). - The workload is kubestronaut-tracker — a small HTTP API with
GET /health,GET /certs,POST /certs/:id/complete, andGET /progress, backed by a single-replica Postgres instance you stand up alongside it. It is a real, backend-persisted version of the same idea this course's own lesson checklists use — except those save your progress inlocalStoragein your browser, and this one is a service you build, deploy, and operate yourself. Its image isregistry.internal/kubestronaut-tracker:TAG, pushed to a throwaway local registry:docker run -d -p 5000:5000 --restart=always --name registry registry:2, withregistry.internalpointed at127.0.0.1in your hosts file. - Namespaces split cleanly in two:
trackerhosts the application itself, andplatformhosts every add-on — Argo CD, the Argo Rollouts controller, istiod, Kyverno, kube-prometheus-stack, the OpenTelemetry Collector, and a local Backstage instance. Every part keeps this split consistent. - The repo is a single git repo,
kubestronaut-tracker, that starts bare — app code, aDockerfile, one passing test, nothing else — and grows exactly one new top-level path per part.
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=trueEvery 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.
| # | Part | Pairs with | Done when |
|---|---|---|---|
| 1 | GitOps Foundation — 🤖 Recon | CGOA — 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. |
| 2 | Progressive Delivery — 🦫 Benny & 🐘 Ellie | CAPA — Argo Rollouts, 18% of the exam | a healthy build promotes through every canary step unattended, and a broken one aborts back to stable with nobody touching a button. |
| 3 | Mesh & Policy — 🦉 Owl & 🐢 Timmy | ICA + KCA | plaintext traffic to a mesh pod is refused, and a manifest with :latest or a root user is rejected at admission, not just logged. |
| 4 | Observability — 🐘 Ellie | OTCA + PCA | your 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. |
| 5 | The Portal — 🦋 Mira | CBA | kubestronaut-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.
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.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.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.Synced and Healthy, and your manual edit is reverted within one sync interval without you re-applying anything./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.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.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.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.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.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."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.
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.
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.
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
- Part 1 — GitOps Foundation. The two-part test: a manual
kubectl editto 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. - 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.
- 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.
- 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.
- The Backstage catalog entry from Part 5 — its
catalog-info.yamlcarries 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.