Comment configurer OOM Killer de Linux

par Robert Chase
Publié en février 2013

Cet article décrit le mécanisme OOM Killer de Linux et explique comment comprendre pourquoi il a tué un processus particulier. Sont également proposées des méthodes de configuration d’OOM Killer permettant de mieux répondre aux besoins de nombreux environnements différents.

À propos d’OOM Killer

Lorsqu’un serveur qui prend en charge une base de données ou un serveur d’applications tombe en panne, s’ensuit souvent une course pour remettre en état de fonctionnement les services critiques, surtout s’il s’agit d’un système de production important. Lorsque vous essayez de déterminer la cause première après le tri initial, il est souvent difficile de savoir pourquoi l’application ou la base de données a soudainement cessé de fonctionner. Dans certains cas, la cause profonde du problème est une manque de mémoire système qui a entraîné l’arrêt d’un processus important pour que le système reste opérationnel.

Le noyau Linux alloue de la mémoire à la demande des applications exécutées sur le système. Étant donné que de nombreuses applications allouent leur mémoire à l’avance et n’utilisent souvent pas cette mémoire, le noyau a été conçu avec la possibilité de surcharger la mémoire pour augmenter l’efficacité de son utilisation. Ce modèle de sur-attribution permet au noyau d’allouer plus de mémoire qu’il n’en dispose physiquement. Si un processus utilise réellement la mémoire qui lui a été allouée, le noyau fournit alors ces ressources à l’application. Lorsqu’un trop grand nombre d’applications commencent à utiliser la mémoire qui leur a été allouée, le modèle de sur-attribution peut poser des problèmes et le noyau doit commencer à tuer les processus afin de rester opérationnel. Le mécanisme que le noyau utilise pour récupérer la mémoire sur le système est appelé out-of-memory killer, abrégé en OOM Killer.

Découvrir pourquoi un processus a été tué

Lors de la résolution d’un problème concernant une application tuée par OOM Killer, plusieurs indices peuvent éclairer quant au comment et au pourquoi le processus a été tué. Dans l'exemple suivant, nous allons examiner notre syslog pour voir si nous pouvons localiser l'origine du problème. Le processus oracle a été tué par OOM killer en raison d'une condition de mémoire insuffisance. La lettre capitale K dans Killed indique que le processus a été tué avec un signal -9. C'est généralement le signe qu'OOM Killer puisse être le coupable.




grep -i kill /var/log/messages*
host kernel: Out of Memory: Killed process 2592 (oracle).


Nous pouvons également examiner l’état d’utilisation faible ou élevé de la mémoire sur un système. Il est important de noter que ces valeurs sont exprimées en temps réel et changent en fonction de la charge de travail du système. Par conséquent, elles doivent être surveillées fréquemment avant que la pression ne soit exercée sur la mémoire. Examiner ces valeurs après la fin d’un processus n’est pas très utile et ne peut pas vraiment aider à enquêter sur les problèmes d’insuffisance de mémoire.




[root@test-sys1 ~]# free -lm
             total       used       free     shared    buffers     cached
Mem:           498         93        405          0         15         32
Low:           498         93        405
High:            0          0          0
-/+ buffers/cache:         44        453
Swap:         1023          0       1023


Sur cette machine virtuelle de test, nous avons 498 Mo de mémoire insuffisante libre. Le système n’utilise pas l’échange. Le commutateur -l affiche les statistiques de mémoire hautes et basses et le commutateur -m place la sortie en mégaoctets pour en faciliter la lecture.




[root@test-sys1 ~]# egrep 'High|Low' /proc/meminfo
HighTotal:             0 kB
HighFree:              0 kB
LowTotal:         510444 kB
LowFree:          414768 kB

Vous pouvez obtenir les mêmes données en examinant /proc/memory et en observant spécifiquement les valeurs hautes et basses. Cependant, avec cette méthode, nous n’obtenons pas d’informations d’échange à partir de la sortie et la sortie est en kilo-octets.

Une mémoire faible est une mémoire à laquelle le noyau a un accès physique direct. Une mémoire élevée est une mémoire pour laquelle le noyau n’a pas d’adresse physique directe et doit par conséquent être mappée via une adresse virtuelle. Sur les systèmes 32 bits plus anciens, vous voyez une mémoire faible et une mémoire élevée en raison de la façon dont la mémoire est mappée à une adresse virtuelle. Sur les plateformes 64 bits, l’espace d’adressage virtuel n’est pas nécessaire et toute la mémoire système est affichée en tant que mémoire faible.

