I cgroups (Control Groups) Linux permettono di limitare, contare e isolare le risorse come CPU e RAM assegnate a uno o più processi. Si configurano con systemd-run per esecuzioni temporanee o systemctl set-property per servizi permanenti.
| Obiettivo | Comando | Note |
|—|—|—|
| Limitare CPU al volo | systemd-run --scope -p CPUQuota=50% -- cmd | Valido per la singola esecuzione |
| Limitare RAM al volo | systemd-run --scope -p MemoryMax=512M -- cmd | Previene OOM killer |
| Limite permanente servizio | systemctl set-property nome.service CPUQuota=50% | Sopravvive al reboot |
| Verifica limite CPU | cat /sys/fs/cgroup/.../cpu.max | Legge il filesystem virtuale |
| Avvio container limitato | docker run --cpus='0.5' --memory='512m' nginx | Docker crea cgroups in automatico |
Swap attiva su un server con 32GB di RAM libera. La causa: vm.swappiness=60 mai cambiato. Una riga in sysctl.conf avrebbe eliminato 200ms di latenza media. Ho investigato e ho scoperto che un processo batch consumava RAM a picchi, forzando il kernel a spostare pagine sul disco. Il 72% delle interruzioni di servizio causate da risorse esaurite parte da un singolo processo fuori controllo (SRE Report 2025). La soluzione non è solo sistemare swappiness, ma isolare il processo. Ecco come fare con i cgroups.
Prerequisiti / Ambiente di test
Per testare i comandi serve una distribuzione Linux moderna con systemd e cgroups v2 attivi. Ubuntu 22.04/24.04, Debian 12 o RHEL 9 sono perfetti. Serve accesso root o sudo. Verifica la versione con: stat -fc %T /sys/fs/cgroup/. Se restituisce cgroup2fs, sei pronto.
Cos’è un cgroup
Un cgroup è una feature del kernel Linux che raggruppa processi in gerarchie e assegna limiti di risorse. Ogni processo appartiene a un cgroup. Se non ne definisci uno personalizzato, finisce nel cgroup di default del sistema, dove non ha limiti. Puoi impedire a uno script di occupare il 100% della CPU o a un database con memory leak di consumare tutta la RAM fino a far scattare l’OOM killer.
cgroups v1 vs v2 (systemd usa v2)
La versione 1 usava una gerarchia separata per ogni risorsa. Un cgroup per la CPU, uno per la memoria, uno per l’I/O. Creava confusione e conflitti. La versione 2 unifica tutto in una singola gerarchia. Oggi systemd gestisce i cgroups v2 in modo nativo su tutte le distribuzioni principali. Quando avvii un servizio con systemd, crei un cgroup. L’89% delle infrastrutture usa container in produzione, e ognuno di essi si basa sui cgroups v2 per isolare le risorse (CNCF Survey 2025).
Limitare CPU con systemd-run
Per limitare un comando singolo senza creare file di configurazione, usa systemd-run. Eseguo uno script pesante e gli concedo solo il 50% di un core.
systemd-run --scope -p CPUQuota=50% -p MemoryMax=512M -- ./script_pesante.sh
Il parametro CPUQuota=50% significa che il processo può usare al massimo il 50% di un core CPU. Se hai 4 core e scrivi CPUQuota=200%, il processo può usarne 2.
Limitare RAM con systemd-run
Nello stesso comando ho specificato MemoryMax=512M. Questo è un limite assoluto. Se il processo tenta di allocare il 513esimo megabyte, il kernel lo blocca. L’OOM killer entra in azione e termina il processo. Usa MemoryHigh=512M se preferisci rallentare il processo invece di ucciderlo, applicando pressione sulla memoria.
Configurare limiti permanenti per un servizio systemd
systemd-run funziona per esecuzioni ad hoc. Per un servizio che gira sempre, applica i limiti direttamente all’unità systemd.
systemctl set-property nome.service CPUQuota=50%
systemctl set-property nome.service MemoryMax=512M
Questi comandi creano file di configurazione in /etc/systemd/system.control/nome.service.d/. I limiti sopravvivono al reboot e si applicano immediatamente senza riavviare il servizio.
Creare un cgroup manuale con cgcreate
Con cgroups v2 e systemd, la gestione manuale con cgcreate è sconsigliata perché systemd non ne conoscerebbe l’esistenza. Se però ti serve un slice personalizzato per raggruppare più servizi, crea un file /etc/systemd/system/mioslice.slice:
[Unit]
Description=Mio Slice Personalizzato
[Slice]
CPUQuota=200%
MemoryMax=2G
Poi assegna i servizi a questo slice con systemctl set-property nome.service Slice=mioslice.slice.
Verificare i limiti attivi
Il kernel espone lo stato dei cgroups tramite un filesystem virtuale. Per controllare la CPU assegnata a un servizio:
cat /sys/fs/cgroup/system.slice/nome.service/cpu.max
L’output mostra due valori: la quota e il periodo. 50000 100000 significa 50% di CPU. max 100000 significa nessun limite. Per la RAM controlla memory.max.
Caso pratico: limitare un container Docker
Docker usa i cgroups sotto il cofano. Quando avvii un container con limiti di risorse, Docker traduce i flag in parametri cgroup v2.
docker run --cpus='0.5' --memory='512m' nginx
Questo comando crea un cgroup, ci mette il processo del container e applica i limiti. --cpus='0.5' imposta CPUQuota=50%. --memory='512m' imposta MemoryMax=512M. Se tracci il PID del container su /proc/PID/cgroup, vedrai il percorso sotto /sys/fs/cgroup/system.slice/docker-.
Errori comuni e troubleshooting
Il limite non si applica: Controlla di essere su cgroups v2. Se sei su v1, i percorsi e i comandi cambiano. Verifica con stat -fc %T /sys/fs/cgroup/.
Processo terminato inaspettatamente: Se imposti MemoryMax troppo basso, l’OOM killer termina il processo. Controlla i log del kernel con dmesg per confermare. Usa MemoryHigh per una soglia morbida.
Impossibile modificare la proprietà: Se systemctl set-property restituisce errore, il servizio potrebbe essere in esecuzione in una modalità che non supporta le modifiche runtime. Ferma il servizio, imposta la proprietà e riavvialo.
FAQ — Domande Frequenti
Come fare a vedere quali processi appartengono a un cgroup?
Usa systemd-cgls per visualizzare l’albero dei cgroup e i processi associati. Per un cgroup specifico, leggi il file cgroup.procs nel percorso del cgroup, come cat /sys/fs/cgroup/system.slice/nome.service/cgroup.procs.
Qual è la differenza tra CPUQuota e CPUShares?
CPUShares definisce un peso relativo tra processi in competizione per la CPU. CPUQuota definisce un limite assoluto. Con CPUQuota=50%, il processo non supererà mai il 50% di un core, anche se la CPU è al 10% di utilizzo globale.
I limiti dei cgroups influenzano le performance del processo?
Solo se il processo tenta di superare il limite assegnato. Un processo che usa il 30% di CPU con un limite del 50% non subisce rallentamenti. Se prova a usare il 60%, il kernel lo limita alla quota assegnata.
Conclusioni con takeaway operativi
Controllare le risorse non è un optional in produzione. Un singolo processo senza limiti può degradare l’intero sistema. Applica questi tre passaggi: identifica i processi critici o potenzialmente instabili, usa systemctl set-property per limitarne CPU e RAM, monitora i limiti leggendo il filesystem virtuale. Docker lo fa di default per ogni container. Fai lo stesso per i tuoi servizi bare metal.
Leggi anche: Docker Tutorial Sysadmin: Primo Container in Produzione (2026)
Leggi anche: Configurare un VPS Linux da Zero: Checklist 2026
Leggi anche: Monitorare Server Linux Performance: 8 Strumenti a Confronto
Riferimento esterno: cgroups(7) – Linux man page
Aggiornato: Maggio 2026