The "CPU resource exceeded" error occurs when a pod uses more CPU than its limit. Kubernetes throttles CPU-limited containers, causing performance degradation and timeouts. This prevents a single pod from consuming all node CPU but requires proper limit configuration.
Kubernetes enforces CPU limits using Linux cgroups. Unlike memory limits which result in OOMKill, CPU limits don't terminate pods—instead they throttle the CPU time available to the container. When a pod exceeds its CPU limit, the Linux kernel restricts its CPU access, causing increased latency and timeouts. CPU is a compressible resource (can be throttled without killing the process), while memory is incompressible (exceeding limits kills the pod). CPU throttling happens silently; pods continue running but perform poorly.
Check if the pod is being throttled:
# View current CPU usage vs limits:
kubectl top pods -A
# Detailed resource metrics:
kubectl describe pod <pod-name> -n <namespace>
# Check cgroup CPU metrics directly (requires node access):
ssh <node-ip>
cat /sys/fs/cgroup/cpuacct/kubepods.slice/kubepods-pod<uid>/cpuacct.usage_percpu_sys
cat /sys/fs/cgroup/cpu/kubepods.slice/kubepods-pod<uid>/cpu.stat # Shows throttle infoIf throttle count is increasing, the pod is being rate-limited.
Use Prometheus or kubectl to observe CPU behavior:
# If using Prometheus:
kubectl port-forward -n prometheus svc/prometheus 9090:9090
# Query: rate(container_cpu_usage_seconds_total{pod_name="<pod>"}[5m])
# Watch CPU usage in real-time:
kubectl top pods <pod-name> -n <namespace> --containers -w
# Get historical data:
kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/<ns>/pods/<pod>/cpu_usageIdentify peak usage: Does it consistently exceed the limit, or only under high load?
Check current configuration:
kubectl get pod <pod-name> -n <namespace> -o yaml | grep -A 10 "resources:"
# Or describe:
kubectl describe pod <pod-name> -n <namespace> | grep -A 5 "Limits\|Requests"Example output:
Limits:
cpu: 500m # 0.5 cores
Requests:
cpu: 250mThe limit is the hard cap; the pod cannot exceed this.
Update the pod/deployment with a higher CPU limit:
# For a deployment:
kubectl set resources deployment <name> -n <namespace> --limits=cpu=1 # 1 core
# Or patch directly:
kubectl patch deployment <name> -n <namespace> -p '{"spec":{"template":{"spec":{"containers":[{"name":"<container>","resources":{"limits":{"cpu":"1"}}}]}}}}'
# Or edit the YAML:
kubectl edit deployment <name> -n <namespace>
# Change: limits.cpu from 500m to 1000m (1 core)
kubectl apply -f deployment.yamlIncrease incrementally: 500m → 1000m → 2000m until performance improves.
Reduce CPU consumption rather than just increasing limits:
Java applications:
# Check for hot CPU usage:
java -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions myapp.jar
# Reduce GC overhead:
-XX:+UseG1GC -XX:MaxGCPauseMillis=200Python/Node.js:
# Profile CPU usage:
import cProfile
cProfile.run('myfunction()')
# Or use async/await for I/O-bound operations:
async def fetch():
await asyncio.gather(*[requests.get(url) for url in urls])Common optimizations:
- Replace N+1 queries with batch/join queries
- Cache expensive computations
- Use async/non-blocking I/O
- Remove unnecessary loops or recursive calls
Set request to a realistic baseline CPU need:
kubectl set resources deployment <name> -n <namespace> --requests=cpu=500m
# Or edit:
kubectl edit deployment <name> -n <namespace>Guideline:
- Request: 80% of peak normal usage
- Limit: 150% of request (allows temporary spikes)
Example:
resources:
requests:
cpu: 200m # 200 millicores
limits:
cpu: 500m # 500 millicoresRequests are used for scheduling; limits are hard caps.
Identify if other pods are consuming excessive CPU:
# List pods on the same node sorted by CPU:
kubectl get pods -A --field-selector=spec.nodeName=<node> --sort-by=.status.containerStatuses[0].lastState.terminated.reason
# Top pods by CPU:
kubectl top pods -A --sort-by=cpu
# Check node CPU allocation:
kubectl describe node <node-name> | grep -A 10 "Allocated resources"If other pods are using significant CPU, move your pod to a less loaded node:
kubectl cordon <busy-node> # Prevent new pods from scheduling
kubectl drain <busy-node> --ignore-daemonsets # Gracefully move existing podsSet proper QoS to help the scheduler make better decisions:
apiVersion: apps/v1
kind: Deployment
metadata:
name: high-priority-app
spec:
template:
spec:
containers:
- name: app
image: myapp:latest
resources:
requests:
cpu: 1
memory: 512Mi
limits:
cpu: 2
memory: 1Gi
priorityClassName: high-priority # OptionalQoS classes:
- Guaranteed: requests == limits (never evicted for resource pressure)
- Burstable: requests < limits (evicted if node has pressure)
- BestEffort: no requests/limits (evicted first)
Use Guaranteed for critical apps to prevent eviction during CPU throttling.
CPU throttling is subtle—unlike OOMKill which causes obvious failures, throttled pods continue running with degraded performance. Monitor throttle metrics: container_cpu_cfs_throttled_seconds_total and container_cpu_cfs_throttled_periods_total. A good rule of thumb: request 50-70% of expected peak load, limit at 100-150% of request. Avoid setting very high limits (cores); use autoscaling instead. For latency-sensitive applications (APIs, databases), consider pod disruption budgets and node affinity to prevent contention. CPU limits are enforced at 100ms granularity (CFS period), so very short-duration spikes may slip through. Kubernetes v1.26+ supports CPU OverCommit to reduce resource waste. Java applications particularly struggle with CPU limits due to GC overhead—ensure adequate limits (500m minimum) for Java services.
No subnets found for EKS cluster
How to fix "eks subnet not found" in Kubernetes
unable to compute replica count
How to fix "unable to compute replica count" in Kubernetes HPA
error: context not found
How to fix "error: context not found" in Kubernetes
default backend - 404
How to fix "default backend - 404" in Kubernetes Ingress
serviceaccount cannot list resource
How to fix "serviceaccount cannot list resource" in Kubernetes