Skip to content

Runbook: PodOOMKilled

Alerte : PodOOMKilled (PrometheusRule, severity warning ou critical selon le service)

Symptôme :

Container <container> dans <pod> a été killed pour OutOfMemory (exit code 137) plus de 3× en 1h.

Severity : 🟡 warning pour 1-2 OOM isolés, 🔴 critical si CrashLoopBackOff.


Diagnostic

1. Confirmer l'OOM

export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
kubectl describe pod -n akko <pod> | grep -iE "OOMKilled|Reason|ExitCode"
# cherche "Reason: OOMKilled" ou "Exit Code: 137"

2. Mémoire utilisée vs limite

kubectl top pod -n akko <pod>
# Compare Memory usage vs .spec.containers[*].resources.limits.memory

3. Historique des OOM (sur la journée)

kubectl get events -n akko --sort-by='.lastTimestamp' | grep -i "oom" | tail -20

4. Dashboards : "Memory usage per pod" (dashboard akko-k8s)

container_memory_working_set_bytes{namespace="akko", pod=~".*<service>.*"}
  / container_spec_memory_limit_bytes{namespace="akko", pod=~".*<service>.*"}

Causes fréquentes + fix

Cause Typique pour Fix
Limite trop basse JupyterHub profile analyst (1G) avec Scala kernel Bump profile_list[].kubespawner_override.mem_limit dans values-dev.yaml. Voir [L11 Scala needs 2-3G].
Memory leak dans le code Airflow scheduler, Trino coordinator Profiling — bump temporaire + ticket de root cause.
JVM heap mal réglée Trino worker, Spark executor Ajuster -Xmx dans extraJvmOpts à 75% de la limite container.
Cache mal dimensionné Superset, Airflow webserver Réduire cache par défaut ou augmenter mem_limit.
HPA mal réglé OpenMetadata server Forcer maxReplicas > 1 pour spread la charge.

Fix pérenne (R02)

Jamais : kubectl patch deployment --resources en live.

Toujours : 1. Identifier la cause : bug code vs sous-provisionnement 2. Si sous-provisionnement : bump resources dans Helm values 3. Si leak : ouvrir un ticket, patch upstream, rebuild image 4. Commit + push + CI deploy + vérifier 5. Vérifier que les OOM ne reviennent pas après 24h

Exemple — bump JupyterHub analyst 1G → 2G

# helm/examples/values-dev.yaml
jupyterhub:
  singleuser:
    profileList:
      - display_name: "Analyst"
        kubespawner_override:
          mem_limit: 2G  # was 1G, Scala kernel needs 2-3G
          cpu_limit: 0.5

Rollback si le bump casse quelque chose

helm history akko -n akko
helm rollback akko <previous-revision> -n akko

Prévention

  • PrometheusRule préventive : alerter à 80% memory avant OOM
    - alert: PodMemoryHigh
      expr: |
        container_memory_working_set_bytes{namespace="akko"}
          / container_spec_memory_limit_bytes{namespace="akko"} > 0.8
      for: 5m
      severity: warning
    
  • Capacity planning : revoir les mem_limit chaque trimestre selon les observations Dashboards p95 memory / limit.
  • Monitoring des OOM historiques : dashboard Dashboards "OOM Kills per day" par service.

Lessons learned

  • L11 — Scala Almond kernel dans JupyterHub prend 2-3G au démarrage. Ne jamais limiter à 1G le profile analyst.

Liens utiles