SSD Nodes Learn 🎉 VPS da $5.50/mese
Guide Matt ConnorDi Matt Connor

Swap sul VPS: serve davvero e quanto dimensionarlo?

Molte immagini cloud non includono swap: scopri quando aggiungerlo a un VPS piccolo, come dimensionarlo, cosa comporta vm.swappiness e quando zram è migliore.

Il tuo VPS ha bisogno di swap?

La maggior parte delle immagini cloud viene rilasciata senza swap e, su un VPS di piccole dimensioni, la risposta è generalmente sì: aggiungi un file di swap. Lo swap non fa comportare un server da 1 GB come un server da 2 GB. Offre al kernel uno spazio in cui collocare le pagine anonime fredde, mantiene utile la page cache e fa sì che l’OOM killer (out of memory killer, la routine del kernel che seleziona un processo e lo termina per liberare memoria) sia l’ultima risorsa anziché la prima.

In breve: su un sistema che esegue alcuni servizi a lunga esecuzione, un file di swap di piccole dimensioni vale lo spazio su disco che occupa. Su un sistema in cui un processo tenta regolarmente di allocare più memoria di quella disponibile sull’intera macchina, lo swap non risolverà il problema e renderà il fallimento più lento e più difficile da individuare. Il resto di questa guida spiega come distinguere questi due casi e illustra i due costi che si manifestano soltanto su un VPS.

Ogni comando riportato di seguito richiede root sul tuo server. Eseguilo quindi sul tuo server, invece di copiare l’output del sistema di qualcun altro.

Cosa fa realmente lo swap e cosa non fa

La memoria Linux è di due tipi. Le pagine supportate da file sono copie di elementi già presenti sul disco: i programmi e tutti i file letti di recente. Questo insieme costituisce la page cache. Le pagine anonime non hanno un file associato: includono heap e stack, oltre alla maggior parte della memoria allocata da un database durante l'esecuzione.

Quando la memoria disponibile si esaurisce, il kernel deve recuperare pagine. Recuperare una pagina supportata da file e non modificata è semplice, perché la copia sul disco è ancora disponibile e la pagina può essere riletta in seguito. Lo stesso non vale per una pagina anonima, perché l'unica copia si trova nella RAM. Senza swap, il kernel ha due possibilità per la memoria anonima: conservarla oppure terminare il processo che la possiede.

Un server senza swap esegue comunque il paging. Semplicemente, usa il tipo di memoria sbagliato. Sotto pressione, il kernel riduce la page cache ed espelle pagine di file che dovrà rileggere a breve, incluso il codice eseguibile dei programmi in esecuzione. Queste pagine rientrano in memoria generando page fault maggiori. Nella colonna bi di vmstat si osservano letture dal disco e il contatore pgmajfault in /proc/vmstat aumenta, mentre si e so restano sempre a zero. Il sistema è in thrashing, ma i contatori dello swap non riportano alcuna attività.

Lo swap non aggiunge capacità di memoria. Se il working set, cioè l'insieme delle pagine effettivamente utilizzate, è più grande della RAM, lo swap trasforma un'operazione di terminazione per esaurimento della memoria in un server estremamente lento. In alcuni casi è il compromesso desiderato, perché è possibile accedere e riparare un server lento, mentre non è possibile intervenire su un database terminato. In altri casi è peggiore, perché un server lento continua a fallire i controlli di integrità mantenendo aperte tutte le connessioni. Stabilire quale comportamento si preferisce prima di aggiungere lo swap.

Perché le immagini cloud vengono distribuite senza swap?

È una scelta deliberata. Un’unica immagine deve avviarsi su tutti i piani offerti da un provider, quindi una partizione swap fissa sprecherebbe spazio sui piani più piccoli e sarebbe inutile su quelli più grandi. Anche la velocità dello swap dipende dallo storage sottostante della macchina guest, che l’immagine non può conoscere in anticipo. Inoltre, chi crea le immagini ottimizza il comportamento prevedibile: in un ambiente distribuito, un processo che termina subito è più semplice da diagnosticare rispetto a una macchina che resta attiva ma risponde a ogni richiesta con un ritardo di diversi secondi.

Questi motivi riguardano macchine temporanee. Un VPS che si intende mantenere è diverso. Invece di sostituirlo, lo si ripara; per questo, qualche secondo di paging è spesso preferibile all’arresto di un servizio. Considerare l’assenza dello swap come un’impostazione predefinita progettata per un caso d’uso diverso dal proprio.

