how to increase Kubernetes pod memory limits safely
Raises Kubernetes pod memory limits safely without causing scheduling or eviction problems. Use when pods are OOMKilled, you need bigger limits, or want to set requests and limits that the scheduler respects. Triggers: raising memory limits, OOMKilled prevention, right-sizing requests vs limits, VPA recommendations. Not for: CPU limit tuning (different behavior), node-level memory upgrades, debugging an existing OOMKilled pod (see that skill).
TL;DR
Raise memory limits with a rolling update, keep requests honest so the scheduler can place the pod, and leave headroom between request and limit for bursts. Do it in small steps and watch actual usage with kubectl top or a VerticalPodAutoscaler in recommendation mode. Safe means no scheduling surprises and no evictions.
The query
how to increase Kubernetes pod memory limits safelyYou want bigger limits without breaking scheduling, causing evictions, or masking a leak.
Use this when
- pods are OOMKilled and need bigger limits
- usage graphs show the pod riding near its limit
- youre right-sizing requests and limits for a workload
- a VPA recommendation suggests new values
Not for
- CPU limits (CPU throttles, memory kills; different tuning)
- adding RAM to the nodes themselves
- debugging why a pod got OOMKilled (fix the cause first)
Steps
- Measure real usage before touching anything:
kubectl top pod [pod-name] -n [namespace] --containersExpected: current usage per container. For history, check your metrics backend (Prometheus container_memory_working_set_bytes). Size from peaks, not averages.
- Set request to the steady-state usage and limit to peak plus headroom:
resources:
requests:
memory: "512Mi"
limits:
memory: "1Gi"Expected rule of thumb: request near the p50, limit near the p99 plus 20 percent. The request is what the scheduler reserves; the limit is where the OOM killer strikes.
- Apply with a rolling update, never by editing a live pod (pods are immutable):
kubectl apply -f deployment.yaml
kubectl rollout status deployment/[name] -n [namespace]Expected: new pods come up with the new limits, old pods drain. kubectl describe pod on a new pod shows the updated values.
- Confirm the pod actually fits on the nodes:
kubectl describe node | grep -A 5 "Allocated resources"Expected: the node's allocated memory still has room for the new requests. If raising requests makes pods unschedulable, the cluster needs more capacity, not smaller requests.
- Watch one full load cycle before calling it done:
kubectl top pod -n [namespace] -l app=[app] --containersExpected: peak usage stays comfortably under the new limit. If it touches the limit again, either raise further or fix the growth in the app.
- For ongoing sizing, run a VPA in recommendation mode:
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: [app]-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: [app]
updatePolicy:
updateMode: "Off"Expected: kubectl describe vpa [app]-vpa shows recommended requests. Apply the recommendations manually on your own schedule.
Variant: bursty workload (batch jobs, image processing)
Keep requests low so scheduling stays easy, set limits high for the bursts. Wide request/limit gaps are fine for bursty work and terrible for steady-state services.
Variant: Java/JVM apps
Set -Xmx to about 75 percent of the new limit so heap plus off-heap fits. Raising the container limit without raising Xmx just moves the waste.
Variant: limit raised but pod still OOMKilled
The rollout may not have replaced the pod (check the pod age and the limit in describe), or the app grows unboundedly. Verify the new limit is live before raising again.
Why it happens
Memory limits are enforced by cgroups: cross the line and the kernel kills the container instantly. Requests control scheduling: the scheduler wont place a pod where the request doesnt fit. Raising limits without watching requests either leaves pods unschedulable (request too big) or lets one pod starve its neighbors (request too small, limit huge).
Edge cases
- LimitRange in the namespace can cap or default your values; check
kubectl describe limitrange -n [namespace]if your numbers dont stick. - VPA in Auto mode restarts pods to apply recommendations; use Off or Initial during business hours.
- Memory QoS: pods with requests equal to limits get Guaranteed class and are evicted last; burstable pods are evicted first under node pressure.
- Dont raise limits to mask a leak; if usage climbs forever, the code needs fixing, not the YAML.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_tvOQlWmx38kr1V5oDJ5PpQ
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.