LimitNPROC kontra TasksMax: hvad en OpenVPN-enhed tæller
LimitNPROC tæller én brugers processer i hele systemet; TasksMax begrænser én enheds cgroup. Læs de effektive værdier, før du hæver nogen af dem.
Et mislykket opstart af OpenVPN kommer ofte som en klage over ressourcer plus et velment forslag om at hæve en grænse, og forslaget virker kun cirka halvdelen af gangene. Bag de fejl ligger to uafhængige tællere. Den ene er en kernegrænse for antallet af opgaver, som et rigtigt bruger-ID ejer, og den nedarves, når processen køres. Den anden er et cgroup-budget, som tjenestestyringen anvender på en enhed og alt, hvad den forgrener. At læse den effektive værdi af hver af dem, for den enhed der faktisk kører, koster mindre end et gæt.
To tællere, to spørgsmål
LimitNPROC er RLIMIT_NPROC under et systemd-navn, og dens regnskabsenhed er det rigtige bruger-ID. Hver proces, som den bruger ejer, tæller med i den samme sum, inklusive arbejde startet af andre enheder, af en loginsession eller af et planlægningsjob. Grænsen er derfor ikke et loft per tjeneste, selv når den er sat inde i en tjenesteenhed, og en tjeneste, der forgrener en hjælper for hver klient, konkurrerer med alt andet, der kører under den konto. Et travlt cron-job under samme bruger kan skubbe en VPN-enhed over en linje, som den aldrig selv krydsede.
TasksMax har en anden ejer: pids-controlleren på enhedens cgroup, som tæller opgaver i stedet for processer. Tråde er opgaver, så en daemon, der ser entrådet ud, men har en arbejderpulje, kan forbruge et budget, der ved første øjekast ser langt større ud end dens procesantal. EffectiveTasksMax rapporterer, hvad cgroup-hierarkiet faktisk tillader, når de overordnede slices har sagt deres.
Hvorfor root-undtagelsen ændrer svaret
Kernen anvender ikke RLIMIT_NPROC på en proces, der bærer CAP_SYS_RESOURCE eller CAP_SYS_ADMIN, og derfor er en enhed, der kører som root uden at opgive privilegier, reelt ubegrænset af den indstilling. Denne ene undtagelse forklarer de modstridende råd, folk udveksler: at hæve LimitNPROC reparerer en udrulning, der opgav privilegier, og gør absolut intet for en, der forblev privilegeret. Tjek User= og om daemonen skifter identitet efter opstart, før du giver den indstilling æren eller skylden. En privilegeret enhed, der senere skifter til en uprivilegeret konto, falder tilbage under grænsen i skiftets øjeblik, hvilket gør fejlens tidslinje værd at læse også.
Fejlstadiet indsnævrer det yderligere. En afvisning under klargøring af kørslen, en forgreningsfejl rapporteret af daemonen selv og en afvist opgaveoprettelse inde i en cgroup giver forskellige journal-linjer, og kun én af dem besvares af et større budget.
Læs de effektive værdier, ikke shellens
ulimit -u i en interaktiv shell beskriver den shell. Det beskriver ikke, hvad tjenestestyringen sendte til daemonen, og det siger intet om cgroup-regnskab. Spørg i stedet enheden, med det instansnavn der findes på værten i stedet for et eksempel fra en vejledning.
systemctl show [email protected] -p User -p LimitNPROC -p TasksCurrent -p TasksMax -p EffectiveTasksMax
cat /proc/$(systemctl show -p MainPID --value [email protected])/limits | grep -i processes
Inde i en container kræver svaret to aflæsninger mere, fordi en indre værdi af infinity kun beskriver gæstens syn. Spørg værts ejeren om containerens eget pids-loft, og bekræft, om den indre tjenestestyring overhovedet kan delegere den controller. En indlejret enhed kan ikke holde et budget, som dens overordnede cgroup aldrig gav.
Dimensionér rettelsen og bevis den under belastning
Vælg et tal ud fra arbejdsbyrden i stedet for fra fejlteksten. Tæl de processer, daemonen starter per tilsluttet klient eller per hjælperkald, gang med den samtidighed, som udrulningen forventes at bære, læg en margen til for administrative sessioner, og sammenlign så det tal med de to effektive værdier. En lokal drop-in-tilsidesættelse holder ændringen gennemseelig og overlever pakkeopdateringer, mens redigering af en leveret enhedsfil skjuler ændringen, indtil den næste opdatering erstatter den. Skriv regnestykket ned ved siden af tilsidesættelsen, fordi den næste person, der hæver eller sænker den, har brug for antagelserne og ikke det endelige tal.
Budgetændringer anvendes ved kørsel, så en genindlæsning alene ændrer ikke størrelsen på processer, der allerede kører. Genstart enheden gennem dens normale livscyklus, accepter sessionens afbrydelse, og læs tællerne igen på den nye instans.
sudo systemctl daemon-reload
sudo systemctl restart [email protected]
systemctl show [email protected] -p TasksCurrent -p EffectiveTasksMax
sudo journalctl -u [email protected] -b --no-pager | tail -n 20
Det, der beviser reparationen, er en genstartet enhed, hvis opgaveantal ligger under begge lofter, mens den bærer den tilsigtede belastning, plus en journal, der ikke længere rapporterer opgave- eller forgreningsudmattelse på samme stadie. Gem tallene før og efter sammen med ændringen, så den næste undersøgelse starter fra en måling i stedet for fra det samme råd. Hvis antallet stadig når loftet, var regnestykket forkert, i stedet for at grænsen tilfældigvis var for lille, og den forskel er værd at kende før den næste genstart.