File di swap o partizione di swap su un VPS?

Usate un file. Una partizione richiede di ridimensionare un filesystem root attivo su un disco già partizionato, con un rischio concreto e senza vantaggi. Un file viene creato e rimosso con i normali comandi. In seguito potete modificarne le dimensioni senza intervenire sulla tabella delle partizioni.

La velocità non è il fattore decisivo. Al tempo swapon il kernel legge una volta la mappa delle extent del file, quindi invia direttamente le operazioni di I/O al dispositivo a blocchi. Il filesystem non viene quindi attraversato per ogni operazione di page-in e page-out. Sullo stesso disco, un file di swap e una partizione di swap offrono prestazioni equivalenti.

È importante conoscere due limitazioni. Non collocate lo swap su un filesystem di rete, come NFS (network file system). Su btrfs, inoltre, il file deve avere la copy-on-write disabilitata e la compressione disattivata. Per questo btrfs include un helper dedicato alla sua creazione.

Come aggiungere un file di swap su Ubuntu o Debian

Controllare la situazione attuale prima di modificare qualsiasi cosa.

swapon --show
free -h
findmnt -no FSTYPE /

Un output vuoto di swapon --show indica che non è presente alcuno swap, condizione normale in una nuova cloud image. findmnt mostra il tipo di filesystem root, che determina la procedura da usare per creare il file. Su ext4, utilizzato dalla maggior parte delle cloud image, fallocate è sicuro.

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

chmod viene eseguito prima di mkswap intenzionalmente. Se lo si salta, mkswap lo segnala con mkswap: /swapfile: insecure permissions 0644, fix with: chmod 0600 /swapfile. Un file di swap leggibile da tutti espone a ogni utente del sistema i dati che altri processi hanno trasferito nello swap. Un mkswap completato correttamente conferma poi la dimensione, con una riga simile a Setting up swapspace version 1, size = 2 GiB (2147479552 bytes).

Su xfs o btrfs l'ultimo comando può fallire con swapon: /swapfile: swapon failed: Invalid argument. Su XFS questo accade perché fallocate lascia extents non scritti; in questo caso occorre scrivere direttamente i byte.

sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress

Su btrfs la causa è il copy-on-write, e le versioni attuali di btrfs-progs impostano automaticamente i flag corretti.

sudo btrfs filesystem mkswapfile --size 2g /swapfile

In entrambi i casi, completare con chmod 600, mkswap dove applicabile, e swapon, quindi verificare il risultato.

swapon --show
free -h

swapon --show dovrebbe elencare /swapfile con tipo file e la dimensione richiesta, mentre free -h dovrebbe mostrare una riga Swap con un utilizzo quasi nullo. Uno swap appena configurato con zero spazio utilizzato è corretto. Il kernel vi trasferisce le pagine soltanto quando è necessario.

Rendere la configurazione persistente dopo un riavvio, quindi verificare subito la voce.

echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
sudo swapoff /swapfile
sudo swapon -a
swapon --show

swapon -a legge /etc/fstab, quindi una riga errata fallisce immediatamente, durante il controllo. Un errore di sintassi non verificato si manifesta durante un riavvio non pianificato, quando il sistema torna operativo senza lo swap che si pensava fosse disponibile.

Per rimuovere lo swap in seguito, eseguire sudo swapoff /swapfile, eliminare la riga da fstab, quindi eseguire sudo rm /swapfile. swapoff deve prima riportare in RAM tutte le pagine trasferite nello swap, quindi su un sistema sotto carico può fallire con swapoff: /swapfile: swapoff failed: Cannot allocate memory. Liberare memoria e riprovare.

Quanto deve essere grande il file di swap?

Il job mantiene in memoria pagine anonime inattive. Pertanto, il valore rilevante è la quantità di memoria allocata realmente inutilizzata, non la quantità di RAM prevista dal piano. La memoria inutilizzata non aumenta proporzionalmente alle dimensioni del piano, quindi il moltiplicatore diminuisce per i piani più grandi. Questa è la regola adottata da questa guida.

ChartSwap file size this guide sets, by plan RAM
The data behind this chart
[
  {
    "label": "1 GB plan",
    "swap_gb": 2,
    "swap_x_ram": 2
  },
  {
    "label": "2 GB plan",
    "swap_gb": 2,
    "swap_x_ram": 1
  },
  {
    "label": "4 GB plan",
    "swap_gb": 2,
    "swap_x_ram": 0.5
  },
  {
    "label": "8 GB plan",
    "swap_gb": 4,
    "swap_x_ram": 0.5
  },
  {
    "label": "16 GB plan",
    "swap_gb": 4,
    "swap_x_ram": 0.25
  }
]

