Inspect Pods and Container Logs

Learn to inspect pods and view container logs with kubectl in this Kubernetes for Python Developers tutorial — hands-on steps, troubleshooting, and what to study next.

Focus: inspect pods and container logs with kubectl

Sponsored

You've deployed your first pods, maybe even a Deployment, but when something goes wrong in your Python service — a 500 error, a slow response, a crash loop — you're staring at a black box. You can't SSH into a pod like a VM. You need a way to see inside. That's exactly what kubectl gives you: the power to inspect what's running, watch its health, and read the logs your Python code prints. With the right commands, you can turn cryptic failures into clear, actionable answers — and this lesson is your hands-on guide to doing exactly that with kubectl.

The problem this lesson solves

You've just deployed a Python Flask app to your cluster. It worked in Docker locally, but a few minutes later, your pods are in CrashLoopBackOff, or worse, they're running but every request returns a 500. Without a way to look inside, you're guessing. You restart pods, you redeploy — but the problem persists.

The core challenge: containers are ephemeral and isolated. You can't just hop into the virtual machine and check the process. But Kubernetes gives you a standard toolset for introspection. If you don't know these commands, you'll spend hours in the dark.

This lesson teaches you the essential kubectl commands to inspect pods and container logs with kubectl. You'll learn to check pod status, read stdout/stderr from your Python app, and run commands inside the container without leaving your terminal. The result: you'll diagnose issues in minutes, not hours.

Core concept / mental model

Think of your cluster as a hotel. Your pods are the rooms, and your Python application is the guest. You can't peek through the keyhole, but you have a front desk (the Kubernetes API) that can relay everything: the room's status (is the guest inside? are they causing trouble?), the messages they leave (logs), and even let you knock and have a conversation (exec into the container).

  • kubectl get lets you list rooms (pods) and their current status (Running, Pending, CrashLoopBackOff).
  • kubectl describe gives you a detailed report on a room: events, configurations, and why the guest might be disturbed.
  • kubectl logs fetches the written messages (stdout and stderr) that your Python app left behind.
  • kubectl exec lets you go into the room and do more, like checking environment variables or running a quick Python script.

This mental model helps: you're not guessing; you're using a structured API to ask the right questions of your cluster.

How it works step by step

Every kubectl command you run hits the Kubernetes API server, which then retrieves the info from the etcd database or the kubelet on the node. Here's the logical flow of inspecting:

  1. List your pods to see the actual state.
  2. Pick the pod you need to inspect, often by name or label.
  3. Describe the pod to get detailed status and recent events.
  4. Fetch logs from the container(s) inside the pod.
  5. Execute a command inside the container if you need more.

Each step is deliberate. You'll often start with get, narrow down with labels, then dive into describe and logs. This prevents you from wasting time on the wrong pod.

Hands-on walkthrough

Let's put this into practice. We'll assume you have a pod running a simple Python Flask app. If you don't have one, create it with the following manifest:

apiVersion: v1
kind: Pod
metadata:
  name: flask-pod
  labels:
    app: flask-demo
spec:
  containers:
  - name: flask
    image: python:3.11-slim
    command: ["sh", "-c"]
    args:
      - |
        echo "Container starting..." >> /proc/1/fd/1
        pip install flask --quiet
        echo "Flask installed" >> /proc/1/fd/1
        python -c "from flask import Flask; app = Flask(__name__)
@app.route('/')
def hello():
    return 'Hello, K8s!'
app.run(host='0.0.0.0', port=8080)" &
        sleep 3600

Pro tip: For a quick demo, you can also use kubectl run flask-demo --image=python:3.11-slim --command -- sleep 3600 — we'll practice logs with that too.

Step 1: See all pods

kubectl get pods

Expected output (similar):

NAME          READY   STATUS    RESTARTS   AGE
flask-pod     1/1     Running   0          5m42s

The READY column tells you if containers are up. If you see 0/1, something's wrong.

Step 2: Get detailed information

kubectl describe pod flask-pod

This prints a treasure trove: pod IP, node, labels, and — critically — the Events section at the bottom. That's where you see things like "Container image "flask" already present" or "Back-off restarting failed container" if there's a crash.

Step 3: Fetch logs

kubectl logs flask-pod

You'll see the output from your Python code:

Container starting...
Flask installed
 * Serving Flask app ''
 * Debug mode: off

But wait — what if your app writes to stderr? By default, kubectl logs shows both stdout and stderr combined from the container's terminal.

Step 4: Follow live logs

When your Python app is serving requests, you'll want to watch logs in real time:

kubectl logs -f flask-pod

Great for local debugging, but be careful in production — it blocks your terminal.

