Configuration de Out-Of-Memory Killer sous Linux pour PostgreSQL

Configuration de Out-Of-Memory Killer sous Linux pour PostgreSQL

Lorsqu'un serveur de base de données se ferme de manière inattendue sous Linux, vous devez en trouver la raison. Il peut y avoir plusieurs raisons. Par exemple, SIGSEGV — échec dû à un bug dans le serveur backend. Mais c'est rare. Le plus souvent, vous manquez simplement d’espace disque ou de mémoire. Si vous manquez d'espace disque, il n'y a qu'une seule issue : libérer de l'espace et redémarrer la base de données.

Tueur de mémoire insuffisante

Lorsqu'un serveur ou un processus manque de mémoire, Linux propose 2 solutions : planter tout le système ou mettre fin au processus (application) qui consomme de la mémoire. Il est bien sûr préférable de mettre fin au processus et d'éviter que le système d'exploitation ne plante. En un mot, Out-Of-Memory Killer est un processus qui tue une application pour empêcher le noyau de planter. Cela sacrifie l’application pour faire fonctionner le système d’exploitation. Voyons d'abord comment fonctionne OOM et comment le contrôler, puis voyons comment OOM Killer décide quelle application mettre fin.

L'une des tâches principales de Linux est d'allouer de la mémoire aux processus lorsqu'ils le demandent. En règle générale, un processus ou une application demande de la mémoire au système d'exploitation, mais ne l'utilise pas pleinement. Si le système d'exploitation distribue de la mémoire à tous ceux qui la demandent mais n'ont pas l'intention de l'utiliser, très vite la mémoire s'épuisera et le système tombera en panne. Pour éviter cela, le système d'exploitation réserve de la mémoire pour le processus, mais ne la libère pas réellement. La mémoire n'est allouée que lorsqu'un processus va réellement l'utiliser. Il arrive que le système d'exploitation ne dispose pas de mémoire libre, mais il attribue de la mémoire à un processus, et lorsqu'un processus en a besoin, le système d'exploitation l'alloue s'il le peut. L'inconvénient est que parfois le système d'exploitation réserve de la mémoire, mais au bon moment, il n'y a pas de mémoire libre et le système plante. Le MOO joue un rôle important dans ce scénario et met fin aux processus pour empêcher le noyau de paniquer. Lorsqu'un processus PostgreSQL est forcé de se terminer, un message apparaît dans le journal :

Out of Memory: Killed process 12345 (postgres).

Si le système manque de mémoire et ne peut pas être libéré, la fonction est appelée out_of_memory. À ce stade, il ne lui reste plus qu'une chose à faire : terminer un ou plusieurs processus. OOM-killer doit-il mettre fin au processus immédiatement ou peut-il attendre ? Évidemment, lorsque out_of_memory est appelé, cela est dû à l'attente d'une opération d'E/S ou d'une pagination sur le disque. Par conséquent, le tueur de MOO doit d'abord effectuer des vérifications et, sur cette base, décider que le processus doit être terminé. Si toutes les vérifications ci-dessous sont positives, OOM mettra fin au processus.

Sélection du processus

Lorsque la mémoire est épuisée, la fonction est appelée out_of_memory(). Il a une fonction select_bad_process(), qui reçoit une évaluation de la fonction badness(). Le « pire » processus sera ciblé. Fonction badness() sélectionne un processus selon certaines règles.

  1. Le noyau a besoin d'un minimum de mémoire pour lui-même.
  2. Vous devez libérer beaucoup de mémoire.
  3. Il n'est pas nécessaire d'arrêter les processus qui utilisent peu de mémoire.
  4. Des processus minimaux doivent être complétés.
  5. Des algorithmes complexes qui augmentent les chances d'achèvement des processus que l'utilisateur souhaite réaliser lui-même.

Après avoir effectué toutes ces vérifications, OOM examine le score (oom_score). MOO attribue oom_score chaque processus, puis multiplie cette valeur par la quantité de mémoire. Les processus avec des valeurs plus élevées sont plus susceptibles d'être victimes du OOM Killer. Les processus associés à l'utilisateur root ont un score inférieur et sont moins susceptibles d'être forcés de s'arrêter.

postgres=# SELECT pg_backend_pid();
pg_backend_pid 
----------------
    3813
(1 row)

L'ID du processus Postgres est 3813, donc dans un autre shell il est possible d'obtenir le score en utilisant ce paramètre du noyau oom_score:

vagrant@vagrant:~$ sudo cat /proc/3813/oom_score
2

