Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes

Monitor pod CPU and memory usage

Learn how to monitor pod CPU and memory usage in Kubernetes. This lesson covers essential metrics, hands-on steps, troubleshooting, and what to study next.

Focus: monitor pod CPU and memory usage

Sponsored

You've deployed a pod, but how do you know if it's using too much CPU or leaking memory? Without monitoring, your cluster is a black box — you won't notice a runaway container until users start seeing errors or the node runs out of resources. This lesson gives you the practical commands and mental model to monitor pod CPU and memory usage in real time, so you can troubleshoot issues before they escalate.

The problem this lesson solves

Kubernetes schedules pods onto nodes, but it doesn't automatically tell you how those pods are consuming resources. A single misbehaving container can starve other pods of CPU cycles or push a node into memory pressure, causing evictions and downtime. Without monitoring:

  • You can't detect memory leaks during development.
  • You can't verify that resource requests and limits are properly set.
  • You can't diagnose why a pod is restarting (OOMKilled) or running slowly.

This lesson gives you the foundational skill to monitor pod CPU and memory usage using kubectl and Kubernetes-native metrics, so you can keep your cluster healthy and responsive.

Core concept / mental model

Think of Kubernetes metrics like a car's dashboard gauges. The CPU gauge shows engine load — how hard the processor is working. The memory gauge shows fuel consumption — how much RAM is being used. Just as you'd glance at your dashboard while driving, you should monitor pod CPU and memory usage to ensure your application isn't overstraining its resources.

Key definitions:

  • CPU — measured in cores (or millicores, where 1000m = 1 core). A pod can burst up to its CPU limit, but if it exceeds the limit, it's throttled.
  • Memory — measured in bytes (Ki, Mi, Gi). If a pod exceeds its memory limit, it gets OOMKilled (Out Of Memory killed) and restarted.
  • Metrics Server — the cluster component that collects resource usage data from kubelets and exposes them via the Kubernetes API. Without it, kubectl top commands won't work.

Pro tip: Even if your cluster doesn't have the Metrics Server installed, you can still use kubectl describe pod or kubectl logs to get partial insight, but kubectl top is the standard tool for real-time usage.

How it works step by step

Step 1: Ensure the Metrics Server is running

The Metrics Server is the backbone of the kubectl top command. It scrapes CPU and memory metrics from each node's kubelet every 15 seconds.

Check if it's installed:

kubectl get pods -n kube-system | grep metrics-server

If you see no results, install it:

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

Step 2: View CPU and memory for pods

Once the Metrics Server is running, the simplest way to monitor pod CPU and memory usage is:

kubectl top pods

This shows every pod in the default namespace with its current CPU and memory usage. For a specific pod:

kubectl top pod <pod-name>

Step 3: Understand the output

Example output:

NAME                      CPU(cores)   MEMORY(bytes)
my-app-6b8f9c9c7d-abc12   50m          128Mi
  • 50m (millicores) — the pod is using 5% of one CPU core (since 1000m = 1 core).
  • 128Mi — the pod is using 128 mebibytes of RAM.

Step 4: Watch pods in real time (like top)

To refresh the data every few seconds (similar to the Linux watch command):

watch -n 2 kubectl top pods

This updates every 2 seconds, letting you see spikes as they happen.

Step 5: Monitor all namespaces

By default, kubectl top only shows the current namespace. To see all pods across the cluster:

kubectl top pods --all-namespaces

Or, for a specific namespace:

kubectl top pods -n my-namespace

Hands-on walkthrough

Let's simulate a pod that uses resources so you can practice monitoring pod CPU and memory usage.

Step 1: Deploy a stress-test pod

Create a file named stress-pod.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: stress-test
spec:
  containers:
  - name: stress
    image: polinux/stress
    command: ["stress"]
    args: ["--cpu", "2", "--vm", "1", "--vm-bytes", "256M", "--timeout", "60s"]

Apply it:

kubectl apply -f stress-pod.yaml

Step 2: Watch resource usage in real time

Open another terminal and run:

watch -n 2 kubectl top pod stress-test

You'll see CPU usage spike near 200% (meaning 2 cores) and memory usage around 256Mi.

Step 3: Check node-level usage too

Sometimes you need to see which node is overloaded:

kubectl top nodes

Step 4: Clean up

Delete the pod:

kubectl delete pod stress-test

Pro tip: The stress tool is perfect for testing resource boundaries. Use it in development to confirm your resource requests and limits are both accurate and sufficient.

Compare options / when to choose what

Tool Granularity Real-time? Use Case
kubectl top pods Per-pod Yes (poll every 2-15s) Quick diagnostics, manual checks
kubectl top nodes Per-node Yes Check node health and capacity
kubectl describe pod Per-pod with events Near real-time See OOMKilled or throttling events
kubectl logs Per-container Streamed Debug memory leaks or CPU-bounded code
Metrics Server API Raw JSON via /apis/metrics.k8s.io Yes Custom dashboards and automation