Nel piano più piccolo sono previsti 2 GB di swap, pari a 2 volte la RAM, perché una macchina da 1 GB ha un margine così ridotto che un singolo picco può attivare l'OOM killer. All'estremità superiore della tabella, il file si ferma a 4 GB, pari a 0.25 volte la RAM, perché trasferire una quantità così grande di dati sullo storage condiviso richiede abbastanza tempo da rendere di fatto il server non disponibile durante l'operazione. Riduci questi valori se lo spazio disco disponibile è limitato, perché il file occupa spazio disco reale.

L'unico motivo classico per dimensionare lo swap in misura pari o superiore alla RAM è l'ibernazione, che scrive l'intera immagine della memoria nello swap. Un VPS non va in ibernazione, quindi questa regola non si applica al tuo caso.

Che cosa cambia davvero vm.swappiness?

vm.swappiness non è una percentuale della RAM e non è una soglia. È il costo relativo che il kernel assegna al recupero delle pagine anonime rispetto alle pagine dei file. Il valore predefinito è 60. Se lo si riduce, il kernel preferisce eliminare la page cache. Se lo si aumenta, il kernel preferisce trasferire nella swap la memoria anonima.

È un compromesso in entrambe le direzioni. Con vm.swappiness = 10 un database mantiene residenti più allocazioni e paga questo vantaggio rileggendo i file appena eliminati dalla cache. Su un server il cui carico principale consiste nel servire file, questa è la direzione sbagliata, perché in quel caso la page cache svolge il lavoro utile.

Impostarlo su 0 non disattiva la swap. Indica al kernel di evitare il recupero delle pagine anonime finché la memoria non è quasi esaurita, anticipando così l'intervento dell'OOM killer invece di ritardarlo. Se non si vuole usare la swap, è necessario rimuovere il file di swap.

sysctl vm.swappiness
printf 'vm.swappiness = 10\n' | sudo tee /etc/sysctl.d/99-swappiness.conf
sudo sysctl --system
sysctl vm.swappiness

Un semplice sysctl -w resta valido fino al riavvio successivo e poi smette di essere applicato senza messaggi; perciò scrivere la configurazione nel file sotto /etc/sysctl.d/. I kernel dalla versione 5.8 accettano valori da 0 a 200. Valori superiori a 100 hanno senso soltanto quando la swap è quasi veloce quanto la RAM, come nel caso di zram.

zram: lo swap che usa CPU invece del disco

zram è un dispositivo a blocchi compresso che risiede nella RAM. Usalo come swap: una pagina che altrimenti verrebbe scritta su disco viene compressa e resta in memoria. Non viene eseguito alcun I/O su disco e non viene consumata alcuna quota disco. Il costo è il tempo CPU necessario per comprimere e decomprimere ogni pagina, oltre alla RAM che conserva le pagine compresse e che non è più disponibile per le applicazioni.

Per le pagine anonime, i rapporti di compressione generalmente pubblicati sono compresi tra 2:1 e 3:1. Il valore effettivo è riportato da zramctl nelle colonne DATA e COMPR. Misuralo invece di basare la configurazione sul valore tipico, perché alcuni carichi di lavoro contengono dati che si comprimono appena.

sudo apt install zram-tools

Imposta ALGO=zstd e PERCENT=25 in /etc/default/zramswap, quindi riavvia il servizio e verifica il risultato.

sudo systemctl restart zramswap
zramctl
swapon --show

PERCENT è una percentuale della RAM totale. Su un sistema con 4 GB, il valore 25 riserva fino a 1 GB per le pagine compresse. Inizia con un valore basso e aumentalo solo se zramctl mostra che il dispositivo si sta riempiendo. L'impostazione PRIORITY nello stesso file determina quale swap il kernel riempie per primo: ha la precedenza il valore più alto. Un file di swap aggiunto con swapon senza altre opzioni riceve una priorità negativa, quindi zram viene usato per primo e il file gestisce l'eccedenza. swapon --show stampa entrambe nella colonna PRIO. Nelle distribuzioni che usano systemd-zram-generator invece di zram-tools, le stesse impostazioni si trovano in /etc/systemd/zram-generator.conf.

