Aller au contenu

Runbook : PodOOMKilled

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

Symptôme :

Container <container> dans <pod> a été tué 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 + correctif

Cause Typique pour Correctif
Limite trop basse Profil JupyterHub analyst (1G) avec noyau Scala Bump profile_list[].kubespawner_override.mem_limit dans values-dev.yaml. Voir [L11].
Fuite mémoire 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 le cache par défaut ou augmenter mem_limit.
HPA mal réglé OpenMetadata server Forcer maxReplicas > 1 pour répartir la charge.

Correctif pérenne (R02)

Jamais : kubectl patch deployment --resources à chaud.

Toujours : 1. Identifier la cause : bug code vs sous-provisionnement 2. Si sous-provisionnement : bump resources dans les Helm values 3. Si fuite : 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 24 h

Exemple — bump JupyterHub analyst 1G → 2G

# helm/examples/values-dev.yaml
jupyterhub:
  singleuser:
    profileList:
      - display_name: "Analyst"
        kubespawner_override:
          mem_limit: 2G  # était 1G, le noyau Scala a besoin de 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 % de mémoire avant l'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 — Le noyau Scala Almond dans JupyterHub prend 2-3G au démarrage. Ne jamais limiter à 1G le profil analyst.

Liens utiles