When to choose kubectl top: You need a fast, CLI-based check during development or incident response.

When to use kubectl describe pod: You see a pod restarting (OOMKilled) and want to know why.

When to integrate with Prometheus/Grafana: For historical analysis, alerting, and long-term capacity planning.

Troubleshooting & edge cases

Problem: kubectl top returns "error: metrics not available yet"

Cause: The Metrics Server is installed but hasn't collected data yet (needs ~15 seconds after startup).

Fix: Wait a few seconds and retry. If it persists, check the Metrics Server logs:

kubectl logs -n kube-system -l k8s-app=metrics-server

Problem: Metrics Server won't start (x509 certificate errors)

Cause: In some clusters (like kubeadm), the Metrics Server by default uses HTTPS with internal certificates, but may not trust the kubelet's self-signed certificate.

Fix: Edit the Metrics Server deployment to add the --kubelet-insecure-tls flag:

kubectl edit deployment metrics-server -n kube-system

Then add - --kubelet-insecure-tls to the container args.

Problem: A pod shows 0 CPU or memory usage

Cause: The pod has just been created or is in a CrashLoopBackOff state. kubectl top only shows running containers.

Fix: Use kubectl get events --sort-by='.lastTimestamp' to see the crash reason, then check kubectl describe pod <pod-name> for the Last State field.

Edge case: Throttled but not OOM

If a pod's CPU usage is capped at its limit (e.g., limit is 500m and usage is 500m), kubectl top will show the limit, but you won't see if the pod is waiting for CPU. Check kubectl describe pod for "Throttle" events.

What you learned & what's next

In this lesson, you learned how to monitor pod CPU and memory usage using kubectl top, understand the metrics showing millicores and mebibytes, and troubleshoot common issues like missing Metrics Server or OOMKilled events. You now have the core skill to:

  • Explain the core idea behind monitoring pod resource usage.
  • Complete a practical exercise using a stress pod to observe real-time metrics.

As a next step, you can explore setting resource requests and limits for your pods, or moving to a production-grade monitoring stack like Prometheus and Grafana. The next lesson in this track covers configuring resource limits so your pods are guaranteed resources and never over-consume.

Keep this kubectl top command in your back pocket — it's your first line of defense when a pod looks slow or unresponsive.

Practice recap

Create a new pod with the polinux/stress image that uses

bash kubectl run stress-test --image=polinux/stress -- --cpu 1 --vm 1 --vm-bytes 128M --timeout 30s

Then, while it runs (it lasts 30 seconds), run kubectl top pod stress-test every 3 seconds using watch. Notice how CPU and memory change. As an extra challenge, add a resource request and limit to the pod YAML and see how it affects the metrics.

Common mistakes

  • Running 'kubectl top' before the Metrics Server is installed — the command will fail with 'metrics not available yet'.
  • Confusing 'CPU(cores)' as a percentage of a single core instead of millicores — 1000m equals one full core, not 100%.
  • Assuming 'kubectl top' shows historical data — it returns only current usage, so you need to poll with 'watch' to see trends.
  • Forgetting to check the Metrics Server pod logs when it fails to start — often it's a TLS certificate issue that needs the '--kubelet-insecure-tls' flag.

Variations

  1. Use 'kubectl top pod --containers' to see per-container usage within a multi-container pod.
  2. Use 'kubectl describe pod' to see container resource usage in the 'Containers' section, alongside request/limit values.
  3. For persistent monitoring, export Metrics Server data to Prometheus and visualize with Grafana dashboards.

Real-world use cases

  • A development team notices a web application responding slowly; they run 'kubectl top pods' to see a spike in CPU usage, then scale the deployment.
  • A site reliability engineer sees a pod restarting repeatedly; they use 'kubectl describe pod' to find 'OOMKilled' and increase the memory limit.
  • During a capacity planning review, an admin runs 'kubectl top nodes' across all namespaces to identify underutilized nodes that could be removed.

Key takeaways

  • The Metrics Server is required for 'kubectl top' commands — install it first or the command will fail.
  • 'kubectl top pods' shows real-time CPU (in millicores) and memory (in mebibytes) per pod.
  • Use 'watch -n 2 kubectl top pods' to monitor changes in resource usage every few seconds.
  • A pod that exceeds its memory limit is killed (OOMKilled); CPU limits cause throttling, not termination.
  • For historical data or alerting, integrate the Metrics Server with Prometheus and Grafana.
  • The '--all-namespaces' flag lets you monitor resource usage across the entire cluster.

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.