Gestione della memoria in Linux: Swap, OOM Killer e Cgroups

12 min di lettura - 31 maggio 2026

hero section cover
Indice
  • Spiegazione della gestione della memoria in Linux: swap, OOM killer e cgroups
  • Come Linux gestisce le pagine di memoria
  • Configurazione dello swap
  • L'OOM killer
  • Cgroups e limiti di memoria
  • Configurazione della memoria in base al ruolo del server
Condividi

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:

StrumentoIdeale perMetrica chiave
free -hPanoramica rapida dell'intero sistemaavailable colonna
vmstat 1Monitoraggio in tempo reale dello swap e dell'I/Osi, so
htopVisualizzazione interattiva per processoBarre di memoria, elenco dei processi
smemUtilizzo accurato per processoUSS (dimensione set univoca)
/proc/meminfoDettagli a livello di kernelMemAvailable, 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 /swapfile

Aggiungi 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 servervm.swappinessvm.vfs_cache_pressure
Server web generico10–2050
Database (MySQL/PostgreSQL)1–550
Predefinito (la maggior parte delle distribuzioni)60100

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.max limite. I log hanno il prefisso Memory 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=-1000

Parametri sysctl aggiuntivi per ottimizzare il comportamento OOM:

ParametroValoreEffetto
vm.overcommit_memory0Modalità di overcommit euristica predefinita
vm.overcommit_memory2Modalità rigorosa; impedisce allocazioni superiori a RAM × overcommit_ratio + swap
vm.panic_on_oom1Riavvia il sistema invece di terminare un processo
vm.oom_kill_allocating_task1Termina 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 v1Cgroup v2
GerarchiaMultipla, per controllerSingola, unificata
Limite di memoria rigidomemory.limit_in_bytesmemory.max
Limite di memoria softmemory.soft_limit_in_bytesmemory.high (limitazione)
Monitoraggio dell'utilizzomemory.usage_in_bytesmemory.current
Metriche di pressioneLimitatoPSI integrato

I controlli di memoria chiave in cgroup v2:

ParametroTipoDescrizione
memory.maxLimite rigidoIl superamento di questo valore attiva l'OOM killer
memory.highLimite softLimita l'allocazione e attiva il recupero prima di raggiungere il limite rigido
memory.lowProtezione softLa memoria al di sotto di questa soglia viene recuperata per ultima
memory.minProtezione hardLa memoria al di sotto di questo livello non viene mai recuperata
memory.swap.maxLimite di swapImpostare su 0 per disabilitare lo swap per questo cgroup
memory.oom.groupBooleanoSe 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 servervm.swappinessStrategia OOMPolitica Cgroup
Database1–5Proteggi (OOMScoreAdjust=-900)Utilizza memory.min per proteggere il buffer pool
Server Web/applicazioni10–20PredefinitoLimite massimo per pool di worker tramite memory.max
Worker in background60Eliminabile (OOMScoreAdjust=+200)Limitazione tramite memory.high
VPS multi-tenant60 (con zram)PredefinitoIsolamento 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:

ParametroServer Web/applicazioniServer database
vm.swappiness10–201–5
vm.vfs_cache_pressure5050
vm.dirty_ratio15%10%
vm.min_free_kbytes6553665536
Protezione OOMPredefinitaOOMScoreAdjust=-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.

Blog

In primo piano questa settimana

Altri articoli
Gestione della memoria in Linux: Swap, OOM Killer e Cgroups

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

Altri articoli
background image

Avete domande o avete bisogno di una soluzione personalizzata?

icon

Opzioni flessibili

icon

Portata globale

icon

Distribuzione immediata

icon

Opzioni flessibili

icon

Portata globale

icon

Distribuzione immediata