Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes

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

Sponsored

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 describe as the crash report and logs as the black box flight recorder. Use describe first to understand the cluster's view; then use logs to 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 of kubectl describe pod <name>.
  • Container states: Waiting, Running, Terminated. describe shows the reason and message for each (e.g., CrashLoopBackOff with “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: - StatusContainer StatesTerminated / 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 check kubectl logs --previous when debugging restarts.
  • Describing a Deployment instead of a Pod: kubectl describe deployment gives 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 logs on a pod that never started: If the pod is Pending or ErrImagePull, there are no logs. Use describe first.

Variations

  • Using kubectl logs -f to tail logs in real time during debugging.
  • Using stern or kubetail for streaming logs from multiple pods matching a label selector.
  • Using kubectl describe on 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, check logs, 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 logs on a pod that is Pending or CrashLoopBackOff but never ran — logs are empty because the container never started. Use kubectl describe first to see the error.
  • Describing a Deployment instead of its Pods — kubectl describe deploy shows the desired spec, not the runtime state of the pods. Always describe the individual pod.
  • Forgetting --previous when a pod restarted — the current logs are from the new container; the error is in the previous one. Use kubectl logs pod-name --previous.
  • Missing multi-container pod logs — without -c container-name, kubectl logs defaults to the first container, which may be an init container or a sidecar you didn't intend to examine.

Variations

  1. Use kubectl logs -f pod-name -c container to tail logs live during a debugging session.
  2. Stream logs from multiple pods with tools like stern or kubetail, which aggregate logs across pods matching a label selector.
  3. 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 pod of one replica reveals a liveness probe timeout on a healthy endpoint.
  • A cronjob pod is stuck in ImagePullBackOffkubectl describe pod shows the exact registry 404, prompting a fix to the image tag.
  • A multi-container pod fails silently — using kubectl logs -c sidecar reveals the sidecar can't connect to the database, not the main app.

Key takeaways

  • kubectl describe provides the full object spec, status, and events — the first tool for any Kubernetes failure.
  • kubectl logs gives application-level output; use --previous for restarted containers.
  • Always start with kubectl describe on the resource that is failing (pod, service, PVC) before checking logs.
  • Events in describe often contain the root cause — image pull errors, probe failures, scheduling constraints.
  • For multi-container pods, specify -c <container> in both describe and logs to target the correct container.
  • Combine kubectl describe with kubectl logs --previous to solve 90% of runtime and startup failures.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.