Configurazione di Out-Of-Memory Killer in Linux per PostgreSQL

Configurazione di Out-Of-Memory Killer in Linux per PostgreSQL

Quando un server database si chiude inaspettatamente in Linux, è necessario trovarne il motivo. Ci possono essere diverse ragioni. Per esempio, SIGSEGV — errore dovuto a un bug nel server backend. Ma questo è raro. Molto spesso, semplicemente si esaurisce lo spazio su disco o la memoria. Se esaurisci lo spazio su disco, c'è solo una via d'uscita: liberare spazio e riavviare il database.

Killer senza memoria

Quando un server o un processo esaurisce la memoria, Linux offre 2 soluzioni: mandare in crash l'intero sistema o terminare il processo (applicazione) che sta consumando memoria. È meglio, ovviamente, terminare il processo e evitare che il sistema operativo si blocchi. In poche parole, Out-Of-Memory Killer è un processo che uccide un'applicazione per evitare che il kernel si blocchi. Sacrifica l'applicazione per mantenere il sistema operativo in esecuzione. Parliamo prima di come funziona OOM e di come controllarlo, quindi vediamo come OOM Killer decide quale applicazione terminare.

Uno dei compiti principali di Linux è allocare memoria ai processi quando lo richiedono. In genere, un processo o un'applicazione richiede memoria dal sistema operativo, ma non la utilizza completamente. Se il sistema operativo fornisce memoria a tutti coloro che ne fanno richiesta ma non hanno intenzione di usarla, molto presto la memoria si esaurirà e il sistema fallirà. Per evitare ciò, il sistema operativo riserva memoria per il processo, ma in realtà non la rilascia. La memoria viene allocata solo quando un processo la utilizzerà effettivamente. Accade che il sistema operativo non abbia memoria libera, ma assegna memoria a un processo e, quando un processo ne ha bisogno, il sistema operativo la alloca se può. Lo svantaggio è che a volte il sistema operativo riserva memoria, ma al momento giusto non c'è memoria libera e il sistema si blocca. OOM svolge un ruolo importante in questo scenario e termina i processi per evitare che il kernel vada in panico. Quando un processo PostgreSQL viene terminato forzatamente, nel registro viene visualizzato un messaggio:

Out of Memory: Killed process 12345 (postgres).

Se la memoria del sistema è insufficiente e non può essere liberata, viene richiamata la funzione out_of_memory. A questo punto le resta solo una cosa da fare: completare uno o più processi. OOM-killer deve terminare immediatamente il processo o può attendere? Ovviamente, quando viene chiamato out_of_memory, è dovuto all'attesa di un'operazione di I/O o di paginazione su disco. Pertanto, l'OOM killer deve prima effettuare dei controlli e, in base ad essi, decidere che il processo deve essere terminato. Se tutti i controlli seguenti risultano positivi, OOM terminerà il processo.

Selezione del processo

Quando la memoria si esaurisce, viene richiamata la funzione out_of_memory(). Ha una funzione select_bad_process(), che riceve una valutazione dalla funzione badness(). Verrà preso di mira il processo “peggiore”. Funzione badness() seleziona un processo secondo determinate regole.

  1. Il kernel necessita di una memoria minima per se stesso.
  2. È necessario liberare molta memoria.
  3. Non è necessario terminare i processi che utilizzano poca memoria.
  4. È necessario completare processi minimi.
  5. Algoritmi complessi che aumentano le possibilità di completamento di quei processi che l'utente stesso desidera completare.

Dopo aver completato tutti questi controlli, OOM esamina il punteggio (oom_score). OOM assegna oom_score ogni processo, quindi moltiplica questo valore per la quantità di memoria. I processi con valori più grandi hanno maggiori probabilità di cadere vittime dell'OOM Killer. I processi associati all'utente root hanno un punteggio inferiore e hanno meno probabilità di essere forzati a terminare.

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

L'ID del processo Postgres è 3813, quindi in un'altra shell è possibile ottenere il punteggio utilizzando questo parametro del kernel oom_score:

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

