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
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 topcommands won't work.
Pro tip: Even if your cluster doesn't have the Metrics Server installed, you can still use
kubectl describe podorkubectl logsto get partial insight, butkubectl topis 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
- Use 'kubectl top pod --containers' to see per-container usage within a multi-container pod.
- Use 'kubectl describe pod' to see container resource usage in the 'Containers' section, alongside request/limit values.
- 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.
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.