kubectl describe and logs debug
Learn to debug Kubernetes pods and deployments using kubectl describe and logs. This practical lesson covers core concepts, step-by-step walkthrough, troubleshooting, and edge cases for effective diagnostic workflows.
Focus: debug with kubectl describe and logs
Your pod is stuck in CrashLoopBackOff, a deployment is showing zero ready replicas, or an Ingress returns 503 seemingly at random. Without a systematic way to inspect what's happening inside the cluster, you're left guessing — and guessing wastes time. In this lesson, you'll learn to use kubectl describe and kubectl logs, the two commands that turn Kubernetes black boxes into transparent systems you can debug with confidence.
The problem this lesson solves
Kubernetes abstracts away the complexity of scheduling and running containers. But when something goes wrong — a pod fails to start, a service maps to no endpoints, or a persistent volume claim stays Pending — that abstraction becomes a wall. Standard commands like kubectl get pods only show status, not why. Without digging deeper, you’re flying blind.
kubectl describe fetches the full object spec, status conditions, events, and error messages. kubectl logs gives you the container's stdout/stderr. Together they replace guesswork with data. This lesson teaches you exactly how to use them to pinpoint failures — from image pull errors to liveness probe failures.
Core concept / mental model
Think of Kubernetes objects as state machines. Every object — Pod, Deployment, Service, PVC — has:
- Spec: the desired state you declared in YAML
- Status: the current state as observed by the control plane
- Events: a chronological log of operations and failures on that object
kubectl describe prints all three. It is the single source of truth for why an object is in its current state.
kubectl logs is your runtime telemetry. While describe tells you what Kubernetes thinks is wrong, logs tell you what your application says is wrong — errors from your code, connection failures, missing config files.
Pro tip: Think of
describeas the crash report andlogsas the black box flight recorder. Usedescribefirst to understand the cluster's view; then uselogsto inspect the application's behaviour.
Key definitions
- Events: Pod-level or object-level messages such as
FailedPullImage,BackOff,Liveness probe failed. They appear at the bottom ofkubectl describe pod <name>. - Container states:
Waiting,Running,Terminated.describeshows the reason and message for each (e.g.,CrashLoopBackOffwith “back-off 5s restarting failed container”).
How it works step by step
Step 1: Get a list of objects
Always start with kubectl get to identify the name and namespace of the object you need to debug.
kubectl get pods -n my-app
Output:
NAME READY STATUS RESTARTS AGE
backend-7d4c9f8c-4k2mz 0/1 CrashLoopBackOff 5 3m
Step 2: Describe the failing pod
kubectl describe pod backend-7d4c9f8c-4k2mz -n my-app
Focus on two sections:
- Status → Container States → Terminated / Waiting (the Reason and Message)
- Events (usually at the bottom): look for Failed, Error, BackOff, Unhealthy.
Example snippet:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Killing 6m38s kubelet Container backend failed liveness probe, will be restarted
Warning Unhealthy 6m38s (x3 over 7m) kubelet Liveness probe failed: Get "http://10.1.0.25:8080/health": dial tcp 10.1.0.25:8080: connect: connection refused
Step 3: Check logs (if container ever started)
kubectl logs backend-7d4c9f8c-4k2mz -n my-app
If the pod restarted multiple times, use --previous to see the logs of the last terminated container:
kubectl logs backend-7d4c9f8c-4k2mz -n my-app --previous
Hands-on walkthrough
Scenario 1: Image pull failure
First, create a pod with a wrong image name:
# bad-image.yaml
apiVersion: v1
kind: Pod
metadata:
name: bad-image
spec:
containers:
- name: app
image: nginx:nonexistent
kubectl apply -f bad-image.yaml
kubectl describe pod bad-image
Output snippet:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 12s default-scheduler Successfully assigned default/bad-image to node-1
Warning Failed 10s kubelet Failed to pull image "nginx:nonexistent": rpc error: code = NotFound desc = manifest for nginx:nonexistent not found: manifest unknown: manifest unknown
Warning Failed 10s kubelet Error: ErrImagePull
Normal BackOff 4s kubelet Back-off pulling image "nginx:nonexistent"
Diagnosis: The image tag is wrong. Fix the YAML and re-apply.
Scenario 2: CrashLoopBackOff from a runtime error
Create a pod that runs a command that fails immediately:
# crash.yaml
apiVersion: v1
kind: Pod
metadata:
name: crashy
spec:
containers:
- name: fail
image: busybox
command: ["sh", "-c", "exit 1"]
kubectl apply -f crash.yaml
kubectl describe pod crashy
Notice the container state: Terminated with Reason: Error and Exit Code: 1.
Now check the logs (even a failed container may produce stdout before exiting):
kubectl logs crashy
Likely empty — the application exited immediately. Use kubectl logs --previous if the container restarted.
Scenario 3: Liveness probe failure
Deploy a pod with a liveness probe that points to a non-existent endpoint:
# probe-fail.yaml
apiVersion: v1
kind: Pod
metadata:
name: probe-fail
spec:
containers:
- name: web
image: nginx
livenessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 2
periodSeconds: 3
kubectl apply -f probe-fail.yaml
sleep 15
kubectl describe pod probe-fail
Look for:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning Unhealthy 12s kubelet Liveness probe failed: HTTP probe failed with statuscode: 404
Normal Killing 12s kubelet Container web failed liveness probe, will be restarted
Fix: Either create the /healthz endpoint in your app, or change the probe path to / or a valid route.
Compare options / when to choose what
| Command | Best for | Limitations |
|---|---|---|
kubectl describe |
Understanding cluster-level state, events, spec vs status | Does not show application output (stdout/stderr) |
kubectl logs |
Application runtime errors, debug output | Requires container to have emitted output; no events |
kubectl logs --previous |
Inspecting logs of a crashed/restarted container | Shows only the last terminated container |
kubectl get events |
Global view of all cluster events (across namespaces) | More noise; less targeted than per-pod describe |
Rule of thumb:
1. Start with kubectl describe on the failing resource.
2. If the container shows CrashLoopBackOff or Error, run kubectl logs (with --previous if needed).
3. For probe or network issues, check both the pod and the service endpoints (kubectl describe endpoints).
Troubleshooting & edge cases
Edge case 1: Pod in Pending state
kubectl describe might show:
Events:
Warning FailedScheduling 15s default-scheduler 0/1 nodes are available: 1 Insufficient cpu.
Solution: Increase node resources or reduce resource requests in the pod spec.
Edge case 2: Init container failure
If you have init containers, describe the pod and look for the init container's container state:
Init Containers:
init-myservice:
State: Terminated
Reason: Error
Exit Code: 1
Use kubectl logs pod-name -c init-myservice to see the init container’s logs.
Edge case 3: Multi-container pod
Always specify the container name with -c <name>:
kubectl logs my-pod -c sidecar -n my-ns
kubectl describe pod my-pod | grep -A 5 "Container ID"
Common mistakes
- Forgetting
--previous: After a container restarts, current logs are empty. Always checkkubectl logs --previouswhen debugging restarts. - Describing a Deployment instead of a Pod:
kubectl describe deploymentgives the deployment spec, not the running pod's events. Describe the pod directly. - Ignoring Events: Many developers only look at the status field. The Events section often contains the exact error message from kubelet.
- Using
kubectl logson a pod that never started: If the pod isPendingorErrImagePull, there are no logs. Usedescribefirst.
Variations
- Using
kubectl logs -fto tail logs in real time during debugging. - Using
sternorkubetailfor streaming logs from multiple pods matching a label selector. - Using
kubectl describeon other objects:kubectl describe svc,kubectl describe pvc,kubectl describe ingress— all expose events that may reveal misconfigurations.
What you learned & what's next
You now have a repeatable debugging workflow for Kubernetes. You can:
- Use kubectl describe to inspect an object's full state, see container reasons, and read the event timeline.
- Use kubectl logs (with --previous) to extract application output from running or crashed containers.
- Combine both to diagnose common failures: image pull errors, probe failures, scheduling issues, and init container crashes.
In the next lesson, you'll extend this diagnostic technique to Services and Ingress — debugging why your app is reachable inside the cluster but not outside, or why a load balancer returns 502s. These same describe and logs commands will be your first tools there too.
Debugging Kubernetes isn't magic — it's knowing where to look. Start with
describe, checklogs, and you'll solve 90% of issues in minutes.
Practice recap
Deploy a pod with a wrong image tag and a liveness probe to a non-existent path. Use kubectl describe to identify both issues, then fix the YAML and re-apply. Practice kubectl logs --previous on a pod that crashes immediately (e.g., exit 1). Document the event messages you see.
Common mistakes
- Running
kubectl logson a pod that isPendingorCrashLoopBackOffbut never ran — logs are empty because the container never started. Usekubectl describefirst to see the error. - Describing a Deployment instead of its Pods —
kubectl describe deployshows the desired spec, not the runtime state of the pods. Always describe the individual pod. - Forgetting
--previouswhen a pod restarted — the current logs are from the new container; the error is in the previous one. Usekubectl logs pod-name --previous. - Missing multi-container pod logs — without
-c container-name,kubectl logsdefaults to the first container, which may be an init container or a sidecar you didn't intend to examine.
Variations
- Use
kubectl logs -f pod-name -c containerto tail logs live during a debugging session. - Stream logs from multiple pods with tools like
sternorkubetail, which aggregate logs across pods matching a label selector. - Investigate other resource types:
kubectl describe svc,kubectl describe endpoints,kubectl describe pvc— each reveals object-level events that may explain misconfigurations.
Real-world use cases
- A new deployment shows 0/3 ready replicas —
kubectl describe podof one replica reveals a liveness probe timeout on a healthy endpoint. - A cronjob pod is stuck in
ImagePullBackOff—kubectl describe podshows the exact registry 404, prompting a fix to the image tag. - A multi-container pod fails silently — using
kubectl logs -c sidecarreveals the sidecar can't connect to the database, not the main app.
Key takeaways
kubectl describeprovides the full object spec, status, and events — the first tool for any Kubernetes failure.kubectl logsgives application-level output; use--previousfor restarted containers.- Always start with
kubectl describeon the resource that is failing (pod, service, PVC) before checking logs. - Events in
describeoften contain the root cause — image pull errors, probe failures, scheduling constraints. - For multi-container pods, specify
-c <container>in bothdescribeandlogsto target the correct container. - Combine
kubectl describewithkubectl logs --previousto solve 90% of runtime and startup failures.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.