LimitNPROC versus TasksMax: co počítá jednotka OpenVPN
LimitNPROC počítá procesy jednoho uživatele v celém systému; TasksMax omezuje cgroup jedné jednotky. Přečtěte si efektivní hodnoty, než kteroukoli z nich zvýšíte.
Neúspěšné spuštění OpenVPN často přichází jako stížnost na prostředky spolu s dobře míněným návrhem zvýšit nějaký limit, a tento návrh zabere jen asi v polovině případů. Za těmito selháními stojí dva nesouvisející čítače. Jeden je limit jádra na počet úloh vlastněných skutečným uživatelským ID a dědí se při spuštění procesu. Druhý je rozpočet cgroup, který správce služeb uplatňuje na jednotku a na vše, co z ní vzejde. Přečíst efektivní hodnotu každého z nich pro jednotku, která skutečně běží, stojí méně než odhad.
Dva čítače, dvě otázky
LimitNPROC je RLIMIT_NPROC pod jménem systemd a jeho účetní jednotkou je skutečné uživatelské ID. Každý proces, který tento uživatel vlastní, se počítá do stejného součtu, včetně práce spuštěné jinými jednotkami, přihlašovací relací nebo úlohou plánovače. Limit tedy není stropem pro jednotlivou službu, i když je nastaven uvnitř jednotky služby, a služba, která pro každého klienta větví pomocníka, soutěží se vším ostatním, co pod tímto účtem běží. Zaneprázdněná úloha cron pod stejným uživatelem může jednotku VPN vytlačit za hranici, kterou sama nikdy nepřekročila.
TasksMax má jiného vlastníka: řadič pids na cgroup jednotky, který počítá úlohy, nikoli procesy. Vlákna jsou úlohy, takže démon, který vypadá jako jednovláknový, ale má fond pracovníků, může spotřebovat rozpočet, jenž na první pohled vypadá mnohem větší než počet jeho procesů. EffectiveTasksMax hlásí, co hierarchie cgroup skutečně dovoluje poté, co rodičovské řezy řekly své.
Proč výjimka pro root mění odpověď
Jádro neuplatňuje RLIMIT_NPROC na proces, který nese CAP_SYS_RESOURCE nebo CAP_SYS_ADMIN, a proto jednotka běžící jako root bez vzdání se oprávnění není tímto nastavením prakticky nijak omezena. Tato jediná výjimka vysvětluje protichůdné rady, které si lidé vyměňují: zvýšení LimitNPROC opraví nasazení, které se oprávnění vzdalo, a neudělá vůbec nic pro to, které zůstalo privilegované. Zkontrolujte User= a zda démon po spuštění mění identitu, než tomu nastavení přičtete zásluhu nebo vinu. Privilegovaná jednotka, která později přejde na neprivilegovaný účet, spadne pod limit v okamžiku přechodu, což činí časovou osu selhání také hodnou přečtení.
Fáze selhání to dále zužuje. Odmítnutí během přípravy spuštění, chyba větvení hlášená samotným démonem a odmítnuté vytvoření úlohy uvnitř cgroup dávají různé řádky v journalu a jen na jeden z nich odpovídá větší rozpočet.
Čtěte efektivní hodnoty, ne ty ze shellu
ulimit -u interaktivního shellu popisuje tento shell. Nepopisuje, co správce služeb předal démonovi, a nic neříká o účtování cgroup. Ptejte se místo toho jednotky, s použitím názvu instance, který na hostiteli existuje, a ne příkladu z příručky.
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
Uvnitř kontejneru potřebuje odpověď další dvě čtení, protože vnitřní hodnota infinity popisuje jen pohled hosta. Zeptejte se vlastníka hostitele na vlastní strop pids kontejneru a ověřte, zda vnitřní správce služeb může tento řadič vůbec delegovat. Vnořená jednotka nemůže držet rozpočet, který její rodičovská cgroup nikdy nepřiznala.
Nastavte velikost opravy a dokažte ji pod zátěží
Vyberte číslo ze zátěže, ne z textu chyby. Spočítejte procesy, které démon spouští na každého připojeného klienta nebo na každé vyvolání pomocníka, vynásobte souběžností, kterou má nasazení unést, přidejte rezervu pro administrativní relace a poté toto číslo porovnejte se dvěma efektivními hodnotami. Místní přepis typu drop-in udržuje změnu kontrolovatelnou a přežije aktualizace balíčků, zatímco úprava dodaného souboru jednotky skrývá změnu, dokud ji nenahradí příští aktualizace. Zapište aritmetiku vedle přepisu, protože další člověk, který ji bude zvyšovat nebo snižovat, potřebuje předpoklady, ne konečné číslo.
Změny rozpočtu se uplatňují při spuštění, takže samotné znovunačtení nezmění velikost procesů, které už běží. Restartujte jednotku jejím obvyklým životním cyklem, přijměte přerušení relace a přečtěte čítače znovu na nové instanci.
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
Opravu dokazuje restartovaná jednotka, jejíž počet úloh zůstává pod oběma stropy, zatímco nese zamýšlenou zátěž, plus journal, který už ve stejné fázi nehlásí vyčerpání úloh nebo větvení. Uchovejte čísla před a po spolu se změnou, aby příští vyšetřování začalo měřením, a ne stejnou radou. Pokud počet stále dosahuje stropu, aritmetika byla špatná, a ne limit náhodou příliš malý, a ten rozdíl stojí za to znát před dalším restartem.