Bien que le fait d'examiner /proc/memory et d'utiliser la commande free soit utile pour connaître l'utilisation « actuelle » de notre mémoire, vous pouvez souhaiter observer l'utilisation de cette mémoire sur une plus grande durée. La commande vmstat est très utile pour cela.

Dans l'exemple de la liste 1, nous avons utilisé la commande vmstat examinant nos ressources toutes les 45 secondes 10 fois. Le commutateur -S affiche nos données dans un tableau et le commutateur -M présente la sortie en mégaoctets pour en faciliter la lecture. Comme vous pouvez le voir, une opération consomme la mémoire libre, mais nous ne faisons pas encore d’échange dans cet exemple.




[root@localhost ~]# vmstat -SM 45 10
procs -----------memory-------- ---swap-- -----io-- --system-- ----cpu---------
 r  b   swpd  free  buff  cache  si   so   bi   bo   in    cs us  sy  id  wa st
 1  0      0   221   125     42   0    0    0    0   70     4  0   0  100  0  0
 2  0      0   192   133     43   0    0  192   78  432  1809  1  15   81   2 0
 2  1      0    85   161     43   0    0  624  418 1456  8407  7  73    0  21 0
 0  0      0    65   168     43   0    0  158  237  648  5655  3  28   65   4 0
 3  0      0    64   168     43   0    0    0    2 1115 13178  9  69   22   0 0
 7  0      0    60   168     43   0    0    0    5 1319 15509 13  87    0   0 0
 4  0      0    60   168     43   0    0    0    1 1387 15613 14  86    0   0 0
 7  0      0    61   168     43   0    0    0    0 1375 15574 14  86    0   0 0
 2  0      0    64   168     43   0    0    0    0 1355 15722 13  87    0   0 0
 0  0      0    71   168     43   0    0    0    6  215  1895  1   8   91   0 0


Liste 1

La sortie de vmstat peut être redirigée vers un fichier en utilisant la commande suivante. Nous pouvons même ajuster la durée et le nombre de fois afin de surveiller davantage dans la durée. Pendant l’exécution de la commande, nous pouvons consulter le fichier de sortie à tout moment pour voir les résultats.

Dans l’exemple suivant, nous examinons la mémoire toutes les 120 secondes 1 000 fois. Le message & à la fin de la ligne nous permet de l'exécution comme un processus et de retrouver notre terminal.

vmstat -SM 120 1000 > memoryusage.out &

Pour référence, la liste 2 montre une section de la page de manuel vmstat qui fournit des informations supplémentaires concernant la sortie fournie par la commande. Il s’agit uniquement d’informations liées à la mémoire ; la commande fournit également des informations sur les E/S disque et l’utilisation du processeur.




   Memory
       swpd: the amount of virtual memory used.
       free: the amount of idle memory.
       buff: the amount of memory used as buffers.
       cache: the amount of memory used as cache.
       inact: the amount of inactive memory. (-a option)
       active: the amount of active memory. (-a option)

   Swap
       si: Amount of memory swapped in from disk (/s).
       so: Amount of memory swapped to disk (/s).

Liste 2

Il existe divers autres outils pour surveiller la mémoire et les performances du système afin d’enquêter sur les problèmes de cette nature. Des outils tels que sar (System Activity Reporter) et dtrace (Dynamic Tracing) sont très utiles pour collecter des données spécifiques sur la performance du système au fil du temps. Pour davantage de visibilité, les sondes dtrace de stabilité et de stabilité de données possèdent même un déclencheur pour les conditions OOM qui se déclenchent si le noyau tue un processus en raison d'une condition OOM. Pour plus d'informations sur dtrace et sar, consultez la section « Voir aussi » du présent article.

Plusieurs éléments peuvent provoquer un événement de mémoire insuffisante autre que le manque de mémoire RAM du système et l’indisponibilité de l’espace d’échange en raison de la charge de travail. Le noyau peut ne pas être en mesure d’utiliser l’espace d’échange de manière optimale en raison du type de charge de travail sur le système. Les applications qui utilisent mlock() ou HugePages ont une mémoire qui ne peut pas être échangée sur le disque lorsque le système commence à manquer de mémoire physique. Les structures de données du noyau peuvent également occuper trop d’espace, épuiser la mémoire du système et provoquer une situation d’insuffisance de mémoire. De nombreux systèmes basés sur l’architecture NUMA peuvent rencontrer des conditions d’insuffisance de mémoire car un nœud manque de mémoire, ce qui déclenche un OOM dans le noyau alors qu’une quantité suffisante de mémoire est disponible dans les nœuds restants. Pour plus d’informations sur les conditions OOM sur les machines dotées de l’architecture NUMA, consultez la section « Voir également  » de cet article.

Configuration d’OOM Killer

