Skip to content

Catalog

All 30 stages in one place — filter by difficulty or verification status, or search. Click any row for the stage's concept note and the diff the reference solution adds at that stage.

  • 30Stages
  • 30✓ Verified
  • 10Hard
  • 1Course
What "verified" means: ✓ Verified — the stage has a reference solution checked in that passed stages 1..N cumulatively against a live kind cluster in CI. CI re-verifies every snapshot on each push, so a drifted assertion fails the build rather than the reader.
Stage Level What it teaches
1. Find the cluster Easy Before a client can do anything it has to answer "which server, as whom?", and the answer is never hardcoded.
2. Choose a context Easy A context is a named triple: a cluster, a user, and optionally a namespace.
3. Ask the server what it is Medium This is the first request that leaves your machine, and it deliberately goes through the discovery client rather than a typed one.
4. List the pods Easy The first real read. A typed clientset gives you a method per resource — CoreV1().Pods(ns).List(...) — which returns *corev1.PodList with real Go fields.
5. Choose a namespace Medium Namespace resolution has three steps and the middle one is the trap: --namespace, then whatever the current context carries, then "default".
6. Print a table Medium A table is a user interface, and the property that makes it one is that the columns line up when the names do not.
7. Humanise the age Medium The API stores a creation timestamp; a person reading a hundred rows wants "2d".
8. Print the object as JSON Medium -o json is not "your table, as JSON". It is the API's own object, verbatim — apiVersion, kind, metadata, spec, status, managedFields and all.
9. Print the object as YAML Medium Same object, different serializer — and the way you get there matters.
10. Look everywhere at once Medium -A is not a client-side filter and it is not a loop over namespaces.
11. Ask for one object Easy Get and List are different endpoints with different failure modes, and the difference is the lesson. A List of an empty namespace succeeds and returns nothing.
12. Ask what the server serves Medium This is the request that makes a client general. Nothing in your program knows what a Pod is: the server reports its groups, the versions in each, and the resources in those —…
13. Resolve any spelling Hard po, pod, pods, Pod, pods.v1. — five spellings of one thing, and the API accepts exactly one of them in a URL.
14. Get anything at all Hard This is the largest single step in the course: your program stops being a pod client. The dynamic client speaks in GVRs and unstructured.
15. Wider columns Easy -o wide adds the columns that only make sense for a particular resource: a Pod's node and IP, a Service's cluster IP and ports.
16. Filter by label Medium Labels are the identifying metadata everything in Kubernetes coordinates through: a Service finds its pods by selector, a Deployment owns its ReplicaSets by selector.
17. Filter by field Medium Field selectors look like label selectors and are a different axis.
18. A stable order Easy The API returns items in whatever order the storage layer hands them over.
19. Keep watching Hard A watch is a long-lived HTTP response the server keeps appending to, one JSON event per change: ADDED, MODIFIED, DELETED, BOOKMARK, ERROR.
20. Delete an object Easy The first write, and the lesson is that delete is asynchronous. The call returns when the server has accepted the request and marked the object — not when it is gone.
21. Create from a manifest Hard A manifest is self-describing: it carries apiVersion and kind, which is why kubectl create -f needs no flag saying what is in the file.
22. Apply, not create Hard Apply is not "create if missing, update if present". It is a different claim: these fields should look like this, and I am the one saying so.
23. Two managers, one field Hard When your apply sets a field another manager already owns, the server answers 409 Conflict and changes nothing.
24. Change one field Medium Patch is the smallest write verb: the body names only what changes, so nothing has to be read first and there is no resourceVersion to conflict on.
25. Scale through a subresource Medium /scale is a subresource: a separate endpoint on the same object, with its own tiny schema.
26. Describe one object Medium Describe answers a different question from get, and the difference explains the format.
27. Attach its events Hard Events are the cluster's explanation of why, and the surprise is that they are not part of the object they describe.
28. Stream a container's logs Hard There is no Log object to Get. pods/log is a subresource that returns a stream of bytes, and with --follow it never ends — which is why its client-go signature could not have…
29. Run a command inside Hard Exec needs several independent byte streams at once — stdin, stdout, stderr and a terminal-resize channel — multiplexed over a single connection. Ordinary HTTP/1.
30. Forward a local port Hard Port-forward is the same upgrade as exec put to a different use: a local listener whose connections are tunnelled, one stream pair per forwarded port, through the apiserver to the…

▶ Run it

From the repo root: — it verifies every stage up to this one, so passing means nothing earlier broke.