Kubernetes Resource Management: Production Checklist for Limits, Requests, and HPA
Efficient resource management in Kubernetes is the cornerstone of any stable and high-performing cloud-native infrastructure. Ignoring this aspect can transform a dynamic and resilient environment into a minefield of instability and unexpected downtime. Imagine a scenario: a well-sized Kubernetes cluster with dozens of deployments handling critical workloads. Everything seems to be working perfectly until a single pod, perhaps due to a memory leak or an unexpected traffic spike, begins to consume resources disproportionately. Without the right controls, this pod can completely saturate a node, leading to the forced eviction of all other pods residing on it. This is not a theoretical exercise; I personally witnessed a cluster with 30 deployments go down for 20 minutes, precisely because of a pod with a memory leak that saturated the node’s RAM. The cause? The absence of just five lines of YAML configuration related to resource limits. A trivial error that had a significant impact on service availability. This article aims to be a practical guide and an operational checklist for correctly configuring requests, limits, QoS classes, and autoscaling, ensuring stability and performance for your production Kubernetes environment.
Tested on: Kubernetes 1.29 · kubectl 1.29 · July 27, 2026
Prerequisites / Test Environment
To follow this guide, you will need a working Kubernetes cluster and kubectl access. A production environment is not necessary; a local cluster like Minikube or Kind is sufficient for testing these concepts. Ensure you have kubectl configured and authenticated to your cluster.
1. Requests and Limits: Difference and Why Both Are Mandatory
The distinction between requests and limits is fundamental for the stability and efficiency of your Kubernetes cluster. These two parameters, defined for CPU and memory, guide the Kubernetes scheduler in placing pods on nodes and kubelet in managing resources on the node.
- Requests: Indicate the minimum amount of resources (CPU and memory) a pod requires to function correctly. The scheduler uses
requeststo decide which node to place a pod on, ensuring the node has enough available resources to meet this minimum requirement. If a node does not have the requested resources, the pod will not be scheduled on that node. Read also: Kubernetes Networking: DNS, Services, Ingress para Sysadmins - Limits: Represent the maximum amount of resources (CPU and memory) a pod can consume. If a pod attempts to exceed its memory
limit, it will be terminated (OOMKilled – Out Of Memory Killed) by the kubelet. If it exceeds its CPUlimit, its execution will be throttled, but it will not be terminated.Limitsare crucial to prevent a single pod from starving other pods on the node, or even causing instability to the entire node, as in the memory leak example I mentioned.
Why are both mandatory? Without requests, Kubernetes cannot guarantee a minimum resource baseline, leading to over-provisioning and instability. Without limits, a misbehaving pod can compromise the entire node. The combination of both provides the scheduler and kubelet with the necessary information for predictable and robust resource management.
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: nginx:latest
resources:
requests:
memory: "64Mi"
cpu: "250m" # 0.25 CPU core
limits:
memory: "128Mi"
cpu: "500m" # 0.5 CPU core
2. QoS Classes: Guaranteed, Burstable, BestEffort
Kubernetes assigns each pod a Quality of Service (QoS) Class based on its requests and limits configuration. This class determines scheduling priority and, crucially, eviction management in situations of resource scarcity on the node.
- Guaranteed: A pod is
Guaranteedif the CPU and memoryrequestsare equal to thelimitsfor all its containers. These pods have the highest priority and are the last to be terminated in case of insufficient resources on the node. - Burstable: A pod is
Burstableif it has at least one CPU or memoryrequestconfigured, andrequestsare less thanlimits(orlimitsare not specified). These pods have an intermediate priority and may be terminated beforeGuaranteedpods. - BestEffort: A pod is
BestEffortif none of its containers specifyrequestsorlimitsfor CPU or memory. These pods have the lowest priority and are the first to be terminated in case of resource scarcity.
Understanding QoS Classes is crucial for resilience. Assign Guaranteed to critical workloads, Burstable for most applications, and BestEffort only for non-essential services or batch jobs that can tolerate interruptions.
3. LimitRange and ResourceQuota for Namespaces
In multi-tenant environments or with different teams sharing a cluster, it is essential to enforce resource usage policies at the namespace level. LimitRange and ResourceQuota are the tools for this.
- LimitRange: Defines the
defaultandmaximumrequestsandlimitsfor pods and containers within a namespace. If a pod does not specifyrequestsorlimits,LimitRangecan inject default values. This prevents developers from forgetting to configure resources. Read also: Helm Kubernetes: Deploy e Gestione Applicazioni con Package Manager (2026)
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-mem-limit-range
spec:
limits:
- default:
cpu: 500m
memory: 256Mi
defaultRequest:
cpu: 200m
memory: 128Mi
type: Container
- ResourceQuota: Limits the total resource consumption for an entire namespace. You can limit the number of pods, services, persistent volumes, and most importantly, the total
requestsandlimitsfor CPU and memory. This prevents a single namespace from monopolizing cluster resources.
kubectl apply -f - <<EOF
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-quota
spec:
hard:
requests.cpu: '4'
requests.memory: 8Gi
limits.cpu: '8'
limits.memory: 16Gi
EOF
These tools, when well-configured, allow you to rest easier, knowing that teams cannot inadvertently (or intentionally) cause problems for the entire cluster.
4. HPA — Autoscaling Based on CPU and Custom Metrics
The Horizontal Pod Autoscaler (HPA) is a controller that automatically scales the number of replicas of a Deployment, ReplicaSet, or StatefulSet based on observed CPU, memory, or other custom metrics. This allows you to manage load spikes without manual intervention.
The HPA monitors metrics via the metrics.k8s.io API (which requires metrics-server to be installed) or external APIs for custom metrics. When the average resource utilization of a pod exceeds a defined threshold, the HPA increases the number of replicas. When it drops, it reduces them.
Example of CPU-based HPA:
kubectl autoscale deployment myapp --cpu-percent=70 --min=2 --max=10
This command creates an HPA that will maintain the average CPU utilization of the myapp deployment at 70%, scaling between a minimum of 2 and a maximum of 10 pods. You can check the HPA status with:
kubectl get hpa
For custom metrics, such as the number of HTTP requests per second or the length of a message queue, it is necessary to integrate a monitoring system like Prometheus and configure a Custom Metrics API to expose these metrics to the HPA.
5. VPA — Vertical Autoscaling to Optimize Requests
While HPA scales horizontally (adding or removing pods), the Vertical Pod Autoscaler (VPA) scales vertically, dynamically adjusting CPU and memory requests and limits for individual pods. The VPA observes a pod’s historical resource usage and suggests (or directly applies) optimal configurations.
VPA is particularly useful for workloads with variable resource usage patterns that do not benefit from horizontal scaling, or for optimizing resources and reducing waste. It can operate in different modes:
- Off: Only suggests optimal values, does not apply them.
- Initial: Applies suggestions only when the pod starts.
- Recreate: Terminates and recreates pods to apply new values.
- Auto: Dynamically adjusts resources without recreating the pod (requires beta Kubernetes features).
VPA implementation is more complex than HPA and requires careful evaluation, especially for Recreate mode, which involves temporary downtime for the pod.
6. kube-resource-report: Cluster Overview in One Command
To get an overview of resource usage and configuration in your cluster, tools like kube-resource-report or even simple kubectl commands are indispensable. For a quick and straightforward analysis of current resource usage, you can use:
kubectl top pods --all-namespaces --sort-by=cpu
This command will give you an immediate overview of the pods consuming the most CPU, useful for identifying potential problems or misconfigured pods. For a more in-depth analysis and aggregated reports, external tools like kube-resource-report or monitoring dashboards (e.g., Grafana with Prometheus) are essential for a production environment. Read also: Prometheus Alerting: Telegram, Email, PagerDuty with AlertManager
Common Errors and Troubleshooting
- Frequent OOMKilled: Indicates that memory
limitsare too low or that there is a memory leak in the application. Increasing thelimitcan temporarily resolve it, but it is crucial to investigate the cause of excessive consumption. - Pod Pending: Often means that CPU or memory
requestsare too high, and there are no nodes with sufficient resources to schedule the pod. Checkkubectl describe podfor details. - CPU Throttling: If CPU
limitsare too low, the application may experience slowdowns. Monitor CPU usage and increaselimitsif necessary, but be careful not to over-provision. - HPA not scaling: Verify that
metrics-serveris installed and running (kubectl top podsshould work). Check HPA events (kubectl describe hpa) to understand why it is not scaling. - Forgetting
requests: This is a common error that leads pods to haveBestEffortQoS, making them vulnerable to eviction in case of resource scarcity. UseLimitRangeto set defaults.
FAQ — Frequently Asked Questions
Should I always set both requests and limits?
Yes, for most production workloads, it is strongly recommended to set both requests and limits. Requests help the scheduler place pods correctly, while limits prevent a single pod from compromising the entire node. Their combination ensures Guaranteed or Burstable QoS, reducing the risk of eviction.
What is the practical difference between HPA and VPA?
HPA (Horizontal Pod Autoscaler) increases or decreases the number of pods (horizontal scaling) based on load. VPA (Vertical Pod Autoscaler) adjusts a single pod’s resources (CPU/memory) (vertical scaling). HPA is ideal for stateless and scalable applications, while VPA is for optimizing resource utilization of single or stateful pods.
How can I monitor my cluster’s resource usage?
For basic monitoring, kubectl top nodes and kubectl top pods are a good start. For more advanced, production-grade monitoring, integration with Prometheus and Grafana is the de facto standard. These tools allow you to visualize historical usage, set alerts, and analyze trends, which are essential for capacity planning. For official documentation on Kubernetes monitoring, refer to the Kubernetes Monitoring documentation.
Can a pod with Guaranteed QoS still be terminated?
Yes, even a Guaranteed pod can be terminated, but it is a last resort. This can happen in extreme situations, such as a lack of critical system resources (e.g., PIDs, disk space) or if the node itself fails (e.g., hardware crash, kernel panic). The Guaranteed class offers maximum protection, but not absolute immunity in case of node failures.
Conclusions with Operational Takeaways
Resource management in Kubernetes is not an option, but a fundamental practice for the stability and efficiency of production environments. The 20-minute downtime incident due to 5 missing YAML lines is a powerful warning. Properly implementing requests and limits for each pod, using ResourceQuota and LimitRange to enforce namespace-level policies, and leveraging autoscaling with HPA and VPA, are crucial steps to building a robust and resilient Kubernetes infrastructure. Do not let a misconfigured pod ruin your day. Invest time in understanding and implementing these best practices; it will pay off in terms of uptime and peace of mind.
Updated: July 2026