Predict and provision infrastructure capacity before demand outpaces supply. Covers load modeling, bottleneck identification, scaling strategies, cost-capacity tradeoffs, and the planning process that prevents both outages and over-provisioning.
Capacity planning ensures systems can meet expected demand without over-provisioning or under-provisioning resources. This process focuses on identifying bottlenecks early, before performance degrades or outages occur. It is critical during growth phases, before major events, and when system behavior changes.
Use kubectl top to view real-time CPU and memory usage across nodes and pods.
kubectl top node
kubectl top pod -n namespace-name
Monitor these metrics over time with a tool like Prometheus or InfluxDB. The key is tracking sustained load, not momentary spikes. For example, a pod may show 50% CPU usage during a 10-minute window but consistently exceed 80% during business hours.
Check system logs for resource contention errors:
OOMKilled
Error: failed to create containerd task: OCI runtime create failed: container_linux.go:380: starting container process caused "process_linux.go:545: container init caused: write /sys/fs/cgroup/cpu,cpuacct/kubelet.slice/.../cpu.cfs_quota_us: invalid argument: unknown
These errors indicate a lack of CPU or memory allocation that must be addressed before scaling.
Use kubectl describe to inspect pod and node resource limits:
kubectl describe pod pod-name -n namespace-name
kubectl describe node node-name
Look for events indicating resource exhaustion or scheduling failures. Common messages include:
Evicted due to NodeOutOfCPU
Evicted due to NodeOutOfMemory
FailedScheduling: 0/3 nodes are available: 3 Insufficient memory.
If a pod fails to start because of insufficient resources, check its requests and limits in the deployment manifest:
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
The system may schedule pods based on requests, but enforce limits at runtime. A pod that exceeds its memory limit will be terminated with an OOMKilled event.
Calculate expected load using historical metrics and projected growth. Use tools like kubectl get pods --sort-by=.status.startTime to identify how many pods are running in parallel during peak hours.
For CPU, compare actual usage against requested capacity:
kubectl top pod -l app=frontend --sort-by=cpu
If a deployment's CPU usage consistently reaches 80% of its limit, plan to increase the limit or add more replicas. The rule of thumb is to maintain headroom: avoid running at 95% utilization unless you have specific monitoring and alerting in place.
When scaling horizontally, consider both pod count and resource distribution. Use kubectl scale to adjust replica counts:
kubectl scale deployment frontend --replicas=10
Monitor the impact of scaling on service latency. If increasing replicas causes performance degradation, it might indicate a bottleneck in another part of the system — for example, database connection limits or shared cache contention.
Check if your system handles graceful shutdowns properly. When pods terminate, they should finish processing requests before exiting. Kubernetes sends SIGTERM to pods when terminating them, so applications must handle this signal appropriately.
Misconfigured resource requests and limits cause unnecessary scheduling failures or overcommitment. If a pod's request is too low, it may be scheduled onto nodes with insufficient capacity. If limits are too high, the pod can monopolize resources, starving other workloads.
Use kubectl apply to update deployments with precise values:
resources:
requests:
memory: "128Mi"
cpu: "500m"
limits:
memory: "256Mi"
cpu: "1000m"
Avoid setting limits without matching requests. A pod with no request but a limit of 2GB may be scheduled on a node with only 1GB of free memory, leading to frequent evictions.
Set up alerts in your monitoring system to trigger when resource usage approaches thresholds. For example, alert when CPU utilization hits 80% for more than 15 minutes.
In Kubernetes, use Horizontal Pod Autoscaler (HPA) to automatically scale based on metrics:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: frontend-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: frontend
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 80
HPA adjusts replicas based on average CPU usage. If your workload is memory-bound, you can define custom metrics instead:
- type: Resource
resource:
name: memory
target:
type: AverageValue
averageValue: 200Mi
If HPA doesn't respond as expected, check for missing metrics or incorrect metric types. A common mistake is using averageUtilization when the workload is memory-bound.
When multiple workloads share nodes, resource contention can occur even if individual pods have adequate limits. Use node labels and taints to isolate critical applications:
kubectl taint nodes node-name dedicated=production:NoSchedule
Then schedule pods with tolerations:
tolerations:
- key: "dedicated"
operator: "Equal"
value: "production"
effect: "NoSchedule"
This ensures critical workloads don't get evicted due to resource pressure from less important services.
Design systems to handle bursts in traffic or temporary failures gracefully. For instance, a service that uses Redis may experience slowdowns if the Redis instance is overloaded. Ensure your application has timeouts and retry logic to prevent cascading failures.
Monitor system logs during high-load periods to catch silent failures. A component may continue working but respond slowly. If response times increase beyond acceptable thresholds, investigate whether it's due to resource constraints or logic issues.
Balance performance with cost. Over-provisioning increases expenses, while under-provisioning risks outages. Use kubectl top and your monitoring system to track actual usage against allocated resources.
If a deployment consistently runs below 20% CPU usage, consider reducing its resource allocation. If it exceeds 90% consistently, plan for more resources or better load distribution.
Use cost analysis tools like kube-cost or Prometheus with Grafana to correlate resource usage with billing data. This helps identify which workloads consume the most resources and whether scaling decisions are economically justified.
When adding new nodes, ensure they have compatible resource profiles. Check that new nodes have sufficient memory and CPU capacity to support existing workloads. Use kubectl drain before removing nodes:
kubectl drain node-name --ignore-daemonsets
This safely evicts pods from a node and redistributes them across other nodes. Verify that all pods can reschedule without issues, especially those with local storage or specific node affinity rules.
If scaling fails due to resource constraints, check the cluster state:
kubectl get nodes
kubectl describe node node-name
Look for taints, conditions, or events indicating why nodes became unschedulable. If a node is marked as NotReady, investigate whether it's due to hardware failure, network issues, or resource exhaustion.
If pods are stuck in Pending state, review their scheduling constraints:
kubectl describe pod pod-name -n namespace-name
Look for events like 0/3 nodes are available: 1 node(s) didn't match node selector, which indicates a misconfigured node selector or label.
After implementing capacity changes, validate that the system behaves as expected. Use load testing tools to simulate real-world traffic patterns and confirm that new limits or replica counts meet performance targets.
Monitor for regressions in application behavior. If a scaling change introduces latency or increases error rates, investigate whether it's due to resource contention or configuration errors.
Keep logs of all changes made during capacity planning sessions. This helps identify which modifications caused specific issues and allows for quick rollbacks if needed.
Use kubectl get events to check recent system events:
kubectl get events --sort-by=.metadata.creationTimestamp
This command shows the most recent events in chronological order, helping to correlate scaling actions with system behavior.
This page was rewritten on 16 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.
We use cookies for analytics (Google Analytics) and advertising (Google AdSense) to improve your experience and support free content. Privacy Policy