Si vous ne voulez pas du tout qu'OOM-Killer tue le processus, il existe une autre option du noyau : oom_score_adj. Ajoutez une valeur négative importante pour réduire les chances de terminer un processus que vous appréciez.

sudo echo -100 > /proc/3813/oom_score_adj

Pour définir une valeur oom_score_adj, définissez OOMScoreAdjust dans le bloc de service :

[Service]
OOMScoreAdjust=-1000

Ou utiliser oomprotect dans une équipe rcctl.

rcctl set <i>servicename</i> oomprotect -1000

Forcer l'arrêt d'un processus

Lorsqu'un ou plusieurs processus sont déjà sélectionnés, OOM-Killer appelle la fonction oom_kill_task(). Cette fonction envoie un signal de fin au processus. En cas de manque de mémoire oom_kill() Appelle cette fonction pour envoyer un signal SIGKILL au processus. Un message est écrit dans le journal du noyau.

Out of Memory: Killed process [pid] [name].

Comment contrôler OOM-Killer

Sous Linux, vous pouvez activer ou désactiver OOM-Killer (bien que ce dernier ne soit pas recommandé). Pour activer ou désactiver, utilisez le paramètre vm.oom-kill. Pour activer OOM-Killer au moment de l'exécution, exécutez la commande sysctl.

sudo -s sysctl -w vm.oom-kill = 1

Pour désactiver OOM-Killer, spécifiez la valeur 0 dans la même commande :

sudo -s sysctl -w vm.oom-kill = 0

Le résultat de cette commande ne sera pas sauvegardé pour toujours, mais seulement jusqu'au premier redémarrage. Si vous avez besoin de plus de persistance, ajoutez cette ligne au fichier /etc/sysctl.conf:

echo vm.oom-kill = 1 >>/etc/sysctl.conf

Une autre façon d'activer et de désactiver est d'écrire une variable panic_on_oom. La valeur peut toujours être enregistrée /proc.

$ cat /proc/sys/vm/panic_on_oom
0

Si vous définissez la valeur sur 0, lorsque la mémoire sera épuisée, il n'y aura pas de panique du noyau.

$ echo 0 > /proc/sys/vm/panic_on_oom

Si vous définissez la valeur sur 1, lorsque la mémoire sera épuisée, une panique du noyau se produira.

echo 1 > /proc/sys/vm/panic_on_oom

OOM-Killer ne peut pas seulement être activé et désactivé. Nous avons déjà dit que Linux peut réserver plus de mémoire aux processus que celle disponible sans l'allouer réellement, et ce comportement est contrôlé par un paramètre du noyau Linux. La variable en est responsable vm.overcommit_memory.

Vous pouvez lui spécifier les valeurs suivantes :

0: Le noyau décide lui-même s'il doit réserver trop de mémoire. C'est la valeur par défaut sur la plupart des versions de Linux.
1: Le noyau réservera toujours de la mémoire supplémentaire. C'est risqué, car la mémoire peut s'épuiser, car, très probablement, les processus en auront un jour besoin.
2: le noyau ne réservera pas plus de mémoire que spécifié dans le paramètre overcommit_ratio.

Avec ce paramètre, vous spécifiez le pourcentage de mémoire pouvant être sur-réservé. S'il n'y a pas de place pour cela, aucune mémoire n'est allouée et la réservation sera refusée. Il s'agit de l'option la plus sûre recommandée pour PostgreSQL. OOM-Killer est affecté par un autre élément - la capacité d'échange, qui est contrôlée par la variable cat /proc/sys/vm/swappiness. Ces valeurs indiquent au noyau comment gérer la pagination. Plus la valeur est élevée, moins il est probable que le MOO termine le processus, mais en raison des opérations d'E/S, cela a un impact négatif sur la base de données. Et vice versa : plus la valeur est faible, plus la probabilité d'intervention de OOM-Killer est élevée, mais les performances de la base de données sont également plus élevées. La valeur par défaut est 60, mais si la base de données entière tient en mémoire, il est préférable de définir la valeur sur 1.

Les résultats de

Ne laissez pas le "tueur" d'OOM-Killer vous effrayer. Dans ce cas, le tueur sera le sauveur de votre système. Il « tue » les pires processus et évite au système de planter. Pour éviter d'avoir à utiliser OOM-Killer pour terminer PostgreSQL, définissez-le sur vm.overcommit_memory valeur 2. Cela ne garantit pas que OOM-Killer n'aura pas à intervenir, mais cela réduira la probabilité de forcer l'arrêt du processus PostgreSQL.

Source: habr.com

Ajouter un commentaire