zram è adatto a un sistema con capacità CPU disponibile e poco spazio libero su disco. È la scelta sbagliata quando la CPU è già la risorsa limitata, perché il lavoro di compressione compete con l'applicazione per la stessa capacità.

Due insidie dello swap che si verificano solo su un VPS

La prima insidia riguarda il disco. Un file di swap da 2 GB occupa 2 GB del disco previsto dal piano non appena lo crei, perché lo spazio deve essere allocato in anticipo. df -h / diminuisce immediatamente dell'intero importo e non recupera spazio finché non elimini il file. In un piano di dimensioni ridotte, si tratta di una parte significativa dello spazio disponibile; inoltre, un filesystem root pieno causa molti più problemi di quanti lo swap ne abbia mai risolti. Il file viene conteggiato anche nell'output di du, un aspetto da ricordare quando cerchi di capire dove sia finito lo spazio e df e du non concordano sulla destinazione dello spazio su disco.

La seconda insidia riguarda la latenza. L'I/O dello swap utilizza lo storage condiviso dall'host con gli altri guest e dall'interno del tuo guest non puoi vedere il loro carico. Puoi solo osservare l'effetto: una pagina che normalmente viene caricata rapidamente a volte richiede molto più tempo, e il processo in attesa resta fermo finché la pagina non arriva. Il ragionamento è lo stesso di CPU steal time su un host condiviso, ma applicato alla coda del disco invece che alla run queue. Misura la latenza sul tuo server, perché qualsiasi valore pubblicato descrive i guest degli altri utenti.

Come capire se lo swap sta causando problemi?

Avere dati nello swap non è un problema. Lo è il traffico di swap. Un server con diverse centinaia di megabyte nello swap e nessuna attività di paging ha semplicemente spostato memoria che non viene utilizzata da ore. È il risultato previsto.

Controllare le velocità invece dei totali.

vmstat 1 5

si e so sono i kibibyte al secondo trasferiti rispettivamente nello swap e dallo swap. Su un server in buone condizioni restano pari o prossimi a zero, indipendentemente dal valore indicato nella colonna swpd. Un valore so sostenuto, insieme all'aumento di si, indica che le pagine vengono scritte sullo swap e subito rilette. Questo comportamento è detto thrashing.

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  3 1048572  38210   4096  61440  912 1180  2210  1290 1402 2890  9  7 12 72  0

Questo esempio mostra un server in difficoltà. Il segnale più chiaro non si trova nelle colonne dello swap. È wa a 72: la CPU ha trascorso la maggior parte del tempo in attesa dell'I/O. Inoltre, b è pari a 3: tre processi sono bloccati.

PSI (pressure stall information) risponde alla domanda in modo più diretto.

cat /proc/pressure/memory
some avg10=8.42 avg60=5.11 avg300=2.03 total=1284729
full avg10=3.10 avg60=1.94 avg300=0.71 total=498210

some avg10=8.42 indica che, negli ultimi 10 secondi, almeno un task è rimasto in attesa della memoria per l'8.42 percento del tempo. full conta il tempo durante il quale ogni task non inattivo è rimasto bloccato. Un valore full sostenuto indica quindi un danno misurabile, non soltanto un segnale di avvertimento. Se il file non esiste, il kernel ha PSI disabilitato per impostazione predefinita. È necessario aggiungere psi=1 alla riga di comando del kernel.

Per vedere quali processi contengono pagine nello swap:

sudo awk '/^Name:/{n=$2} /^VmSwap:/ && $2+0 > 0 {printf "%10d kB  %s\n", $2, n}' /proc/[0-9]*/status | sort -rn | head

Per verificare se l'OOM killer è già intervenuto:

sudo journalctl -k --grep "Out of memory"

Un evento appare come Out of memory: Killed process 2199 (mysqld) total-vm:1275860kB, anon-rss:129252kB, file-rss:0kB, shmem-rss:0kB, UID:114 pgtables:504kB oom_score_adj:0, mentre il log del servizio, nello stesso secondo, contiene Main process exited, code=killed, status=9/KILL. Se queste righe sono già comparse su un server senza swap, aggiungere un file di swap è il tentativo successivo meno costoso.

Quando lo swap è la soluzione sbagliata

Lo swap dà tempo quando la pressione sulla memoria è temporanea o riguarda pagine poco utilizzate. Non risolve il problema di un processo che continua a crescere fino a terminare, e rende il guasto più difficile da monitorare, perché la macchina passa minuti aggiuntivi a eseguire il paging invece di terminare rapidamente il processo e riavviarlo.

