Aller au contenu principal
~$ guillaume.putier.fr

notes/zombie-par-sonde-de-sante

9448 zombies dans un conteneur, un par passage de la sonde de santé

node en PID 1, une sonde wget en HTTPS toutes les 30 secondes, et le conteneur s'étouffe au bout de trois jours. docker top ne montre rien.

  • docker
  • node
  • healthcheck

La passerelle de ma flotte d'agents était unhealthy depuis trois jours quand je l'ai regardée, le 30 septembre 2026. Sa sonde échouait sur un message qui ne parle pas du service : OCI runtime exec failed: procReady not received.

Docker n'arrivait plus à lancer un processus dans le conteneur. Le cgroup en comptait 9459, pour un plafond pids.max de 9463. node y comptait 11 threads. Les 9448 autres étaient des zombies ssl_client, tous rattachés à node.

La sonde était banale :

healthcheck:
  test: wget --no-check-certificate -qO- https://127.0.0.1:8080/healthz
  interval: 30s

En HTTPS, le wget de busybox lance un second programme, ssl_client, qui se retrouve orphelin et se fait adopter par le PID 1. Sur une machine, le PID 1 est un init qui ramasse ses enfants morts. Dans ce conteneur, le PID 1 était node, qui ne ramasse rien. Un zombie par passage, 2880 par jour, le plafond en 3,3 jours.

docker top ne les affiche pas. Il faut lire le compteur du cgroup, puis demander les parents :

cat /sys/fs/cgroup/system.slice/docker-<id>.scope/pids.current
ps -eo ppid,stat,comm | awk '$2 ~ /Z/'

Le correctif tient en une ligne de compose, init: true. Docker place alors docker-init en PID 1, et lui réclame les orphelins.

Je l'ai rejoué en local, la même sonde toutes les 2 secondes pendant 100 secondes : 49 zombies sans init, aucun avec. Après recréation sur la machine, 12 processus.

Le dépôt porte depuis un test qui refuse tout service node déclaré sans init.

retour aux notes