10 Kubernetes Production Problems I Check First: SRE Incident Runbook

📅 Published: 2026-09-20 ⏱ 14 min read 🏷 Kubernetes & SRE 👤 Naveed Ahmed
When PagerDuty fires at 3 AM with 50 pods in CrashLoopBackOff, scanning endless logs wastes precious minutes. After a decade of debugging production Kubernetes clusters, I follow a strict 10-point triage order that isolates 95% of outages within five minutes. Here is my operational runbook.

The 10-Point SRE Triage Matrix

During a production incident, triage follows a strict hierarchy: Host Node → Networking/DNS → Control Plane → Container Runtime → Application Code. Never debug application logs until you confirm the infrastructure substrate is healthy.

Problem 1

Exit Code 137: Linux OOMKilled vs Node Memory Pressure

Exit code 137 means SIGKILL was dispatched. The critical question: Was it a container-level OOM (exceeded resources.limits.memory) or a node-level OOM (host kernel killed processes due to node exhaustion)?

// Fast CLI Diagnostic
# Check if container was OOMKilled
kubectl get pods -n prod -o jsonpath='{range .items[*]}{.metadata.name}{"	"}{.status.containerStatuses[*].lastState.terminated.reason}{"	"}{.status.containerStatuses[*].lastState.terminated.exitCode}{"
"}{end}' | grep OOMKilled

# Check node dmesg for kernel kill events
kubectl debug node/<node-name> -it --image=busybox -- chroot /host dmesg -T | grep -i -E "oom[-_]killer|killed process"

The Fix: Differentiate RSS memory from Page Cache. If JVM or Node.js heap is configured higher than container memory limits, tune heap flags (-XX:MaxRAMPercentage=75.0).

Problem 2

Exit Code 143: Graceful Termination Timeout Races

When a pod exits with 143, it received SIGTERM but failed to shutdown gracefully within terminationGracePeriodSeconds (default: 30s), forcing kubelet to send SIGKILL.

# Inspect pod shutdown duration events
kubectl get events -n prod --field-selector reason=Killing --sort-by='.metadata.creationTimestamp'

The Fix: Implement a preStop hook with a sleep (e.g. sleep 10) to allow Kubernetes endpoints and kube-proxy iptables to remove the pod IP before the application stops accepting traffic, and increase terminationGracePeriodSeconds: 60.

Problem 3

Liveness Probe Cascading Death Spirals

The most destructive configuration mistake in Kubernetes: configuring a liveness probe to check downstream dependencies (PostgreSQL database or Redis). If the database slows down, all pods fail their liveness probe simultaneously, kubelet restarts all containers in a stampede, destroying connection pools and taking down the entire system.

The Rule: Liveness probes must only verify if the container process is deadlocked internally (shallow /healthz check returning HTTP 200). Use readiness probes for dependency checks so traffic is temporarily detached without restarting the process.

Problem 4

CoreDNS 5-Second Latency & Conntrack Table Collisions

When external or inter-pod requests experience sudden 5.00-second latency spikes, it is almost always the Linux netfilter conntrack UDP race condition between IPv4 (A) and IPv6 (AAAA) DNS queries.

// Inspect conntrack drops and CoreDNS latency
# Check conntrack insertion drops
sudo conntrack -S

# Verify CoreDNS response metrics
kubectl top pods -n kube-system -l k8s-app=kube-dns

The Fix: Deploy NodeLocal DNSCache daemonset on every node to serve DNS over local TCP loops, eliminating conntrack UDP races entirely.

Problem 5

AWS VPC CNI IP Address Exhaustion

Pods remain stuck in ContainerCreating or FailedCreatePodSandBox with error: "failed to assign an IP address to container".

# Check aws-node daemonset IP pool status
kubectl get pods -n kube-system -l k8s-app=aws-node
kubectl describe daemonset aws-node -n kube-system | grep -A 8 "Environment:"

The Fix: Enable Prefix Delegation on the AWS VPC CNI. Set ENABLE_PREFIX_DELEGATION=true and configure WARM_PREFIX_TARGET=1, expanding node IP capacity from ~30 IPs to over 250 IPs per instance.

Problems 6–10 Summary

Remaining Essential Checks

Have questions about this architecture or scaling your infrastructure?

Whether you're planning a complex cloud migration, optimizing Kubernetes reliability, or designing autonomous AI workflows, I'm always open to discussing architecture and technical challenges with engineering teams.

Connect with Naveed on LinkedIn →

Frequently Asked Questions

What is the difference between exit code 137 and exit code 143 in Kubernetes?

Exit code 137 indicates the container was killed by SIGKILL (signal 9 + 128 = 137), almost always triggered by the Linux kernel Out-Of-Memory (OOM) killer when container memory exceeds limits. Exit code 143 indicates SIGTERM (signal 15 + 128 = 143), meaning Kubernetes gracefully requested termination (e.g. node drain, rolling update, or failing liveness probe) but the app did not exit before terminationGracePeriodSeconds expired.

Why does CoreDNS cause 5-second DNS delays in Kubernetes?

The notorious 5-second DNS delay is caused by a race condition in Linux netfilter conntrack during simultaneous UDP lookups (A and AAAA records) over the same source port. This causes conntrack insert collisions and packet drops. The fix is deploying NodeLocal DNSCache or setting single-request-reopen in the pod dnsConfig.

How do you resolve AWS VPC CNI IP exhaustion?

AWS VPC CNI IP exhaustion happens when pod churn exhausts the available secondary IPv4 addresses on worker node ENIs. Resolve it by configuring WARM_IP_TARGET and MINIMUM_IP_TARGET in the aws-node daemonset, or enabling prefix delegation (ENABLE_PREFIX_DELEGATION=true) which allocates /28 IPv4 prefixes (16 IPs per slot) instead of individual IPs.

Naveed Ahmed

Naveed Ahmed (Kumbhar)

Senior DevOps & Cloud Engineer with 10+ years specializing in AWS, Kubernetes, Platform Engineering, SRE incident response, and autonomous AI infrastructure agents.

Have a technical challenge or architecture question? Connect on LinkedIn →