
Quando un server di database in Linux termina inaspettatamente, è necessario trovare la causa. Ci possono essere diverse ragioni. Ad esempio, SIGSEGV — un guasto dovuto a un bug nel server backend. Tuttavia, questo è raro. Nella maggior parte dei casi, si esaurisce semplicemente lo spazio su disco o la memoria. Se lo spazio su disco è finito, l'unica soluzione è liberare spazio e riavviare il database.
Out-Of-Memory Killer
Quando a server un processo o servizio termina la memoria, Linux offre 2 soluzioni: far crollare l'intero sistema o terminare il processo (applicazione) che consuma memoria. È preferibile terminare il processo e salvare il sistema operativo da un arresto anomalo. In poche parole, l'Out-Of-Memory Killer è un processo che termina un'applicazione per salvare il kernel da un crash. Sacrifica l'applicazione per mantenere attivo il sistema operativo. Discutiamo prima di come funziona l'OOM e di come controllarlo, e poi vediamo come l'OOM Killer decide quale applicazione terminare.
Uno dei compiti principali di Linux è assegnare memoria ai processi quando ne fanno richiesta. Di solito, un processo o un'applicazione richiede memoria al sistema operativo, ma non la utilizza completamente. Se il sistema operativo fornisse memoria a tutti coloro che la richiedono ma non la utilizzano, ben presto la memoria si esaurirebbe e il sistema andrebbe in crisi. Per evitare ciò, il sistema operativo riserva memoria per il processo ma in realtà non la eroga. La memoria viene assegnata solo quando il processo intende effettivamente utilizzarla. A volte, il sistema operativo non ha memoria disponibile, ma fissa della memoria per il processo, e quando il processo ne ha bisogno, il sistema operativo la fornisce se è possibile. Il problema è che a volte il sistema operativo riserva memoria, ma nel momento del bisogno non c'è memoria disponibile, causando un fallimento del sistema. L'OOM gioca un ruolo importante in questo scenario e termina i processi per proteggere il kernel dall'errore di panico. Quando un processo PostgreSQL viene terminato forzatamente, appare nel log il messaggio:
Out of Memory: Terminato il processo 12345 (postgres).Se c'è poca memoria nel sistema e non è possibile liberarla, viene chiamata la funzione out_of_memory. A questo punto, resta solo una cosa da fare: terminare uno o più processi. OOM-killer deve terminare il processo immediatamente o è possibile aspettare? È evidente che, quando viene attivato l'out_of_memory, ciò è legato a un'attesa di operazioni di input/output o di swapping di pagine su disco. Pertanto, OOM-killer deve prima eseguire controlli e, sulla base di essi, decidere quale processo terminare. Se tutti i controlli seguenti danno esito positivo, OOM terminerà il processo.
Scelta del processo
Quando la memoria si esaurisce, viene chiamata la funzione out_of_memory(). Essa contiene la funzione select_bad_process(), che riceve una valutazione dalla funzione badness(). Sarà terminato il processo 'più cattivo'. La funzione badness() sceglie il processo secondo determinate regole.
- Il kernel ha bisogno di un minimo di memoria per sé.
- È necessario liberare molta memoria.
- Non è necessario terminare i processi che utilizzano poca memoria.
- È necessario terminare almeno alcuni processi.
- Algoritmi complessi che aumentano le probabilità di terminazione per quei processi che l'utente desidera terminare.
Dopo aver eseguito tutti questi controlli, OOM esamina la valutazione (oom_score). OOM assegna oom_score ad ogni processo, poi moltiplica questo valore per la quantità di memoria. I processi con valori più alti hanno maggiori probabilità di diventare vittime di OOM Killer. I processi legati a un utente privilegiato hanno una valutazione più bassa e minori probabilità di essere terminati forzatamente.
postgres=# SELECT pg_backend_pid();
pg_backend_pid
----------------
3813
(1 row)L'identificativo del processo Postgres è 3813, quindi in un'altra shell si può ottenere la valutazione utilizzando questo parametro del kernel. oom_score:
vagrant@vagrant:~$ sudo cat /proc/3813/oom_score
2Se non vuoi affatto che OOM-Killer termini il processo, c'è un altro parametro del kernel: oom_score_adj. Aggiungi un grande valore negativo per ridurre le probabilità che il tuo processo importante venga terminato.
sudo echo -100 > /proc/3813/oom_score_adjPer impostare il valore oom_score_adj, imposta OOMScoreAdjust nel blocco del servizio:
[Service]
OOMScoreAdjust=-1000Oppure usa oomprotect nel comando rcctl.
rcctl set servicename oomprotect -1000Terminazione forzata del processo
Quando uno o più processi sono già stati scelti, OOM-Killer chiama la funzione oom_kill_task(). Questa funzione invia un segnale di terminazione al processo. In caso di mancanza di memoria oom_kill() chiama questa funzione per inviare il segnale SIGKILL al processo. Un messaggio viene registrato nel log del kernel.
Out of Memory: processo terminato [pid] [name].Come controllare l'OOM-Killer
In Linux, è possibile abilitare e disabilitare l'OOM-Killer (anche se quest'ultima opzione non è consigliata). Utilizzare il parametro vm.oom-kill. Per abilitare l'OOM-Killer in esecuzione, eseguire il comando sysctl.
sudo -s sysctl -w vm.oom-kill=1Per disabilitare l'OOM-Killer, impostare il valore a 0 nello stesso comando:
sudo -s sysctl -w vm.oom-kill=0Il risultato di questo comando non sarà permanente, ma solo fino al primo riavvio. Se è necessario maggiore permanenza, aggiungere questa riga al file /etc/sysctl.conf:
echo vm.oom-kill=1 >> /etc/sysctl.confUn altro modo per abilitare e disabilitare è scrivere la variabile panic_on_oom. È possibile controllare il valore in /proc.
$ cat /proc/sys/vm/panic_on_oom
0Se si imposta il valore a 0, quando la memoria finisce non ci sarà kernel panic.
$ echo 0 > /proc/sys/vm/panic_on_oomSe si imposta il valore a 1, quando la memoria finisce si verifica un kernel panic.
echo 1 > /proc/sys/vm/panic_on_oomL'OOM-Killer può essere attivato e disattivato. Abbiamo già detto che Linux può riservare più memoria per i processi di quanta ne abbia effettivamente, ma non rilasciarla di fatto, e questo comportamento è gestito da un parametro del kernel Linux. Questo è controllato dalla variabile vm.overcommit_memory.
Per essa è possibile specificare i seguenti valori:
0: il kernel decide autonomamente se è opportuno riservare troppa memoria. Questo è il valore predefinito nella maggior parte delle versioni di Linux.
1: il kernel riserverà sempre memoria extra. Questo è rischioso, poiché la memoria potrebbe terminare, dato che è probabile che in qualche momento i processi richiedano la quantità assegnata.
2: il kernel non riserverà più memoria di quanto specificato nel parametro overcommit_ratio.
In questo parametro si specifica la percentuale di memoria per la quale è consentita la riserva eccessiva. Se non c'è spazio per essa, non viene assegnata memoria e la riserva viene negata. Questa è l'opzione più sicura, consigliata per PostgreSQL. Un altro elemento che influisce sull'OOM-Killer è la possibilità di swap, gestita dalla variabile cat /proc/sys/vm/swappiness. Questi valori indicano al kernel come gestire lo swapping delle pagine. Maggiore è il valore, minore è la probabilità che l'OOM termini il processo, ma a causa delle operazioni di input-output, questo ha un impatto negativo sul database. E viceversa: minore è il valore, maggiore è la probabilità di intervento dell'OOM-Killer, ma anche le prestazioni del database sono migliori. Il valore di default è 60, ma se l'intero database può essere caricato in memoria, è meglio impostare il valore a 1.
Risultati
Non lasciatevi spaventare dal «killer» nell'OOM-Killer. In questo caso, il killer sarà il salvatore del vostro sistema. «Uccide» i processi più problematici e salva il sistema da un arresto anomalo. Per evitare di dover ricorrere all'OOM-Killer per terminare PostgreSQL, impostate il vm.overcommit_memory valore a 2. Ciò non garantisce che l'OOM-Killer non debba intervenire, ma ridurrà la probabilità di terminazione forzata del processo PostgreSQL.
Fonte: habr.com
