Kubernetes8 min read

kubectl logs: Debugging Pods with Logs, Timestamps, and Previous Instances

Beyond `kubectl logs pod-name` — using timestamps, previous instances, and multi-container patterns to diagnose real failures.

kubectldebuggingkubernetes logspod logscontainer troubleshooting

Every Kubernetes user knows `kubectl logs pod-name`. It's the first command you reach for when a pod misbehaves. But the default output is often useless — it dumps the entire log buffer, ignores timestamps, and hides logs from crashed containers. Over time, I've built a set of patterns that turn `kubectl logs` from a firehose into a precision tool.

This post covers the flags and workflows I use daily to debug pod failures, with real examples from incidents in production.

The Basics (and Why They Fail)

Running `kubectl logs my-pod` prints the entire log of the first container. If the pod restarted, you get the current (possibly empty) log. If there's a CrashLoopBackOff, you see nothing useful because the container keeps dying before writing logs. The default output also lacks timestamps, making it impossible to correlate with other metrics or events.

lightbulb

Always use `--timestamps` when debugging time-sensitive issues. It adds RFC3339 timestamps to each line, which you can feed into tools like `sort` or `jq` for cross-pod correlation.

Getting Logs from a Crashed Container

When a pod is in CrashLoopBackOff, the current container is either restarting or hasn't written any logs yet. The logs you need are in the *previous* instance. The `--previous` flag retrieves them.

Using --previous to inspect logs from a terminated container.
# Get logs from the last run of a crashed container
kubectl logs my-pod --previous

# Combine with timestamps for precise timing
kubectl logs my-pod --previous --timestamps

# Tail only the last 50 lines to avoid noise
kubectl logs my-pod --previous --tail=50

The Case of the Silent CrashLoopBackOff

  1. 14:02Deployment rolled out a new image tag.
  2. 14:03Pods enter CrashLoopBackOff. `kubectl logs` shows empty output.
  3. 14:05Engineer runs `kubectl logs --previous` and sees Java OOM error in the logs.
  4. 14:07Rollback to previous image resolves the issue.

Lesson

Without `--previous`, the OOM error would have been invisible. The pod's current instance had no logs because it crashed before the logger could flush.

Multi-Container Pods: The -c Flag Is Not Optional

If your pod has multiple containers (e.g., an app container and a sidecar), `kubectl logs` defaults to the first container listed in the pod spec. That might be the sidecar, not the main app. Always specify `-c`.

Targeting specific containers with the -c flag.
# List containers in a pod
kubectl get pod my-pod -o jsonpath='{.spec.containers[*].name}'

# Get logs from a specific container
kubectl logs my-pod -c app

# Follow logs from both containers in separate terminals
kubectl logs my-pod -c app -f
kubectl logs my-pod -c sidecar -f
warning

Don't forget init containers! They have their own flag: `--init-container`. Without it, `kubectl logs` ignores init container output entirely.

Streaming, Tailing, and Since — Controlling the Firehose

When following logs with `-f`, you often don't want to replay the entire buffer. Combine `--tail` with `-f` to start from the last N lines and then stream new ones. The `--since` flag is useful for time-boxed queries.

Controlling log volume with --tail, --since, and --since-time.
# Stream only new logs after the last 100 lines
kubectl logs my-pod --tail=100 -f

# Logs from the last 5 minutes
kubectl logs my-pod --since=5m

# From a specific time (RFC3339 format)
kubectl logs my-pod --since-time="2025-03-15T10:00:00Z"

I once debugged a slow memory leak by comparing logs from `--since=1h` across three replicas. Without `--since`, I'd have been scrolling through gigabytes of data.

Putting It All Together: A Real Debugging Workflow

Here's a typical sequence I use when a pod starts failing health checks:

  1. 1Check pod status: `kubectl get pod my-pod` — note the restart count.
  2. 2If restarts > 0, grab previous logs: `kubectl logs my-pod --previous --timestamps | head -100`.
  3. 3If no previous logs, stream current logs with `--tail=50 -f` and trigger a manual request to the pod's endpoint.
  4. 4If the pod has sidecars, use `-c` to identify which container is failing.
  5. 5Use `--since=10m` to isolate logs around the failure time.
  6. 6Redirect to a file: `kubectl logs my-pod --timestamps --tail=-1 > pod.log` for offline analysis.
Practical one-liner for offline analysis.
# One-liner to capture full log with timestamps from a crashed container
kubectl logs my-pod --previous --timestamps --tail=-1 > crash.log

# Then grep for errors with line numbers
grep -n "ERROR\|Exception" crash.log
73%

of Kubernetes incidents involve at least one pod restart — where --previous is the only way to see the root cause.

These patterns have saved me hours of frustration. The key is to treat `kubectl logs` not as a simple dump, but as a query language for container output. Combine flags, use timestamps, and always check the previous instance when things crash.

Frequently asked questions

How do I get logs from a container that already crashed?

Use `kubectl logs pod-name --previous`. This retrieves the logs from the previous instance of the container, which is exactly what you need when a pod is in CrashLoopBackOff.

How can I see logs from a specific container in a multi-container pod?

Use the `-c container-name` flag, e.g., `kubectl logs pod-name -c sidecar`. If you omit it, `kubectl` defaults to the first container, which may not be the one you want.

Can I stream logs with a delay or only new entries?

Yes, combine `--tail=N` with `-f` to stream only the last N lines plus new ones. For example, `kubectl logs pod-name --tail=50 -f` avoids dumping the entire log history.

How do I get logs from init containers?

Use `--init-container` flag: `kubectl logs pod-name --init-container init-container-name`. Without it, init container logs are not shown.