limite de resurse cgroups v2 cu systemd

11 min citire - 3 iunie 2026

hero section cover
Cuprins
  • Limite de resurse cgroups v2 cu systemd
  • Activarea cgroups v2
  • Cum organizează systemd grupurile c
  • Limite CPU
  • Limite de memorie cu cgroups v2
  • Limite I/O
  • Izolarea multi-tenant cu segmente
  • Monitorizare cu systemd-cgtop și PSI
Distribuie

Setați limite de CPU, memorie și I/O cu cgroups v2 și systemd. Configurare practică pentru gazde Linux cu mai mulți locatari, cu monitorizare PSI și izolare de slice.

Limite de resurse cgroups v2 cu systemd

cgroups v2 este cadrul unificat de control al resurselor al kernel-ului Linux. Acesta înlocuiește ierarhia fragmentată v1 cu o singură structură arborescentă care gestionează CPU, memoria și I/O în mod consecvent și stă la baza izolării containerelor în Docker, Kubernetes și systemd. Acest articol prezintă modul de activare a cgroups v2, de setare a limitelor prin systemd și de aplicare a acestuia în scenarii reale de găzduire multi-tenant.

Activarea cgroups v2

Distribuțiile moderne sunt livrate cu cgroups v2 activat în mod implicit: Ubuntu 21.10+, Debian 11+, Fedora 31+ și RHEL/Rocky 9+. Sistemele mai vechi pot rula o ierarhie hibridă sau pot rămâne în continuare la v1 în mod implicit. Verificați cu:

stat -fc %T /sys/fs/cgroup/

Rezultatul comenzii cgroup2fs confirmă că v2 este activ. tmpfs înseamnă de obicei v1.

Pentru a comuta un sistem hibrid la v2 pur, editați /etc/default/grub și adăugați următoarele la GRUB_CMDLINE_LINUX_DEFAULT:

systemd.unified_cgroup_hierarchy=1 cgroup_no_v1=all

Apoi regenerați GRUB și reporniți:

sudo update-grub
sudo reboot

Pentru producție, rulați kernel 5.2 sau o versiune mai nouă, astfel încât să obțineți cgroup freezer pentru v2 și systemd 244+ pentru cpuset delegare. Pe Rocky Linux 8 și RHEL 8 s-ar putea să fie necesar să activați contabilitatea în mod explicit adăugând aceste linii la /etc/systemd/system.conf:

DefaultCPUAccounting=yes
DefaultMemoryAccounting=yes
DefaultIOAccounting=yes

Reîncărcați cu sudo systemctl daemon-reexec. După repornire, verificați ce controlere sunt disponibile:

cat /sys/fs/cgroup/cgroup.controllers

Ar trebui să vedeți cpu, memory, ioși pids listate. Aceste controlere nu sunt activate în mod implicit pentru cgroup-urile secundare. Pentru a le activa, scrieți în fișierul de control al subarborelui rădăcină:

echo "+cpu +memory +io" | sudo tee /sys/fs/cgroup/cgroup.subtree_control

Pentru o prezentare detaliată a diferențelor interne dintre v2 și v1, prezentarea lui Michael Kerrisk de la NDC TechTown este cea mai bună resursă:

Cum organizează systemd grupurile c

systemd creează un cgroup pentru fiecare serviciu pe care îl pornește, numit după unitate. nginx.service obține /sys/fs/cgroup/system.slice/nginx.service/, iar fiecare proces pe care îl generează se află în interiorul acelui cgroup. Trei tipuri de unități se mapează direct la ierarhie:

Tipul unitățiiRolDescriere
.sliceNod interiorGrupează serviciile conexe și definește limitele comune
.serviceNod terminalGestionează procesele pornite de systemd
.scopeNod frunzăUrmărește procesele pornite din exterior (încărcături ale containerelor, sesiuni de autentificare)

Patru segmente implicite sunt livrate din fabrică: -.slice (root), system.slice, user.sliceși machine.slice. Orice limită aplicată unei secțiuni se aplică automat tuturor serviciilor din aceasta.

O regulă v2 demnă de reținut: procesele pot exista doar în nodurile frunză. Un cgroup cu cgroup-uri copil nu poate găzdui direct procese, motiv pentru care systemd nu plasează niciodată serviciile în trunchiul unei secțiuni.

