Troubleshooting Kubernetes Pod OOMKilled on Windows WSL2 Ubuntu: Resource Limits Exceeded
Resolve Kubernetes Pod OOMKilled errors on WSL2 Ubuntu by analyzing resource limits, optimizing application memory, and adjusting WSL2 VM allocation.
Resolve Kubernetes Pod OOMKilled errors on WSL2 Ubuntu by analyzing resource limits, optimizing application memory, and adjusting WSL2 VM allocation.
A Kubernetes Pod experiencing an OOMKilled (Out Of Memory Killed) state is a common headache for developers and system administrators alike, especially when running development or testing clusters on resource-constrained environments like Windows Subsystem for Linux 2 (WSL2) with Ubuntu. This guide provides a highly technical, step-by-step approach to diagnose and resolve such issues.
Symptom & Error Signature
When a Kubernetes pod is OOMKilled, it means the process inside the container attempted to use more memory than it was allocated, leading the kernel to terminate it. You'll typically observe pods repeatedly restarting or failing to transition to a Running state.
You might see the following in your terminal output:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
my-app-pod-abcdefg-hijkl 0/1 OOMKilled 3 (4s ago) 2m
another-pod-123456-789ab 1/1 Running 0 5m
Detailed pod description will show the OOMKilled reason in the Last State of a container:
$ kubectl describe pod my-app-pod-abcdefg-hijkl
Name: my-app-pod-abcdefg-hijkl
Namespace: default
Priority: 0
Node: my-k8s-node-wsl2/172.x.x.x
Start Time: Thu, 13 Aug 2026 10:00:00 +0000
Labels: app=my-app
Annotations: <none>
Status: Running
IP: 10.x.x.x
IPs:
IP: 10.x.x.x
Containers:
my-app:
Container ID: containerd://abcdef...
Image: my-registry/my-app:latest
Image ID: docker.io/my-registry/my-app@sha256:fedcba...
Port: 8080/TCP
Host Port: 0/TCP
Limits:
memory: 512Mi
Requests:
memory: 256Mi
State: Waiting
Reason: CrashLoopBackOff
Last State: Terminated
Reason: OOMKilled
Exit Code: 137
Started: Thu, 13 Aug 2026 10:02:10 +0000
Finished: Thu, 13 Aug 2026 10:02:11 +0000
Ready: False
Restart Count: 3
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-abcde (ro)
Conditions:
Type Status
Initialized True
Ready False
ContainersReady False
PodScheduled True
Volumes:
kube-api-access-abcde:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
Mode: 420
QoS Class: Burstable
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute opExists for 300s
node.kubernetes.io/unreachable:NoExecute opExists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning OOMKilled 3m (x4 over 3m) kubelet Container my-app was OOMKilled
Warning BackOff 2m45s (x5 over 3m) kubelet Back-off restarting failed container my-app in pod my-app-pod-abcdefg-hijkl
Within the WSL2 Ubuntu instance, if the OOM condition is severe enough to affect the entire VM, you might also find kernel OOM killer messages in dmesg:
$ dmesg -T | grep -i "oom-killer"
[Thu Aug 13 10:02:11 2026] oom-kill:constraint=CONSTRAINT_MEMCG,nodemask=(null),cpuset=/,mems_allowed=0
[Thu Aug 13 10:02:11 2026] Memory cgroup out of memory: Killed process 12345 (my-app-process) total-vm:xxxxkB, anon-rss:yyyykB, file-rss:zzzzkB, shmem-rss:0kB
Root Cause Analysis
The OOMKilled error indicates that a process within your Kubernetes Pod's container exhausted its allocated memory. This can stem from several underlying issues, often exacerbated in a WSL2 environment:
Pod Resource Limits Misconfiguration: In Kubernetes, you define
requestsandlimitsfor CPU and memory for each container.limits.memoryspecifies the maximum memory a container can use. If the application inside the container attempts to allocate memory beyond this limit, the Kubernetes kubelet will terminate the container with anOOMKilledstatus.requests.memory: The minimum memory guaranteed to the container. The scheduler uses this for placement.limits.memory: The maximum memory the container is allowed to use. Exceeding this triggers the OOM killer.
Application Memory Leak or High Demand: The application itself might have a memory leak, inefficient memory usage, or simply require more memory than initially anticipated for its workload. This is especially common with applications that cache heavily, process large datasets, or have long-running connections.
WSL2 VM Memory Constraints: The entire WSL2 virtual machine, which hosts your Ubuntu distribution and thus your Kubernetes cluster (e.g., K3s, Minikube, Docker Desktop's K8s), has its own memory allocation defined by the Windows host. If the sum of memory used by all processes within the WSL2 VM (including the Kubernetes control plane, Docker daemon, and all running containers) exceeds the WSL2 VM's allocated memory, the host's kernel OOM killer might step in to kill processes within WSL2, or the WSL2 environment itself might become unstable. This is configured via the
.wslconfigfile.Kubernetes Node OOM: If you're running a multi-node cluster (uncommon for a single WSL2 instance but possible with tools like K3s creating multiple "nodes" as containers), a specific node might be undersized, leading to resource starvation across multiple pods on that node.
Step-by-Step Resolution
Follow these steps to systematically diagnose and resolve the OOMKilled issue.
1. Inspect Pod & Node Resource Usage
First, confirm the configured memory limits for the problematic pod and check the overall resource usage on your Kubernetes node.
# Get current resource limits for the pod
kubectl describe pod <your-pod-name> | grep -A 5 "Limits:"
# Example output snippet:
# Limits:
# memory: 512Mi
# Requests:
# memory: 256Mi
# Check current memory usage of pods (requires Metrics Server installed)
kubectl top pod --all-namespaces
# Check current memory usage of nodes (requires Metrics Server installed)
kubectl top node
If
kubectl topcommands fail, ensure the Kubernetes Metrics Server is installed. For K3s, it's often enabled by default. For Minikube/Docker Desktop, you might need to enable it:minikube addons enable metrics-serverkubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
2. Analyze Container Logs and Events
Review the logs and events for clues about what the application was doing just before it was killed.
# Get logs from the last termination of the container
kubectl logs <your-pod-name> --previous
# If the pod keeps crashing, this might not show much.
# Get all events related to the pod for a wider context
kubectl get events --field-selector involvedObject.name=<your-pod-name>
Look for application-specific error messages, indications of heavy processing, or large data allocations right before the OOMKilled event.
3. Adjust Pod Resource Limits
If your application genuinely needs more memory or your limits.memory was set too conservatively, increase it.
# Example: my-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-registry/my-app:latest
ports:
- containerPort: 8080
resources:
requests:
memory: "512Mi" # Increase request as well
cpu: "250m"
limits:
memory: "1Gi" # Increased memory limit
cpu: "500m"
Apply the changes:
kubectl apply -f my-deployment.yaml
Simply increasing the
limits.memorywithout understanding the actual memory usage patterns might just defer the problem or transfer the pressure to the entire WSL2 VM. It's a temporary fix if the application has a memory leak or poor resource management.
4. Monitor Application Memory Usage (Inside Container)
For more precise diagnostics, try to get inside the running container and observe memory usage in real-time. This is often challenging with OOMKilled pods, but if it runs for a short period, you might catch it.
If the pod briefly runs:
kubectl exec -it <your-pod-name> -- bashOnce inside, use tools like
free -h,top, orps auxto observe memory consumption. Ifbashisn't available, try/bin/sh. You might need to install these tools if the container image is minimal (e.g., Alpine-based).Using
debugcontainers (Kubernetes 1.23+):kubectl debug -it <your-pod-name> --image=ubuntu:latest --target=<container-name-in-pod>This creates a new ephemeral container that shares the process namespace with your failing container, allowing you to use debugging tools without modifying the original image.
5. Increase WSL2 Memory Allocation
This is critical for Kubernetes on WSL2. By default, WSL2 only uses a fraction of your system's RAM. If your K8s cluster and its workloads demand more, you need to explicitly allocate more memory to the WSL2 VM.
Create or edit
.wslconfig: Navigate to your Windows user profile directory:%UserProfile%(e.g.,C:UsersYourUsername). Create a file named.wslconfig(if it doesn't exist) or edit it.; .wslconfig [wsl2] memory=4GB ; Limits the memory allocated to the WSL2 VM. ; Example: 4GB, 8GB. Adjust based on your host RAM. processors=2 ; Limits the number of virtual processors given to the WSL2 VM. ; Example: 2, 4. swap=2GB ; How much swap space to add to the WSL2 VM. localhostForwarding=true ; Enable to access WSL2 services from Windows host.Setting
memorytoo high in.wslconfigcan starve your Windows host system, leading to overall system instability and poor performance. Choose a value that leaves ample RAM for Windows applications. A good rule of thumb is 50-75% of your total physical RAM, assuming your K8s workload is your primary use case.Shut down WSL2 and restart: Open PowerShell or Command Prompt as administrator and execute:
wsl --shutdownThen, restart your WSL2 distribution (e.g., by opening Ubuntu terminal) and your Kubernetes cluster.
Verify changes: Inside your WSL2 Ubuntu instance:
free -hYou should see the updated memory allocation.
6. Check WSL2 Ubuntu Kernel OOM Logs
Even after increasing WSL2 memory, if the OOMKilled persists, check the kernel logs within your WSL2 Ubuntu instance for direct OOM killer messages, which can give more context on what process was being targeted.
dmesg -T | grep -i "oom-killer|memory"
This output can reveal if the WSL2 kernel itself is killing processes (including the container runtime or kubelet) due to overall memory pressure within the VM, rather than just the Kubernetes cgroup limit.
7. Optimize Application Memory Usage
If increasing limits doesn't resolve the issue, or if you want a more robust solution, focus on the application itself:
- Code Review & Profiling: Identify memory leaks, inefficient data structures, or unnecessary allocations in your application code. Tools like
valgrind(C/C++),go tool pprof(Go),memory_profiler(Python), or Java profilers can be invaluable. - Garbage Collection Tuning: For languages like Java or Go, fine-tuning garbage collection parameters can reduce memory spikes.
- Smaller Base Images: Using minimal base images (e.g., Alpine instead of Ubuntu or Debian) for your Docker containers can significantly reduce the container's memory footprint even before your application starts.
- Caching Strategies: Implement efficient caching or offload heavy processing to external services if possible.
Consider using tools like Prometheus and Grafana within your Kubernetes cluster to monitor resource usage over time. This provides historical data and dashboards to identify trends and potential memory leaks proactively.
By systematically addressing both the Kubernetes resource configuration and the underlying WSL2 memory allocation, you can effectively troubleshoot and resolve OOMKilled issues for your pods running on Windows WSL2 Ubuntu.
Our Production Verification Guarantee
Encountering a bug not covered here or running a non-standard kernel configuration? Our solutions are continually refined against real production incidents. Submit an environment trace for our editorial team to replicate.