Se non vuoi che OOM-Killer interrompa del tutto il processo, c'è un'altra opzione del kernel: oom_score_adj. Aggiungi un valore negativo elevato per ridurre le possibilità di completare un processo che apprezzi.

sudo echo -100 > /proc/3813/oom_score_adj

Per impostare un valore oom_score_adj, imposta OOMScoreAdjust nel blocco servizi:

[Service]
OOMScoreAdjust=-1000

Oppure usa oomprotect in una squadra rcctl.

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

Forzare la conclusione di un processo

Quando uno o più processi sono già selezionati, OOM-Killer richiama la funzione oom_kill_task(). Questa funzione invia un segnale di terminazione al processo. In caso di carenza di memoria oom_kill() Chiama questa funzione per inviare un segnale SIGKILL al processo. Viene scritto un messaggio nel log del kernel.

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

Come controllare OOM-Killer

Su Linux puoi abilitare o disabilitare OOM-Killer (sebbene quest'ultimo non sia consigliato). Per abilitare o disabilitare utilizzare il parametro vm.oom-kill. Per abilitare OOM-Killer in fase di runtime, esegui il comando sysctl.

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

Per disabilitare OOM-Killer, specificare il valore 0 nello stesso comando:

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

Il risultato di questo comando non verrà salvato per sempre, ma solo fino al primo riavvio. Se hai bisogno di maggiore persistenza, aggiungi questa riga al file /etc/sysctl.conf:

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

Un altro modo per abilitare e disabilitare è scrivere una variabile panic_on_oom. Il valore può sempre essere registrato /proc.

$ cat /proc/sys/vm/panic_on_oom
0

Se imposti il ​​valore su 0, quando la memoria si esaurisce, non si verificherà alcun panico nel kernel.

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

Se imposti il ​​valore su 1, quando la memoria si esaurisce, si verificherà un panico del kernel.

echo 1 > /proc/sys/vm/panic_on_oom

OOM-Killer non può solo essere acceso e spento. Abbiamo già detto che Linux può riservare per i processi più memoria di quella disponibile senza effettivamente allocarla, e questo comportamento è controllato da un parametro del kernel Linux. La variabile ne è responsabile vm.overcommit_memory.

È possibile specificare i seguenti valori:

0: Il kernel stesso decide se riservare troppa memoria. Questa è l'impostazione predefinita sulla maggior parte delle versioni di Linux.
1: Il kernel riserverà sempre memoria extra. Questo è rischioso, perché la memoria potrebbe esaurirsi, perché, molto probabilmente, un giorno i processi ne avranno bisogno.
2: il kernel non riserverà più memoria di quella specificata nel parametro overcommit_ratio.

Con questo parametro si specifica la percentuale di memoria che può essere riservata in eccesso. Se non c'è spazio, non verrà allocata memoria e la prenotazione verrà negata. Questa è l'opzione più sicura consigliata per PostgreSQL. OOM-Killer è influenzato da un altro elemento: la capacità di scambio, che è controllata dalla variabile cat /proc/sys/vm/swappiness. Questi valori dicono al kernel come gestire il paging. Più alto è il valore, meno è probabile che OOM termini il processo, ma a causa delle operazioni di I/O ha un impatto negativo sul database. E viceversa: più basso è il valore, maggiore è la probabilità dell'intervento di OOM-Killer, ma anche le prestazioni del database sono maggiori. Il valore predefinito è 60, ma se l'intero database entra in memoria, è meglio impostare il valore su 1.

Risultati di

Non lasciare che il "killer" di OOM-Killer ti spaventi. In questo caso, l'assassino sarà il salvatore del tuo sistema. “Uccide” i processi peggiori e salva il sistema dal crash. Per evitare di dover utilizzare OOM-Killer per terminare PostgreSQL, impostare su vm.overcommit_memory valore 2. Ciò non garantisce che OOM-Killer non debba intervenire, ma ridurrà la probabilità di forzare la chiusura del processo PostgreSQL.

Fonte: habr.com

Aggiungi un commento