OOM Killer sur Linux offre plusieurs options de configuration qui permettent aux développeurs de choisir le comportement du système lorsqu’il sera confronté à une condition de mémoire insuffisante. Ces paramètres et choix varient en fonction de l’environnement et des applications que le système a configurés sur celui-ci.

Remarque : nous vous conseillons d'effectuer des tests et des réglages dans un environnement en développement avant d'apporter des modifications sur des systèmes de production importants.

Dans certains environnements, lorsqu’un système exécute une seule tâche critique, le redémarrage lorsqu’un système s’exécute dans une condition de mémoire insuffisante peut être une option viable pour ramener le système à l’état opérationnel rapidement, sans intervention de l’administrateur. Bien que ce ne soit pas une approche optimale, la logique derrière cela est que si une application ne peut pas fonctionner car elle a été interrompue par OOM Killer, un redémarrage du système la restaure si elle démarre avec le système au démarrage. Si l’application est démarrée manuellement par un administrateur, cette option n’est pas avantageuse.

Les paramètres suivants provoquent la panique et le redémarrage du système en cas de mémoire insuffisante. Les commandes sysctl définissent ce fonctionnement en temps réel et le fait d'ajouter les paramètres à sysctl.conf permet de survivre aux redémarrages. La valeur X pour kernel.panic correspond au nombre de secondes avant le redémarrage du système. Il doit être ajusté pour répondre aux besoins de votre environnement.




sysctl vm.panic_on_oom=1
sysctl kernel.panic=X
echo "vm.panic_on_oom=1" >> /etc/sysctl.conf
echo "kernel.panic=X" >> /etc/sysctl.conf


Nous pouvons également régler la façon dont OOM Killer gère les conditions de mémoire insuffisante avec certains processus. Prenons, par exemple, le processus oracle 2592 qui a été tué précédemment. Si nous voulons faire en sorte que notre processus oracle soit moins susceptible d'être tué par OOM KILLER, nous pouvons procéder de la manière suivante.

echo -15 > /proc/2592/oom_adj

Nous pouvons faire en sorte qu'OOM Killer soit plus susceptible de tuer le processus oracle en procédant de la manière suivante.

echo 10 > /proc/2592/oom_adj

Si nous voulons exclure le processus oracle d'OOM Killer, nous pouvons faire ce qui suit, ce qui l'exclura complètement de l'OOM Killer. Il est important de noter que cela peut provoquer un comportement inattendu en fonction des ressources et de la configuration du système. Si le noyau n’est pas en mesure de tuer un processus utilisant une grande quantité de mémoire, il se déplacera vers d’autres processus disponibles. Certains de ces processus peuvent être des processus importants du système d’exploitation qui, à terme, peuvent entraîner la panne du système.

echo -17 > /proc/2592/oom_adj

Nous pouvons définir des plages valides pour oom_adj entre -16 et +15. Le paramètre -17 supprime un processus de OOM Killer. Plus le nombre est élevé, plus le processus est susceptible d’être sélectionné pour être interrompu si le système rencontre une condition de mémoire insuffisante. Il est également possible d'examiner le contenu de /proc/2592/oom_score, afin de déterminer la probabilité qu'un processus soit tué par OOM Killer. Un score de 0 indique que notre processus est supprimé d'OOM Killer. Plus le score OOM est élevé, plus un processus est susceptible d’être tué dans une condition de mémoire insuffisante.

Vous pouvez désactiver OOM Killer complètement avec la commande suivante. Ceci n’est pas recommandé pour les environnements de production, car si une condition de mémoire insuffisante se présente, un comportement inattendu peut en résulter en fonction des ressources système disponibles et de la configuration. Ce comportement inattendu peut aller de la panique du noyau à un blocage selon les ressources disponibles pour le noyau au moment de la condition de mémoire insuffisante.




sysctl vm.overcommit_memory=2
echo "vm.overcommit_memory=2" >> /etc/sysctl.conf

Pour certains environnements, ces options de configuration ne sont pas optimales et d’autres réglages et ajustements peuvent être nécessaires. La configuration de HugePages pour votre noyau peut aider à résoudre les problèmes de mémoire insuffisante en fonction des besoins des applications exécutées sur le système.

Voir également

Voici quelques ressources supplémentaires concernant HugePages, dtrace, sar et OOM pour les architectures NUMA :

À propos de l’auteur

Robert Chase est membre de l’équipe de gestion des produits Oracle Linux. Il s’occupe de Linux et des logiciels open source depuis 1996. Il travaille aussi bien avec de petits systèmes tels que les terminaux embarqués qu’avec de gros matériels de type supercalculateur.

Revision 1.0, 02/19/2013