Imposta invece un limite al processo. Un servizio systemd accetta MemoryMax= e MemorySwapMax= in un file drop-in. In questo modo puoi limitare memoria e CPU per un servizio con systemd senza modificare l'applicazione. I container offrono gli stessi controlli a un livello superiore; configurarli consente di impedire che un servizio Compose consumi tutte le risorse del server. Entrambe le soluzioni producono un evento di terminazione con il nome del processo nei log, che puoi individuare, invece di lasciare che il kernel scelga la vittima in base al punteggio.

Esegui questa configurazione quando il server è nuovo e non è ancora sotto carico. Creare il file di swap e impostare un limite di memoria richiede pochi minuti e rientra nelle attività dei primi dieci minuti su un nuovo VPS.

FAQ

L'aggiunta dello swap fa funzionare il mio VPS da 1 GB come un VPS da 2 GB?

No. Lo swap è molto più lento della RAM e il kernel vi sposta soltanto le pagine che considera inattive. Fornisce margine per gestire i picchi e consente di parcheggiare la memoria allocata ma mai più utilizzata. Se il carico di lavoro legge e scrive attivamente più memoria di quella disponibile sulla macchina, lo swap trasforma un'uscita per esaurimento della memoria in un paging continuo. Il server resta attivo, ma risponde così lentamente da diventare inutilizzabile. In questo caso, aggiungete RAM oppure limitate il processo che continua a crescere.

Di quanto swap ha bisogno un VPS da 1 GB o da 2 GB?

2 GB sono sufficienti in entrambi i casi e, oltre questo valore, non è necessario aumentare lo swap in proporzione alla RAM. Lo swap contiene pagine anonime inattive e la quantità di memoria realmente inattiva su un server non cresce come la RAM totale. La vecchia regola del doppio della RAM deriva dall'ibernazione, che scrive su disco l'intera immagine della memoria. Un VPS non va mai in ibernazione. Dimensionare lo swap oltre 4 GB comporta soprattutto un errore più lento e prolungato, su uno storage condiviso con altri guest.

Impostare vm.swappiness su 0 è il modo corretto per impedire lo swapping?

No e il parametro non produce l'effetto suggerito dal nome. vm.swappiness = 0 non disabilita lo swap. Indica al kernel di evitare il reclaim delle pagine anonime fino a quando la memoria disponibile è quasi esaurita, rendendo più probabile, non meno, un OOM kill. Inoltre sposta tutte le operazioni di reclaim sulla page cache, quindi le letture dei file accedono più spesso al disco. Se volete eliminare completamente lo swap, eseguite sudo swapoff -a e rimuovete la riga da fstab. Se volete ridurre lo swapping, provate vm.swappiness = 10 e confrontate le colonne si e so in vmstat prima e dopo la modifica.

Devo usare zram invece di un file di swap?

Usate zram quando avete margine sulla CPU e poco spazio libero su disco. Usate un file di swap quando la situazione è opposta. zram comprime le pagine e le mantiene nella RAM, evitando completamente l'I/O su disco. Il costo è un consumo di CPU per ogni page in e page out, oltre alla RAM occupata, che non è più disponibile per le applicazioni. Su un VPS con una quota CPU ridotta, questo costo grava proprio sulla risorsa che è già scarsa. Usare entrambe le soluzioni è normale: assegnate a zram una priorità maggiore con PRIORITY in /etc/default/zramswap e mantenete un file di swap su disco sottostante per gestire l'overflow.

Perché l'OOM killer è stato eseguito quando free mostrava memoria disponibile?

free restituisce una fotografia in un determinato istante, mentre un'allocazione avviene in un attimo. Un processo che richiede un blocco di grandi dimensioni più rapidamente di quanto il reclaim riesca a liberare memoria viene terminato, anche se la situazione media sembrava sotto controllo. Leggete il log del kernel con sudo journalctl -k --grep "Out of memory", che indica il processo terminato e la sua dimensione resident al momento dell'evento. Verificate quindi se il kill è stato causato da un limite cgroup anziché dall'esaurimento della memoria dell'intera macchina. Un container o un'unità systemd con MemoryMax= impostato viene terminato quando raggiunge il proprio limite, anche se l'host dispone ancora di memoria libera.

#swap#memory#oom#zram#linux-performance