Setați întotdeauna limitele prin systemd, în loc să scrieți direct în /sys/fs/cgroup/ direct. Scrierile manuale nu persistă după reporniri și intră în conflict cu proprietatea exclusivă a systemd asupra ierarhiei. Utilizați systemctl set-property pentru modificări punctuale și unit drop-ins (systemctl edit nginx.service) pentru cele permanente.

Limite CPU

cgroups v2 vă oferă două controale ale CPU: o limită maximă (cpu.max, expus ca CPUQuota în systemd) și o pondere proporțională (cpu.weight / CPUWeight).

CPUQuota este o limită maximă absolută. CPUQuota=50% permite jumătate de nucleu; CPUQuota=200% permite timp echivalent cu două nuclee complete. Serviciul este limitat dacă încearcă să depășească această valoare, indiferent de cât de inactiv este restul procesorului.

CPUWeight contează doar în caz de conflict. Intervalul este de la 1 la 10.000, implicit 100. Trei servicii cu ponderi de 150, 100 și 50 primesc aproximativ 50%, 33% și 17% din timpul procesorului atunci când toate îl solicită simultan. Când CPU-ul este inactiv, ponderile nu restricționează nimic.

Pentru sarcini de lucru sensibile la latență, fixați procesele pe nuclee specifice cu AllowedCPUs=. Acest lucru reduce comutarea de context și menține cache-ul per nucleu activ:

[Service]
CPUQuota=200%
CPUWeight=150
AllowedCPUs=0-3

Utilizați o cotă fixă atunci când aveți nevoie de costuri previzibile (facturare multi-tenant, izolare de vecini zgomotoși). Utilizați ponderile atunci când doriți o utilizare maximă a hardware-ului și aveți nevoie doar de ordonarea priorităților în timpul vârfurilor de trafic.

Limite de memorie cu cgroups v2

Memoria are două niveluri: memory.high (soft, throttling) și memory.max (hard, OOM). Pentru informații generale despre swap, recuperarea paginilor și kernel OOM killer, consultați articolul nostru însoțitor despre gestionarea memoriei Linux.

Setați memory.high aproximativ 10-20% sub memory.max. Kernelul începe să recupereze pagini și să limiteze alocările odată ce memory.high este depășit, ceea ce permite de obicei recuperarea sarcinii de lucru înainte ca OOM killer să se activeze. Dacă utilizarea atinge memory.max, kernelul oprește procesele din cgroup.

O configurație tipică:

[Service]
MemoryHigh=400M
MemoryMax=512M
MemorySwapMax=0

MemorySwapMax=0 dezactivează swap-ul pentru acest cgroup. Merită făcut pentru sarcini de lucru sensibile la latență (baze de date, streaming în timp real) unde I/O-ul swap-ului ar scădea latența de coadă.

Pentru grupurile de lucrători în care lăsarea în urmă a fraților orfani ar corupe starea partajată, scrieți 1 în fișierul memory.oom.group . Când un proces este oprit din cauza OOM, kernelul oprește toate procesele din cgroup împreună.

Verificați memory.events pentru a vedea cât de des a fost limitat sau oprit un serviciu din cauza OOM:

cat /sys/fs/cgroup/system.slice/nginx.service/memory.events

Fișierul high și oom_kill vă indică dacă limitele dvs. sunt dimensionate corect. Valorile persistente diferite de zero înseamnă că sarcina de lucru are nevoie de mai mult spațiu de manevră.

Limite I/O

Controlerul I/O are același design cu două moduri: limite absolute prin io.max și partajare proporțională prin io.weight.

Limitele sunt pe dispozitiv de bloc, identificate prin numere major:minor. Găsiți-le cu lsblk -o NAME,MAJ:MIN. O configurație tipică systemd:

[Service]
IOReadBandwidthMax=/dev/sda 50M
IOWriteBandwidthMax=/dev/sda 30M
IOReadIOPSMax=/dev/sda 1000
IOWriteIOPSMax=/dev/sda 500

io.weight funcționează ca cpu.weight: intervalul 1-10.000, valoarea implicită fiind 100. Atribuirea valorii 500 unui serviciu destinat clienților și a valorii 50 unei copii de rezervă nocturne împiedică saturarea discului de către copia de rezervă în orele de vârf, dar îi permite să utilizeze lățimea de bandă completă atunci când nimic altceva nu are nevoie de ea.

