Skip to content

Declare the state, then watch the loop fight you.

Kubernetes is taught as a field reference, and the fields are not the hard part. The hard part is a control loop nobody watches: what the ReplicaSet controller does when readiness never goes true, what the scheduler does when your requests do not fit, and when exactly traffic stops arriving at a pod that is shutting down.

Valid, idiomatic, accepted by the apiserver.
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 25% # replicas: 4
readinessProbe:
httpGet: { path: /, port: 8080 }
periodSeconds: 5
What the loop did with it
0.0s apply deployment/checkout accepted, resourceVersion 8841
0.4s ScalingReplicaSet checkout-7d4f → 1
0.4s Killing checkout-9b21-x7k grace 30s
1.1s GET /checkout 503 no endpoints
2.6s Started checkout-7d4f-q2m
3.0s Ready checkout-7d4f-q2m
3.2s GET /cart 500 not actually ready
3.4s GET /checkout 200

Every failed request there carries the reason it failed, stamped at the moment it was emitted rather than guessed at afterwards — which is what makes this gradeable instead of a simulation toy. The defect is not in the syntax. It is in the interaction between a controller, a probe and a clock, and no amount of reading the manifest reveals it. So there is a model of the loop here.

Nine tracks

  • Desired and observed

    Who are you actually arguing with?

  • Pods and the kubelet

    What is the kubelet doing with this right now?

  • Probes

    Which of the three did you mean?

  • Rollouts

    What will this change cost in failed requests?

  • Traffic and endpoints

    When exactly does traffic stop arriving at this pod?

  • Scheduling

    Why is this pod still Pending?

  • Pressure

    Is this slow, or is it being held back?

  • Disruption

    What happens to this service at two in the morning?

  • Reading a generated manifest

    What will this rollout cost, before you run it?

Everything you do here stays in this browser.Part of liter8.sh