Self-hosting

Quand l’OOM killer tue Minecraft : descendre dans la pile pour trouver la vraie cause

Pendant plusieurs semaines, mon serveur Minecraft s’est coupé tout seul, à des heures aléatoires, sans rien laisser dans les logs côté Java. Pas de crash, pas d’exception, juste un silence. Le serveur s’arrêtait comme si on avait débranché la prise. Jusqu’à ce que je tombe sur cette ligne, planquée dans journalctl -k :

Out of memory: Killed process 1234 (java)

L’OOM killer du noyau Linux était passé par là. Et, comme souvent, le coupable n’était pas celui que j’accusais.

Pourquoi l’application ne dit rien

Le réflexe, quand un processus disparaît, c’est d’aller lire ce que l’application elle-même en dit. Pour Minecraft, c’est latest.log. Et il n’y avait rien : aucune panique, aucune erreur applicative. C’est normal — quand le noyau décide de tuer un processus pour récupérer de la mémoire, il ne lui laisse pas le temps d’écrire ses dernières volontés. Sous Linux, lorsque la RAM vient à manquer, l’OOM killer choisit un processus selon un score interne (oom_score) et l’abat sur-le-champ. La JVM, avec son appétit constant et sa grosse réservation mémoire, est presque toujours la première sur la liste. La logique du noyau est implacable : sauver l’ensemble du système quitte à sacrifier un processus, et sans demander la permission.

Le correctif, en trois couches

Une fois le vrai coupable identifié, la solution s’est construite en trois ajustements, chacun visant une cause différente.

  1. Ajouter du swap. Quatre gigaoctets sur un fichier, montés au démarrage. Ce n’est pas une solution miracle — un swap saturé est aussi catastrophique qu’une RAM pleine — mais une marge qui absorbe les pics brefs sans tuer le processus.
  2. Plafonner la JVM. -Xmx5G interdit à Java de dépasser cinq gigaoctets de heap, quoi que disent les réglages par défaut. Sans ce plafond, la JVM consomme jusqu’à ce que le noyau s’en occupe à sa place.
  3. Encadrer le service avec systemd. MemoryMax=6G dans l’unité, et tout le service est arrêté proprement avant que l’OOM killer n’ait à intervenir. La différence est énorme : un systemctl restart au lieu d’un plantage muet.

La vraie leçon n’est pourtant pas dans le triplet swap + Xmx + MemoryMax. Elle est dans la méthode : ne pas s’arrêter aux logs de l’application, descendre d’un cran, lire le noyau, accepter que la cause se trouve souvent en dehors du périmètre qu’on imaginait. Ce réflexe — descendre dans la pile jusqu’à la vraie cause — est sans doute la compétence la plus précieuse que m’ait apprise l’administration de mon propre serveur. Depuis que le triplet est en place, plus une seule coupure. Et maintenant, quand quelque chose tombe sur cette machine, je commence par journalctl -k.