Messa a punto di Linux OOM Killer per VPS: una guida pratica
12 min di lettura - 8 giugno 2026

Mettete a punto l'OOM killer di Linux sul vostro VPS per proteggere database e SSH, bloccare i processi in fuga con i cgroup e impedire che il servizio sbagliato venga ucciso.
Ottimizzazione dell'OOM killer di Linux per VPS
L'OOM killer di Linux è l'ultima risorsa del kernel quando la memoria si esaurisce: seleziona un processo e lo termina per mantenere in vita il sistema. Su un VPS, dove la RAM è limitata e non c'è alcun margine di manovra, la scelta predefinita è spesso quella sbagliata. Il database viene terminato, un processo in esecuzione da tempo sopravvive e l'utente deve capire il motivo. Questa guida spiega come l'OOM killer valuta i processi, come orientare tale valutazione verso i servizi critici e come utilizzare i cgroup in modo che un singolo processo fuori controllo non possa causare il crash del resto del sistema.
Come l'OOM killer sceglie una vittima
Quando il kernel non riesce a recuperare memoria sufficiente tramite l'evacuazione della cache di pagina o lo swap, invoca l'OOM killer. Ogni processo ha un oom_score punteggio compreso tra 0 e 1000, derivato principalmente dalla sua Resident Set Size (RSS) e dall'utilizzo dello swap. Il processo con il punteggio più alto riceve un SIGKILL.
L'RSS domina il calcolo, motivo per cui l'eliminazione ricade quasi sempre sul processo che consuma più memoria. Spesso si tratta del database, del server delle applicazioni o di qualsiasi processo a lunga durata che sta svolgendo il lavoro più utile. Il processo che ha effettivamente innescato l'allocazione, l'"invoker", è raramente quello terminato.
Esistono due tipi di eventi OOM che è necessario distinguere:
- OOM globale: l'host (o il tuo VPS nel suo complesso) ha esaurito la RAM e lo swap. Il kernel esamina ogni processo e termina quello con il punteggio più alto.
- OOM cgroup: un cgroup specifico ha raggiunto il limite di memoria. Il kernel termina solo i processi all'interno di quel cgroup, anche se il resto del sistema ha memoria disponibile.
Se avete configurato i limiti delle unità systemd o state eseguendo container, la maggior parte dei vostri eventi OOM saranno OOM cgroup. Questa è una cosa positiva: il raggio d'azione è contenuto.
Individuare la pressione sulla memoria prima del crash
Gli eventi OOM non sono quasi mai improvvisi. Di solito c'è prima un periodo in cui la pressione aumenta, e l'obiettivo del monitoraggio è individuarla in quel lasso di tempo.
free -h fornisce la vista di sistema. La colonna che conta è available, non free: tiene conto della cache delle pagine recuperabile e riflette ciò che è effettivamente possibile allocare senza ricorrere allo swapping. Mantenere MemAvailable sopra circa il 10-15% del MemTotal al picco di carico.
Per l'attribuzione per processo, ordina per RSS:
ps aux --sort=-%mem | head -10Oppure usa htop e ordina per RES. I valori che vedete qui alimentano direttamente il punteggio del kernel, quindi le voci in cima alla lista sono i target OOM più probabili.
Sui kernel 4.20 e successivi, le informazioni sullo stallo da pressione (Pressure Stall Information) costituiscono un sistema di allerta precoce che vale la pena integrare nel monitoraggio:
cat /proc/pressure/memoryIl some avg10 figura rappresenta la percentuale di tempo in cui almeno un'attività è rimasta in stallo in attesa di memoria negli ultimi dieci secondi. Un valore inferiore al 5% va bene. Valori sostenuti superiori al 10% indicano che il sistema sta dedicando tempo reale bloccato nel recupero della memoria, e un kill per OOM è plausibile.
Lo swap thrashing viene visualizzato in vmstat 1 come non zero si e so colonne non pari a zero che si mantengono nel tempo. Una piccola quantità di swap residente è innocua. Lo swap-in e lo swap-out costanti non lo sono.
Protezione dei processi critici con oom_score_adj
Il punteggio calcolato dal kernel può essere modificato per ogni singolo processo tramite oom_score_adj, su una scala da -1000 (immune) a +1000 (uccidimi per primo). La regolazione viene aggiunta direttamente al punteggio finale.
Per una modifica una tantum su un processo in esecuzione:
echo -500 | sudo tee /proc/$(pidof sshd)/oom_score_adjPer qualsiasi cosa si voglia mantenere tra un riavvio e l'altro, impostarla nell'unità systemd. È il posto giusto per sshd, il database e qualsiasi altra cosa che non ci si può permettere di perdere:
[Service]
OOMScoreAdjust=-900Impostazioni predefinite sensate da cui partire:
- sshd: -1000. Se si perde l’accesso remoto durante una crisi di memoria, il ripristino diventa molto più difficile.
- MySQL, PostgreSQL, Redis: da -800 a -900. Protezione forte senza renderli completamente intoccabili in una situazione davvero catastrofica.
- Worker delle applicazioni, lavori batch, attività cron: da +100 a +500. Questi sono i processi che preferiresti vedere terminati piuttosto che il tuo database.
Non impostare tutto a -1000. Se nulla è terminabile, il kernel finirà per andare in panico o bloccarsi, il che è peggio.
Limitazione della memoria con cgroups e systemd
La regolazione dei punteggi influenza chi viene eliminato. I cgroup influenzano se l'eliminazione globale avviene o meno. Assegnando a ciascun servizio un limite massimo rigido, si concentrano i problemi di memoria in un singolo cgroup, invece di lasciare che un singolo processo esaurisca l'intero VPS.
In un file di unità systemd:
[Service]
MemoryHigh=400M
MemoryMax=512M
OOMPolicy=stop
Restart=on-failure
RestartSec=5sMemoryHigh è un limite flessibile: il kernel recupera in modo aggressivo le pagine dal cgroup al di sopra di questo punto, ma non termina nulla. MemoryMax è il limite massimo rigido. Se il cgroup cerca di allocare oltre questo limite, il kernel termina un processo all'interno del cgroup. Con Restart=on-failure il servizio si riavvia immediatamente.
Su cgroup v2 (Ubuntu 22.04 e versioni successive, Debian recente, RHEL 9), memory.oom.group termina tutti i processi nel cgroup contemporaneamente invece di lasciare processi orfani. Utile per servizi multiprocesso come i pool PHP-FPM dove un gruppo terminato a metà funzionerebbe in modo anomalo.
Alcune note specifiche per l'applicazione che vale la pena applicare:
- PHP-FPM: impostare
pm = ondemandsu istanze VPS di piccole dimensioni e dimensionarepm.max_childrenin base all'RSS medio per worker, non a quello predefinito. Un pool dimensionato per 4 GB di margine su un VPS da 2 GB andrà in OOM la prima volta che si riempie. - Node.js: limitare l'heap V8 con
--max-old-space-size=512(in MB). Senza questo limite, Node continuerà a crescere fino a quando il kernel non interverrà. - MySQL e PostgreSQL:
innodb_buffer_pool_sizeeshared_buffersdovrebbero lasciare spazio libero per la cache delle pagine del sistema operativo, la memoria di connessione e qualsiasi altro tenant presente sul server. Le impostazioni predefinite presuppongono un server dedicato.
Lettura dei log dopo un evento OOM
Quando si attiva l'OOM killer, il kernel scarica un rapporto dettagliato nel buffer circolare. Estrarlo con:
dmesg -T | grep -iE 'killed process|out of memory'
journalctl -k --grep='Out of memory'Il blocco da leggere attentamente inizia con l'invoker e termina con la vittima. Il kernel stampa un elenco completo delle attività con l'RSS di ciascun processo, l'utilizzo dello swap e il oom_score_adj. Vale la pena controllare tre cose:
- Il vincolo.
CONSTRAINT_NONEsignifica un OOM globale,CONSTRAINT_MEMCGindica che un cgroup ha raggiunto il limite. La soluzione varia a seconda del caso Free swap. Se si tratta di0kB, sia la RAM che lo swap sono esauriti. Aggiungere spazio di swap, aumentareMemoryMaxil limite del processo responsabile, oppure ridurre la concorrenza.- Il punteggio della vittima rispetto a tutto il resto. Se il punteggio della vittima non è molto più alto di quello dei processi immediatamente successivi, i tuoi
oom_score_adjvalori non stanno funzionando a sufficienza. Aumenta il divario.
Per gli OOM dei cgroup in particolare, il contatore di kill risiede memory.events all'interno del cgroup:
cat /sys/fs/cgroup/system.slice/mysql.service/memory.eventsUn oom_kill significa che il servizio sta raggiungendo ripetutamente il proprio limite. Questo è un segnale per aumentare MemoryMax, analizzare il carico di lavoro o spostare il servizio su un piano più ampio, non continuare a riavviarlo in un ciclo infinito.
Conclusione
Ottimizzare l'OOM killer non significa eliminarlo. Significa controllare quale processo ne paghi le conseguenze quando la memoria si esaurisce e ridurre l'impatto quando ciò accade. Il modello che funziona in produzione:
- Proteggi con Score i servizi che non puoi permetterti di perdere, in particolare sshd e i tuoi database.
- Limitate tutto il resto
MemoryMaxin un'unità systemd in modo che un singolo processo fuori controllo comporti un singolo riavvio, non un'interruzione del servizio. - Monitorate il PSI e
MemAvailablepiuttosto che aspettaredmesgche ti raccontino la storia a posteriori. - Lascia il 15-20% di RAM come margine. L'ottimizzazione non può compensare un VPS che è semplicemente troppo piccolo per il carico di lavoro.
Se la pressione sulla memoria è strutturale piuttosto che configurabile, è necessaria più RAM o uno storage supportato da swap più veloce. I piani VPS di FDC Servers girano su AMD EPYC con storage NVMe, il che mantiene le letture supportate dallo swap abbastanza veloci da impedire che brevi picchi di memoria si trasformino in arresti del sistema.

Messa a punto di Linux OOM Killer per VPS: una guida pratica
Mettete a punto l'OOM killer di Linux sul vostro VPS per proteggere database e SSH, bloccare i processi in fuga con i cgroup e impedire che il servizio sbagliato venga ucciso.
12 min di lettura - 8 giugno 2026
Controllo del traffico (tc) di Linux: una guida pratica
12 min di lettura - 5 giugno 2026

Avete domande o avete bisogno di una soluzione personalizzata?
Opzioni flessibili
Portata globale
Distribuzione immediata
Opzioni flessibili
Portata globale
Distribuzione immediata