Free lesson · CKAD Prep Program · Module 4: Observability and maintenance
Collect and Read Logs with Intent
Logs are the application's testimony; events are the cluster's. Knowing which to read first, and how to slice container output across replicas and restarts, is half of all debugging.
10 min reading
Objectives
- Pull logs per container, past crashes included, without flailing
- Follow multi-pod output with labels instead of pod names
- Say what belongs in stdout versus what belongs in events
- Structure log lines so the next debug starts with a filter, not reading
Why this matters
CrashLoopBackOff pages get answered from logs, not from redeploying hopefully. The difference between a ten-minute fix and an hour is usually tooling: previous-container logs for the crash that already rotated, label-selected streams for the fleet view, and timestamps that correlate with events. The CKAD assumes fluency here and spends its difficulty elsewhere.
Concepts
kubectl logs <pod> -c <container> reads one container; --previous reads the last dead instance, which is where crash causes live. --since plus --timestamps bound and correlate output. -l <selector> with --all-containers (or per-container) streams the fleet: one command across replicas beats N tabs. --tail keeps huge outputs manageable.
Stdout discipline decides everything downstream: one event per line, timestamps included, severity prefixed, request IDs propagated. Multi-line stack traces belong on single logical lines (JSON logging) or they shatter across collectors. Events (kubectl get events --sort-by) carry cluster-side facts the app cannot know: scheduling, pulls, probes, evictions. Read events for platform causes, logs for application causes, and check both before theorizing.
Worked example
A CrashLooping worker, read properly in order:
kubectl get pods -l app=worker # Restart count climbing
kubectl logs worker-xxx --previous | tail -30 # the crash itself
kubectl logs -l app=worker --all-containers --since=10m | grep -i error
kubectl get events --field-selector involvedObject.name=worker-xxxThe previous-container log names the exception; the fleet grep says whether all replicas share it; the events say whether the platform contributed (OOMKilled, failed mount, image pull). Three commands, one theory, then the fix.
Exam notes
Logs die with the pod unless collected: previous-container is one restart deep, not archival. Sidecar or node-level collection is the real answer for retention, and questions distinguish the two scopes. And --previous on a first-run pod errors plainly: no previous instance means no previous logs, not a broken command.
Quick check
A 4-question self-check. Your answers stay on your device, are never stored or sent. Only a passing score (for example 3 of 4) is saved, and only to unlock lesson progress: at least 3 correct is required before a lesson counts as complete. It never counts toward any certification assessment.
Lesson feedback
No published feedback yet.
Log in and complete the lesson to leave feedback.
Exercise
A fictional 3-replica API throws errors on one replica only. Give the exact command sequence that finds the failing replica, reads its current plus previous logs, and checks whether events implicate the platform. State what each output would show in both the app-bug and the OOMKilled cases.
Pass criteria
Sequence uses label selection plus previous plus events; both cases predicted with the distinguishing output (shared versus single stack trace, exit code 137 plus OOMKilled event).