LimitNPROC mot TasksMax: vad en OpenVPN-enhet räknar
LimitNPROC räknar en användares processer i hela systemet; TasksMax begränsar en enhets cgroup. Läs de effektiva värdena innan du höjer någon av dem.
Ett misslyckat start av OpenVPN kommer ofta som ett klagomål på resurser plus ett välmenande förslag att höja en gräns, och förslaget fungerar bara ungefär hälften av gångerna. Bakom dessa fel står två oberoende räknare. Den ena är en kärngräns för antalet uppgifter som ett riktigt användar-ID äger, och den ärvs när processen körs. Den andra är en cgroup-budget som tjänstehanteraren tillämpar på en enhet och allt den förgrenar. Att läsa det effektiva värdet av var och en, för den enhet som faktiskt kör, kostar mindre än en gissning.
Två räknare, två frågor
LimitNPROC är RLIMIT_NPROC under ett systemd-namn, och dess redovisningsenhet är det riktiga användar-ID:t. Varje process som användaren äger räknas mot samma summa, inklusive arbete som startats av andra enheter, av en inloggningssession eller av ett schemaläggarjobb. Gränsen är därför inte ett tak per tjänst även när den är satt inne i en tjänsteenhet, och en tjänst som förgrenar en hjälpare för varje klient konkurrerar med allt annat som körs under det kontot. Ett upptaget cron-jobb under samma användare kan knuffa en VPN-enhet över en linje som den aldrig själv korsade.
TasksMax har en annan ägare: pids-styrenheten på enhetens cgroup, som räknar uppgifter i stället för processer. Trådar är uppgifter, så en daemon som ser entrådad ut men har en arbetarpool kan förbruka en budget som vid första anblicken ser långt större ut än dess processantal. EffectiveTasksMax rapporterar vad cgroup-hierarkin faktiskt tillåter när de överordnade skivorna har sagt sitt.
Varför root-undantaget ändrar svaret
Kärnan tillämpar inte RLIMIT_NPROC på en process som bär CAP_SYS_RESOURCE eller CAP_SYS_ADMIN, och därför är en enhet som körs som root utan att släppa privilegier i praktiken obegränsad av den inställningen. Detta enda undantag förklarar de motstridiga råd som människor utbyter: att höja LimitNPROC reparerar en utrullning som släppte privilegier och gör absolut ingenting för en som förblev privilegierad. Kontrollera User= och om daemonen byter identitet efter start innan du ger inställningen äran eller skulden. En privilegierad enhet som senare byter till ett oprivilegierat konto faller tillbaka under gränsen i bytesögonblicket, vilket gör felets tidslinje värd att läsa också.
Feletappen snävar in det ytterligare. En avvisning under förberedelsen av körningen, ett förgreningsfel som daemonen själv rapporterar och en avvisad uppgiftsskapning inne i en cgroup ger olika journal-rader, och bara en av dem besvaras av en större budget.
Läs de effektiva värdena, inte skalets
ulimit -u i ett interaktivt skal beskriver det skalet. Det beskriver inte vad tjänstehanteraren skickade till daemonen, och det säger ingenting om cgroup-redovisning. Fråga enheten i stället, med instansnamnet som finns på värden och inte ett exempel från en guide.
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
Inuti en container behöver svaret två läsningar till, eftersom ett inre värde av infinity bara beskriver gästens vy. Fråga värdens ägare om containerns eget pids-tak, och bekräfta om den inre tjänstehanteraren alls kan delegera den styrenheten. En nästlad enhet kan inte hålla en budget som dess överordnade cgroup aldrig gav.
Dimensionera åtgärden och bevisa den under last
Välj en siffra från arbetsbelastningen i stället för från feltexten. Räkna processerna som daemonen startar per ansluten klient eller per hjälparanrop, multiplicera med den samtidighet som utrullningen förväntas bära, lägg till en marginal för administrativa sessioner och jämför sedan siffran med de två effektiva värdena. En lokal drop-in-överskridning håller ändringen granskningsbar och överlever paketuppdateringar, medan redigering av en levererad enhetsfil döljer ändringen tills nästa uppdatering ersätter den. Skriv ner räkningen bredvid överskridningen, för nästa person som höjer eller sänker den behöver antagandena, inte slutsiffran.
Budgetändringar tillämpas vid körning, så en omladdning ensam ändrar inte storleken på processer som redan körs. Starta om enheten genom dess normala livscykel, acceptera sessionsavbrottet och läs räknarna igen på den nya instansen.
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 som bevisar åtgärden är en omstartad enhet vars uppgiftsantal ligger under båda taken medan den bär den avsedda lasten, plus en journal som inte längre rapporterar uppgifts- eller förgreningsutmattning i samma skede. Spara siffrorna före och efter tillsammans med ändringen, så att nästa undersökning börjar från en mätning och inte från samma råd. Om antalet fortfarande når taket var räkningen fel och inte gränsen slumpmässigt för liten, och den skillnaden är värd att känna till före nästa omstart.