Step 5: Get logs from a previous instance

If your pod crashed and restarted, the logs from the previous attempt are still accessible:

kubectl logs flask-pod --previous

The --previous flag is gold when troubleshooting CrashLoopBackOff — you see the error that caused the crash!

Step 6: Run commands inside the container

kubectl exec -it flask-pod -- python -c "import flask; print(flask.__version__)"

You might see:

2.3.3

Or use an interactive shell:

kubectl exec -it flask-pod -- /bin/bash

Now you're inside the container — inspect files, run diagnostics, and exit with exit.

Multi-container pods

If a pod has multiple containers, you must specify which one:

kubectl logs flask-pod -c flask-container
kubectl exec -it flask-pod -c sidecar-container -- /bin/sh

Compare options / when to choose what

Not every inspection method suits every situation. Here's a decision table:

Situation Best command Why
Quick status check kubectl get pods Fast overview of cluster health
Pod failing to start kubectl describe pod <name> Shows events and reason for failure
App is running but misbehaving kubectl logs <pod> See what your Python code says
Crash loop — need old logs kubectl logs <pod> --previous Get logs from before the crash
Need to debug internals kubectl exec -it <pod> -- /bin/sh Interactive access to container FS
Watch logs live during testing kubectl logs -f <pod> Real-time output for development

Pro tip: For multiple pods (like a Deployment), use kubectl logs deployment/<name> — it fetches logs from one pod in that deployment automatically.

Troubleshooting & edge cases

"Error from server: Internal error occurred: log line too long"

If a Python app prints massive JSON logs, kubectl truncates. Solution: - Use --tail=50 to get the last 50 lines. - Write logs to a file inside the container and kubectl cp it out.

"No logs found" but you know your app prints

  • Check if the app is writing to stdout or a file. Containers only see stdout/stderr unless you configure logging.
  • Your Python logging handler may buffer; force flush with flush=True.

Pod shows CrashLoopBackOff

  1. Run kubectl logs --previous to get the crash cause.
  2. Common causes: wrong ENV variables, missing dependencies, or bad port binding.

exec can't find bash

Many slim images (like python:3.11-slim) don't have bash. Use /bin/sh instead.

Permission denied on exec

You need pods/exec RBAC permission. As a developer, you usually have it — but in a strict cluster, ask your admin.

What you learned & what's next

You now have a solid toolkit to inspect pods and container logs with kubectl. You can:

  • List and describe pods to diagnose status issues.
  • Read and follow logs from your Python containers.
  • Access previous logs after a crash.
  • Execute commands inside containers for deeper debugging.
  • Handle multi-container pods and common edge cases.

These skills are the foundation for the next step in your Kubernetes journey: debugging with kubectl port-forward or managing deployments. With logs and exec, you can confidently move to orchestrating more complex apps.

Callout: The more you practice, the faster you'll debug. Next lesson, you'll learn how to forward a local port to a pod so you can test your Python API directly.

Practice recap

Create a simple Python pod that writes a log line every second, then use kubectl logs -f to watch it live. Then intentionally cause a crash (e.g., exit with code 1) and practice kubectl logs --previous to see the error. Try multi-container eventually.

Common mistakes

  • Running kubectl logs on a multi-container pod without -c — you get an error asking you to specify a container.
  • Using --previous on a freshly deployed pod that never crashed — returns no output, which confuses beginners.
  • Trying to exec with bash in a container that only has sh — leads to a "no such file" error.
  • Ignoring kubectl describe events — the fastest way to see why a pod isn't starting is in the Events section.

Variations

  1. Use kubectl logs deployment/my-app to get logs from a random pod in a Deployment.
  2. Use kubectl logs -l app=flask-demo to fetch logs from all pods matching a label.
  3. For centralized logging, use kubectl logs for ad-hoc debugging, and EFK stack (Elasticsearch, Fluentd, Kibana) for production.

Real-world use cases

  • A Python service crashes on startup in production; you use kubectl logs --previous to see the traceback and fix a missing environment variable.
  • Your Flask app is slow under load; you exec into the pod and run top to check for CPU/memory bottlenecks.
  • You're debugging a multi-container pod with a sidecar; you use kubectl logs -c to isolate which container is failing.

Key takeaways

  • Start with kubectl get pods to see the big picture, then drill down with describe.
  • kubectl logs reads stdout/stderr from your container — make sure your Python code logs to stdout.
  • For crash loops, always check kubectl logs --previous — it contains the last error before the crash.
  • kubectl exec lets you run commands inside the container for deeper inspection.
  • In multi-container pods, always specify -c <container-name>.
  • Use kubectl describe events to find the root cause of scheduling or image pull 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.