Swapping su PVE
Questo articolo è un incrocio fra documentazione e un rant. Da quando uso PVE (dalla 4.x) fino ad ora (6.4) ho sempre avuto problemi con lo swap, che andavano dal piantamento totale della macchina ad un rallentamento mostruoso causato dal fatto che la partizione di swap si riempiva al 100% anche se c'era abbondanza di ram libera.
Per quanto io mi sia impegnato non ho ancora trovato una spiegazione esauriente sul perché lo swap funziona in questo modo su PVE, quello che segue sono mie personali impressioni che non corrispondono alla verità assoluta.
Swap su ZFS: NO
Mai usare lo swap su ZFS, provoca un effetto valanga che porta la macchina a piantarsi per OOM. Alcune versioni di PVE installavano per default lo swap su ZFS (credo la 4.x e forse le prime versioni 5.x) e l'unica soluzione per evitare che la macchina si riavvii durante i backup è disattivare totalmente lo swap, o swappare su un disco che NON sia in ZFS. Nelle versioni nuove di PVE installate con ZFS lo swap è disattivato di default.
Lo swap si riempie durante i backup
Sulle mie macchine, che sono piccole (16-32 GB di RAM) ho notato che lo swap tende a riempirsi anche in presenza del 50% di RAM libera, e questo succede tipicamente durante i backup (con vzdump in modalità snapshot) verso un altro disco locale. Il problema è che non c'è nessuna reale necessità di swappare in questo modo, e tutto questo uso di swap finisce col rallentare inutilmente tutto. Il problema pare essere decisamente peggiore se le vm usano come caching il metodo "writeback", in questo caso l'abuso di swap durante il backup è ancora più evidente, ma in ogni caso accade anche con la cache "none" che è il default.
La mia ipotesi è che durante il backup (fra dischi locali) il kernel cerchi di allocare moltissima cache e nel fare questo provochi lo swapping out della RAM allocata alle VM e non in uso continuo. Considerando che tipicamente il backup avviene quando le VM sono accese ma non stanno facendo lavoro, qualsi tutta la RAM allocata alle VM (che dal punto di vista dell' host è RAM allocata al processo KVM relativo) è "ferma", non viene movimentata, quindi è candidata ad essere swappata per fare spazio alla cache del disco.
Il problema è che una volta finito il backup non c'è niente che forzi il kernel a riprendere quello spazio di memoria fuori dallo swap e riportarlo in RAM, fino al momento in cui le VM vengono nuovamente usate. L'effetto percepito dagli utenti è che la mattina presto il server è lentissimo (sta tirando fuori dallo swap lo spazio di memoria dedicato alle VM) e poi verso sera funziona bene (quando oramai tutta la memoria delle VM è stata riportata in RAM), salvo poi tornare ad avere il problema la mattina dopo, quando il backup della notte ha di nuovo fatto swappare tutto lo spazio allocato alle VM dalla RAM allo swap.
Il parametro swappiness viene ignorato
Per cercare di limitare il problema appena descritto, ho provato a ridurre la swappiness (dell'host, non dentro i guest) da 60 (che è il default) fino a zero. Il risultato è stato molto deludente. In macchine dove la RAM occupata arriva intorno al 30 - 50%, il processo di backup causa un ecessivo swap out, esattamente come capitava con swappiness a 60. Leggendo in giro ho incontrato post di persone che avevano molta più RAM (500 GB) che invece si lamentavano di come il kernel non swappasse mai. Altri invece incontravano il mio stesso problema. Questi comportamenti così diversi (e opposti) mi dicono che a quanto pare nessuno ha ancora capito cosa faccia davvero il parametro della swappiness, ma quello che è sicuro è che non fa quello che ci aspettiamo che faccia.
La soluzione
Alla fine di tutte queste elucubrazioni e test, ho dedotto che la soluzione è disattivare totalmente lo swap. Posto che ci sia abbastanza RAM per fare girare tutto, disattivando lo swap risolviamo ogni problema e otteniamo un sistema molto più performante, senza rallentamenti percepiti dagli utenti. Su un host con 16 GB di RAM, della quale metà circa allocata alle VM (e allo stesso modo su un altro host con 24 GB, sempre con circa metà allocata alle VM) ho riscontrato che tutto gira senza problemi, e durante i backup l'uso della RAM non aumenta in maniera significativa (circa 600 MB di RAM usata in più). Questo significa che il backup non ha nessuna necessità di riempire lo swap, non vi è alcuna reale carenza di RAM durante i backup, quindi non c'è pericolo di andare in OOM, almeno non nella mia situazione con metà della RAM libera. Il tempo di esecuzione dei backup non è aumentato per carenza di cache, anzi è leggermente diminuito (di un 5% circa) probabilmente a causa della riduzione dell' i/o inutile causato dallo swap out ingiustificato.
E se la RAM non mi basta?
Se la RAM non basta, credo che sia meglio, dal punto di vista delle performance, ridurre la RAM allocata alle VM e quindi forzare le VM a swappare "dentro sè stesse" piuttosto che consentire all' host di swappare.