L’OOM canary est expérimental et désactivé par défaut. Son comportement peut évoluer
d’une version de ClickHouse à l’autre jusqu’à la fin de la validation en production.
Vue d’ensemble
SIGKILL — généralement le plus gros consommateur, qui,
sur un hôte dédié, est clickhouse-server lui-même. On perd alors l’ensemble du serveur
au lieu de lui laisser une chance de se rétablir.
L’OOM canary change l’ordre des victimes. Il exécute un petit processus enfant
sacrificiel qui se rend lui-même prioritaire pour l’OOM killer, afin que le noyau le tue
à la place du serveur. Le serveur détecte alors sa mort, confirme qu’il s’agissait d’un événement OOM,
puis réduit la pression mémoire pour pouvoir survivre.
Le canary n’augmente aucune limite mémoire et ne remplace pas des
limites correctement définies (voir Memory overcommit et
max_server_memory_usage). Il constitue une dernière ligne de défense qui échange une petite quantité
fixe de mémoire contre une chance de survivre à un pic de consommation mémoire.
Comment cela fonctionne
clickhouse oom-canary distinct. Il définit son propre
oom_score_adj au maximum (1000) pour que le noyau le cible en premier, puis
alloue, touche et applique mlock à oom_canary_size octets (100 Mo par défaut) afin que
sa mémoire résidente soit bien réelle. Il est automatiquement tué si le serveur s’arrête.
Dans le serveur, un thread de surveillance observe le canary (via pidfd) et réagit lorsqu’il
meurt :
- Tué par
SIGKILLavec preuve d’OOM au niveau du cgroup → exécuter la réponse OOM, puis relancer un nouveau canary. - Tué sans preuve d’OOM (par exemple, un
kill -9manuel), ou arrêté après une défaillance transitoire → relance uniquement, sans réponse. - Échec permanent de l’initialisation, ou arrêt du serveur → le canary se désactive.
oom_kill de memory.events.local du cgroup v2.
Elle est volontairement locale au cgroup : des compteurs hiérarchiques ou à l’échelle de l’hôte peuvent
être incrémentés par des processus sans rapport et déclencheraient de fausses réponses.
Lorsqu’un OOM est confirmé, la réponse exécute ces étapes indépendantes : consigner un message FATAL,
purger les arènes de l’allocator (jemalloc), annuler dans la mesure du possible toutes les
queries en cours d’exécution, annuler tous les merges et mutations, et mettre en
file d’attente un événement dans
system.crash_log. Les log système ne sont pas
vidés de manière synchrone, car forcer des E/S sous pression mémoire peut aggraver
la situation.
Exigences
- Linux ≥ 5.3. Le moniteur détient le canari via
pidfd_open; sur les noyaux plus anciens, le canari se désactive au démarrage. Cela est sans effet sur les plateformes non Linux. cgroup v2avecmemory.events.localpour la réponse OOM. Sans cela, le canari se relance bien après unSIGKILL, mais ne peut pas confirmer un OOM ; la réponse n’est donc jamais exécutée (un avertissement est consigné au démarrage).- Capacité
mlock(facultative). Le verrouillage de la mémoire du canari nécessiteCAP_IPC_LOCKou une valeurRLIMIT_MEMLOCKsuffisante ; en cas d’échec, le canari consigne un avertissement et sa mémoire peut être paginée sur disque, ce qui le rend moins efficace comme cible OOM.
Configuration
Observabilité
system.crash_log avec signal = 9 et un
signal_description mentionnant OOM Canary :