Limitele I/O se aplică doar când vizați dispozitivul corect. Kernelul urmărește I/O pe dispozitiv de bloc, așa că o limită la /dev/sda nu are niciun efect asupra I/O-ului care se îndreaptă către /dev/nvme0n1. Pe gazdele cu mai multe discuri, setați limite pentru fiecare dispozitiv.

Izolarea multi-tenant cu segmente

Pentru medii partajate, definiți o secțiune pentru fiecare chiriaș. Creați /etc/systemd/system/tenant-a.slice:

[Slice]
CPUQuota=200%
CPUWeight=150
MemoryHigh=3584M
MemoryMax=4096M
MemorySwapMax=0
IOReadBandwidthMax=/dev/sda 200M
TasksMax=512

TasksMax=512 limitează numărul total de procese și thread-uri, ceea ce împiedică o bombă de fork dintr-un chiriaș să doboare gazda. Plasați serviciile chiriașului în această secțiune (prin Slice=tenant-a.slice în fișierele lor de unitate) și acestea moștenesc totul automat.

Acest model funcționează și pentru separarea activităților de fundal zgomotoase de serviciile orientate către utilizatori. Plasați backup-urile, rotația jurnalelor și sarcinile batch într-o background.slice cu CPUWeight și io.weight . Acestea primesc resurse complete când sistemul este inactiv și se retrag când sosește traficul de producție.

Pentru medii de execuție a containerelor precum Docker și Podman, adăugați Delegate=yes în fișierele lor de unitate systemd. Acest lucru le permite să-și gestioneze propriile sub-cgroups fără drepturi de root, iar limitele stabilite pentru segmentul părinte se aplică în continuare tuturor elementelor de sub acesta.

Monitorizare cu systemd-cgtop și PSI

Pentru o vizualizare în timp real de tip top a CPU, memoriei și I/O pe cgroup, rulați:

systemd-cgtop

Pentru ierarhia statică și pentru a vedea unde se află procesele, utilizați systemd-cgls.

Cea mai utilă caracteristică v2 pentru monitorizarea producției este Pressure Stall Information (PSI). PSI raportează procentul de timp în care sarcinile dintr-un cgroup au fost blocate în așteptarea unei resurse, expus în trei fișiere per cgroup:

cat /sys/fs/cgroup/tenant-a.slice/cpu.pressure
cat /sys/fs/cgroup/tenant-a.slice/memory.pressure
cat /sys/fs/cgroup/tenant-a.slice/io.pressure

Un procesor cu o utilizare de 100% și o presiune de 0% este sănătos. Fiecare sarcină care dorește procesor îl primește. Același procesor cu o utilizare de 80%, dar cu o presiune de 30% înseamnă că sarcinile stau la coadă pentru timp de execuție. Alertați-vă pe PSI, nu pe utilizare: acesta detectează conflictele pe care indicatorii de utilizare le ratează complet.

Ajustați limitele în timp real fără a reporni nimic:

sudo systemctl set-property tenant-a.slice MemoryMax=6144M

Modificarea se aplică imediat și persistă după repornire. Combinat cu alertele bazate pe PSI, acest lucru vă permite să răspundeți la schimbările de încărcare înainte ca acestea să se transforme în opriri OOM sau latență scăpată de sub control.

Dacă rulați sarcini de lucru multi-tenant de înaltă densitate și aveți nevoie de un host cu spațiu suficient pentru a aplica aceste politici în mod corespunzător, serverele noastre dedicate sunt concepute special pentru acest scop.

Blog

În prim plan săptămâna aceasta

Mai multe articole
De ce este important să aveți un VPS puternic și nemeditat

De ce este important să aveți un VPS puternic și nemeditat

Un VPS neevaluat oferă o lățime de bandă forfetară la o viteză fixă a portului. Cum diferă de planurile cu contorizare, când merită și ce trebuie să verificați înainte de cumpărare.

7 min citire - 9 mai 2025

Managementul memoriei în Linux: Swap, OOM Killer și Cgroups

12 min citire - 31 mai 2026

Mai multe articole
background image

Aveți întrebări sau aveți nevoie de o soluție personalizată?

icon

Opțiuni flexibile

icon

Acoperire globală

icon

Implementare instantanee

icon

Opțiuni flexibile

icon

Acoperire globală

icon

Implementare instantanee