Gestione della memoria in Linux: Swap, OOM Killer e Cgroups
12 min di lettura - 31 maggio 2026

Come funzionano insieme Linux swap, OOM killer e cgroup, con esempi di configurazione per database, server web e host VPS multi-tenant.
Spiegazione della gestione della memoria in Linux: swap, OOM killer e cgroups
Linux gestisce la memoria in modo diverso rispetto alla maggior parte dei sistemi operativi. Un elevato utilizzo della RAM non è sempre un problema: il kernel utilizza attivamente la memoria libera per la cache al fine di velocizzare le letture dal disco. Tuttavia, quando si crea una reale pressione sulla memoria, entrano in gioco tre meccanismi: swap, OOM killer e cgroups. Comprendere come si comporta ciascuno di essi e come configurarli fa la differenza tra un server che si degrada gradualmente sotto carico e uno che si blocca senza preavviso.
Come Linux gestisce le pagine di memoria
Ogni processo viene eseguito nel proprio spazio di indirizzamento virtuale, fino a 128 TB sui sistemi a 64 bit. Il kernel mappa questi indirizzi virtuali alla RAM fisica tramite tabelle di pagina, con il Translation Lookaside Buffer (TLB) che memorizza nella cache le ricerche recenti. Un accesso TLB richiede circa 1 nanosecondo; un mancato accesso costa 20-100 nanosecondi, il che si somma in carichi di lavoro ad alta intensità di memoria come i database.
La memoria fisica è suddivisa in pagine da 4 KB e il kernel le divide in due categorie:
- Pagine supportate da file — legate ai file su disco. Il kernel può scartare quelle pulite o svuotare quelle sporche senza bisogno di swap.
- Pagine anonime: memoria heap e stack senza file di supporto. Queste devono essere scritte nello swap prima che il kernel possa liberarle.
Su server con elevata richiesta di memoria, una grande percentuale di pagine anonime comporta un ricorso precoce allo swap. Osservare lo si (swap in) e so (swap out) in vmstat 1 : valori persistenti diversi da zero sono il primo segnale che il sistema è sotto pressione.
Per il monitoraggio, usa lo strumento giusto per il lavoro:
| Strumento | Ideale per | Metrica chiave |
|---|---|---|
free -h | Panoramica rapida dell'intero sistema | available colonna |
vmstat 1 | Monitoraggio in tempo reale dello swap e dell'I/O | si, so |
htop | Visualizzazione interattiva per processo | Barre di memoria, elenco dei processi |
smem | Utilizzo accurato per processo | USS (dimensione set univoca) |
/proc/meminfo | Dettagli a livello di kernel | MemAvailable, Dirty, Slab |
Un errore comune: osservare la free colonna free -h e farsi prendere dal panico. La available colonna è quella che conta. Include la memoria che il kernel può recuperare dalla cache su richiesta. Un server che mostra solo 512 MB liberi ma 5 GB disponibili non è in difficoltà.
Quando la memoria scende al di sotto di una soglia, il kswapd demone del kernel inizia a recuperare pagine in background. Se ciò non basta, il kernel passa al recupero diretto, bloccando i processi finché le pagine non vengono liberate. È da qui che derivano i picchi di latenza. Imposta un avviso quando MemAvailable scende al di sotto del 10–15% della RAM totale, in modo da avere il tempo di reagire.
Configurazione dello swap
Lo swap è un'area del disco — una partizione o un file — in cui il kernel sposta le pagine anonime inattive quando la RAM si riempie. Il divario di velocità è significativo: la RAM DDR4 ha una latenza di circa 100 ns, mentre gli SSD NVMe sono intorno ai 100.000 ns e gli SSD SATA più vicini ai 500.000 ns. Lo swap è un buffer di sicurezza, non RAM aggiuntiva. Un server che fa costantemente affidamento sullo swap ha un problema di memoria che non può essere risolto con più swap.
Utilizza un file di swap piuttosto che una partizione. È più facile da ridimensionare e non richiede la ripartizione del disco.
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfileAggiungi il file /etc/fstab per garantire la persistenza tra i riavvii. Il chmod 600 passaggio è necessario: qualsiasi dato paginato fuori dalla RAM è leggibile dallo swap, quindi il file non deve essere leggibile da tutti.
Dopo aver creato lo swap, regola vm.swappiness. Il valore predefinito di 60 è aggressivo. Per la maggior parte dei carichi di lavoro di hosting è preferibile che il kernel privilegi la RAM e utilizzi lo swap solo come ultima risorsa:
| Ruolo del server | vm.swappiness | vm.vfs_cache_pressure |
|---|---|---|
| Server web generico | 10–20 | 50 |
| Database (MySQL/PostgreSQL) | 1–5 | 50 |
| Predefinito (la maggior parte delle distribuzioni) | 60 | 100 |
Per quanto riguarda le dimensioni dello swap: 1–2 GB sono sufficienti per un VPS da 2 GB che gestisce picchi di traffico occasionali. Su sistemi con 8 GB o più, uno swap fisso di 2–4 GB è generalmente sufficiente. L'obiettivo è fornire al kernel una valvola di sfogo per le pagine fredde, non estendere la memoria indirizzabile totale.
Su server con RAM limitata e CPU abbondante, zram crea un'area di swap compressa in memoria, evitando completamente l'I/O del disco. Vale la pena prenderlo in considerazione su host VPS multi-tenant in cui NVMe è condiviso tra i tenant. Fai attenzione alla contesa di I/O se lo swap risiede sullo stesso dispositivo dei file di database: lo swapping intenso e le scritture su disco ad alto throughput non coesistono bene.
L'OOM killer
Quando il kernel esaurisce la RAM e lo swap e non riesce a recuperare memoria sufficiente con altri mezzi, interviene l'OOM killer. Assegna un punteggio ai processi utilizzando la oom_badness() funzione:
points = (rss_anon + rss_file + rss_shmem + swapents + pgtables_pages) + (oom_score_adj × totalpages / 1000)Il processo con il punteggio più alto viene terminato. La formula favorisce i processi che consumano molta memoria e il kernel evita di terminare più processi in rapida successione verificando se un processo è già stato terminato negli ultimi 5 secondi.
Nei log compaiono due tipi di eventi OOM:
- OOM globale — l'intero sistema ha esaurito la RAM e lo swap. I log sono preceduti dal prefisso
Out of memory: - Cgroup OOM — un container o un servizio ha raggiunto il proprio
memory.maxlimite. I log hanno il prefissoMemory cgroup out of memory:
Per rivedere gli eventi OOM passati:
dmesg -T | grep -i "out of memory"
journalctl -k --grep="oom"Presta attenzione al order campo nei log OOM. Un valore superiore a 0 suggerisce una frammentazione della memoria piuttosto che un esaurimento totale: il kernel non è riuscito a trovare pagine contigue sufficienti anche se era disponibile memoria libera.
È possibile influenzare i processi a cui si rivolge l'OOM killer regolando /proc/<pid>/oom_score_adj. L'intervallo va da -1000 (non terminare mai) a +1000 (terminare per primo). Per i servizi gestiti da systemd, impostare questo valore in modo permanente nel file dell'unità:
[Service]
OOMScoreAdjust=-1000Parametri sysctl aggiuntivi per ottimizzare il comportamento OOM:
| Parametro | Valore | Effetto |
|---|---|---|
vm.overcommit_memory | 0 | Modalità di overcommit euristica predefinita |
vm.overcommit_memory | 2 | Modalità rigorosa; impedisce allocazioni superiori a RAM × overcommit_ratio + swap |
vm.panic_on_oom | 1 | Riavvia il sistema invece di terminare un processo |
vm.oom_kill_allocating_task | 1 | Termina il processo che ha causato l'OOM anziché quello che consuma più risorse |
Per un monitoraggio proattivo, controllare /proc/pressure/memory (Pressure Stall Information, disponibile a partire dal kernel 4.20). Osservare il some avg10 valore: se è inferiore al 5% è tutto a posto, se rimane al di sopra del 20% significa che è probabile che si verifichi un evento OOM. Un allocstall contatore in /proc/vmstat è un altro segnale precoce: conta i blocchi di recupero diretto, che spesso precedono le interruzioni per OOM. Strumenti come systemd-oomd o earlyoom possono intervenire in base alle soglie PSI prima che scatti l'OOM killer del kernel.
Cgroups e limiti di memoria
I gruppi di controllo (cgroups) consentono di organizzare i processi in gruppi e di applicare limiti rigidi alle risorse. Introdotti in Linux 2.6.24, sono alla base dei runtime dei container, tra cui Docker, Podman, Kubernetes e LXC. Il kernel tiene traccia dell'utilizzo della memoria per ogni cgroup, coprendo la memoria anonima, le pagine supportate da file e gli oggetti del kernel. Se un cgroup raggiunge il proprio limite, il kernel recupera la memoria all'interno di quel gruppo o attiva un kill OOM a livello di cgroup.
Cgroup v1 e v2 differiscono principalmente nella loro struttura. La v1 monta ogni controller (memoria, CPU, I/O) separatamente sotto /sys/fs/cgroup/<controller>/, il che porta a un monitoraggio delle risorse incoerente. La v2 utilizza una gerarchia unificata a /sys/fs/cgroup/. Kubernetes è passato alla v2 come impostazione predefinita nella versione 1.25 e ha abbandonato il supporto per la v1 nella 1.31.
Per verificare quale versione utilizza il tuo sistema:
stat -fc %T /sys/fs/cgroup/cgroup2fs significa v2; tmpfs in genere indica v1.
| Funzionalità | Cgroup v1 | Cgroup v2 |
|---|---|---|
| Gerarchia | Multipla, per controller | Singola, unificata |
| Limite di memoria rigido | memory.limit_in_bytes | memory.max |
| Limite di memoria soft | memory.soft_limit_in_bytes | memory.high (limitazione) |
| Monitoraggio dell'utilizzo | memory.usage_in_bytes | memory.current |
| Metriche di pressione | Limitato | PSI integrato |
I controlli di memoria chiave in cgroup v2:
| Parametro | Tipo | Descrizione |
|---|---|---|
memory.max | Limite rigido | Il superamento di questo valore attiva l'OOM killer |
memory.high | Limite soft | Limita l'allocazione e attiva il recupero prima di raggiungere il limite rigido |
memory.low | Protezione soft | La memoria al di sotto di questa soglia viene recuperata per ultima |
memory.min | Protezione hard | La memoria al di sotto di questo livello non viene mai recuperata |
memory.swap.max | Limite di swap | Impostare su 0 per disabilitare lo swap per questo cgroup |
memory.oom.group | Booleano | Se abilitato, OOM termina tutti i processi nel cgroup contemporaneamente |
Una regola pratica: impostare memory.high circa il 10–20% in meno memory.max per dare al kernel spazio da recuperare prima di raggiungere il limite massimo. Quando si dimensiona memory.max, aggiungi il 20–30% in più rispetto al picco di utilizzo dell’applicazione per tenere conto della cache di pagina, che viene conteggiata nel totale della memoria del cgroup.
Gestire i cgroup tramite systemd anziché scrivere direttamente nel filesystem del cgroup. Utilizzare direttive del file unit come MemoryMax=, MemoryHigh=e MemoryMin= per i limiti persistenti. Per test rapidi:
systemd-run --scope -p MemoryMax=512M <command>Per i pool di worker dei server web, impostare memory.oom.group=1 garantisce un'interruzione pulita se un worker supera il proprio limite — senza lasciare processi orfani. Per i motori di database, memory.min protegge il buffer pool dall'essere recuperato in caso di pressione a livello di sistema.
Configurazione della memoria in base al ruolo del server
Le impostazioni di memoria corrette dipendono dall'attività svolta dal server. Applicare la stessa configurazione a un database e a un server web PHP danneggerà uno dei due.
| Ruolo del server | vm.swappiness | Strategia OOM | Politica Cgroup |
|---|---|---|---|
| Database | 1–5 | Proteggi (OOMScoreAdjust=-900) | Utilizza memory.min per proteggere il buffer pool |
| Server Web/applicazioni | 10–20 | Predefinito | Limite massimo per pool di worker tramite memory.max |
| Worker in background | 60 | Eliminabile (OOMScoreAdjust=+200) | Limitazione tramite memory.high |
| VPS multi-tenant | 60 (con zram) | Predefinito | Isolamento rigido per tenant tramite memory.max |
Per MySQL e PostgreSQL, allocare il 50–70% della RAM disponibile a innodb_buffer_pool_size, disabilitare le Transparent Huge Pages per ridurre i picchi di latenza e proteggere il processo con OOMScoreAdjust=-900 nel file di unità systemd.
Per PHP-FPM, dimensionare i pool di worker in base all'utilizzo effettivo della memoria. Ogni worker utilizza in genere 30–100 MB. Dividere la RAM allocata per la dimensione media di un worker per ottenere un pm.max_children . Utilizzare memory.max nei cgroups per limitare il pool.
Per carichi di lavoro con molte operazioni di scrittura, impostare vm.dirty_ratio a circa il 10% e vm.dirty_background_ratio al 3%. Questo svuota le pagine sporche più frequentemente, evitando lunghi blocchi di I/O.
Rendere persistente l'ottimizzazione del kernel salvando i parametri in /etc/sysctl.d/90-memory.conf. Le impostazioni applicate durante l'esecuzione vanno perse al riavvio.
Per un riepilogo dei valori consigliati in base al ruolo:
| Parametro | Server Web/applicazioni | Server database |
|---|---|---|
vm.swappiness | 10–20 | 1–5 |
vm.vfs_cache_pressure | 50 | 50 |
vm.dirty_ratio | 15% | 10% |
vm.min_free_kbytes | 65536 | 65536 |
| Protezione OOM | Predefinita | OOMScoreAdjust=-1000 |
Se gestisci carichi di lavoro ad alta densità e hai bisogno di un server con la potenza necessaria per applicare correttamente queste politiche, vale la pena dare un'occhiata ai server dedicati di FDC.

Gestione della memoria in Linux: Swap, OOM Killer e Cgroups
Come funzionano insieme Linux swap, OOM killer e cgroup, con esempi di configurazione per database, server web e host VPS multi-tenant.
12 min di lettura - 31 maggio 2026
Guida alla configurazione di Prometheus e node_exporter
15 min di lettura - 29 maggio 2026

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