Incident Handling — On-Call Playbook & Real Scenarios›02 · Where to start troubleshooting

Lesson 02 of 19 · The on-call playbook: from page to prevention

Where to start troubleshooting

Where to start when everything looks broken: scope the problem first (one user, pod, node, zone or everything), check what changed, walk the request path outside-in, and test cheap hypotheses one at a time, writing down what you've ruled out.

Practitioner
Key wordstroubleshooting methodscopeblast radiuswhat changedoutside-inhypotheseseliminationkubectl eventscompare good vs bad
1 · Scope it first One user or everyone? client vs service One pod or all replicas? code/config vs platform One node or many? host vs cluster One zone/site or all? infra vs global What changed? deploys, config, infra, time 2 · Walk the path outside-in DNS · CDN · WAF · load balancer Ingress / gateway Service → endpoints Pods: status, logs, events Nodes: pressure, kubelet, runtime Control plane · network · storage · cloud
Scope first, then walk the path outside-in.

Don't start with your favourite tool

Under pressure, people jump to what they know best: "let me check the database", "must be DNS". Sometimes that's right. Often it wastes the most important 20 minutes. A method beats instinct.

If the lights go out, you don't start by unscrewing one bulb. You look: is it just this room, the whole house, or the whole street? If the whole street is dark, it's not your bulb. Then you follow the path: street → fuse box → room switch → bulb.

Step 1: scope the blast radius

Question If only part is broken… …it points to
One user or everyone? One user/customer Client, account, data, a specific route
One pod or all replicas? One pod That pod's node, data, or a bad instance
One version or all? New version only The release
One node or many? One node Disk, network, kubelet, runtime on that node
One zone/site or all? One zone Infrastructure, network, a dependency in that zone
Everything All of it Shared dependencies: DNS, control plane, identity, network, a global config push

Step 2: what changed?

Line up the start of the symptom with recent changes (lesson 01): deploys, config, node upgrades, certificates, cron jobs, cloud events. A strong correlation is the fastest lead.

Step 3: walk the path outside-in

Follow the user's request and find the first hop that fails:

  1. DNS, CDN/WAF, load balancer (is traffic arriving?)
  2. Ingress/gateway (status codes, access logs)
  3. Service → endpoints (are there ready pods?)
  4. Pods (status, restarts, logs, events)
  5. Nodes (pressure conditions, kubelet, runtime, kernel messages)
  6. Control plane, network, storage, cloud provider
$ kubectl get events -A --sort-by=.lastTimestamp | tail -30
$ kubectl get pods -A | grep -vE 'Running|Completed'
$ kubectl get nodes -o wide
$ kubectl describe node <node> | sed -n '/Conditions/,/Addresses/p'

Step 4: hypotheses, one at a time

  • Write the hypothesis down: "The new image can't reach the database because the secret changed."
  • Pick the cheapest test: check the secret's timestamp; exec into a pod and connect.
  • Record the result, especially what's ruled out. It prevents going in circles and helps whoever joins later.
  • Change one thing at a time, and note each change in the timeline.

Step 5: compare good and bad

A healthy pod next to a broken one, a healthy node next to a failing one, yesterday's config next to today's: diff is one of the best troubleshooting tools there is.

$ kubectl get pod good-pod -o yaml > good.yaml && kubectl get pod bad-pod -o yaml > bad.yaml && diff good.yaml bad.yaml

Try it: find it by method

  1. In a lab cluster, ask a colleague to break one thing silently (a NetworkPolicy, a taint, a wrong Service selector, a full disk on one node).
  2. Before touching anything, write the scope table for the symptom.
  3. Walk the path outside-in and note the first failing hop.
  4. Write two hypotheses, test the cheaper one first, and record eliminations.
  5. Afterwards, compare your time with a "just start poking" attempt on a different break.

Going deeper: better starting points

  • Build a service overview dashboard per critical journey: edge errors, latency, saturation, recent deploys (annotations).
  • Keep a dependency map so "everything is broken" quickly narrows to shared dependencies (see SRE & Production Incident Response, lesson 06).
  • Use traces and correlated logs to jump straight to the failing hop (see Observability with OpenTelemetry, lesson 05).

Recap

  • Scope first: user, pod, version, node, zone, everything.
  • Ask what changed, and correlate with the start time.
  • Walk the path outside-in and find the first failing hop.
  • One hypothesis at a time, cheapest test first; write down what's ruled out; compare good vs bad.

This site is a public version of my personal engineering knowledge hub. It intentionally excludes confidential company information and internal operational details.