LimitNPROC супраць TasksMax: што лічыць юніт OpenVPN
LimitNPROC лічыць працэсы аднаго карыстальніка ва ўсёй сістэме; TasksMax абмяжоўвае cgroup аднаго юніта. Прачытайце эфектыўныя значэнні, перш чым падымаць любое з іх.
Няўдалы запуск OpenVPN часта прыходзіць як скарга на рэсурсы разам з добрасардэчнай парадай падняць ліміт, і гэтая парада дапамагае прыкладна ў палове выпадкаў. За гэтымі збоямі стаяць два незвязаныя лічыльнікі. Адзін — гэта ліміт ядра на колькасць задач, якімі валодае рэальны ідэнтыфікатар карыстальніка, і ён наследуецца пры выкананні працэсу. Другі — бюджэт cgroup, які менеджар службаў прымяняе да юніта і ўсяго, што ён адгаліноўвае. Прачытаць эфектыўнае значэнне кожнага з іх для юніта, які сапраўды працуе, каштуе менш за здагадку.
Два лічыльнікі, два пытанні
LimitNPROC — гэта RLIMIT_NPROC пад імем systemd, і яго адзінка ўліку — рэальны ідэнтыфікатар карыстальніка. Кожны працэс, якім валодае гэты карыстальнік, лічыцца ў агульны лік, уключаючы працу, якую пачалі іншыя юніты, сеанс уваходу або задача планавальніка. Таму гэты ліміт не з'яўляецца абмежаваннем на асобную службу, нават калі ён зададзены ўнутры юніта службы, і служба, якая адгаліноўвае памочніка для кожнага кліента, канкуруе з усім астатнім, што працуе пад гэтым уліковым запісам. Загружаная задача cron пад тым жа карыстальнікам можа штурхнуць юніт VPN за мяжу, якую ён ніколі не перасякаў сам.
TasksMax мае іншага ўладальніка: кантролер pids на cgroup юніта, які лічыць задачы, а не працэсы. Патокі — гэта задачы, таму дэман, які выглядае аднапаточным, але мае пул працоўных, можа спажыць бюджэт, што на першы погляд значна большы за яго колькасць працэсаў. EffectiveTasksMax паказвае, што іерархія cgroup сапраўды дазваляе пасля таго, як бацькоўскія слайсы сказалі сваё слова.
Чаму выключэнне для root змяняе адказ
Ядро не прымяняе RLIMIT_NPROC да працэсу, які мае CAP_SYS_RESOURCE або CAP_SYS_ADMIN, і таму юніт, што працуе ад root без адмовы ад прывілеяў, фактычна не абмежаваны гэтым параметрам. Гэта адзінае выключэнне тлумачыць супярэчлівыя парады, якімі людзі абменьваюцца: падняць LimitNPROC выпраўляе разгортванне, якое адмовілася ад прывілеяў, і не робіць нічога для таго, што засталося прывілеяваным. Праверце User= і тое, ці змяняе дэман асобу пасля запуску, перш чым хваліць або вінаваціць гэты параметр. Прывілеяваны юніт, які пазней пераходзіць на непрывілеяваны ўліковы запіс, у момант пераходу зноў аказваецца пад лімітам, і гэта робіць храналогію збою таксама вартай прачытання.
Стадыя збою звужае гэта далей. Адмова падчас падрыхтоўкі выканання, памылка адгалінавання, якую паведамляе сам дэман, і адхіленае стварэнне задачы ўнутры cgroup даюць розныя радкі журнала, і толькі на адзін з іх адказвае большы бюджэт.
Чытайце эфектыўныя значэнні, а не тыя, што ў абалонцы
ulimit -u інтэрактыўнай абалонкі апісвае гэтую абалонку. Ён не апісвае, што менеджар службаў перадаў дэману, і нічога не кажа пра ўлік cgroup. Запытайце замест гэтага юніт, выкарыстоўваючы імя асобніка, які існуе на хаспе, а не прыклад з дапаможніка.
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
Унутры кантэйнера адказ патрабуе яшчэ двух чытанняў, бо ўнутранае значэнне infinity апісвае толькі погляд госця. Спытайце ўладальніка хаста пра ўласную мяжу pids кантэйнера і пацвердзіце, ці можа ўнутраны менеджар службаў увогуле дэлегаваць гэты кантролер. Укладзены юніт не можа трымаць бюджэт, якога яго бацькоўская cgroup ніколі не давала.
Ацаніце памер выпраўлення і давядзіце яго пад нагрузкай
Бярыце лік з працоўнай нагрузкі, а не з тэксту памылкі. Падлічыце працэсы, якія дэман запускае на кожнага падключанага кліента або на кожны выклік памочніка, памножце на паралельнасць, якую разгортванне павінна вытрымаць, дадайце запас на адміністрацыйныя сеансы, а затым параўнайце гэты лік з двума эфектыўнымі значэннямі. Лакальнае перакрыццё drop-in захоўвае змяненне даступным для праверкі і перажывае абнаўленні пакетаў, тады як рэдагаванне пастаўленага файла юніта хавае змяненне, пакуль наступнае абнаўленне не заменіць яго. Запішыце арыфметыку побач з перакрыццём, бо наступнаму чалавеку, які будзе падымаць або зніжаць яго, патрэбныя здагадкі, а не канчатковы лік.
Змяненні бюджэту прымяняюцца пры выкананні, таму адно перазагружанне не змяняе памер працэсаў, якія ўжо працуюць. Перазапусціце юніт праз яго звычайны жыццёвы цыкл, прыняўшы перапынак сеансу, і прачытайце лічыльнікі зноў на новым асобніку.
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
Выпраўленне даказвае перазапушчаны юніт, колькасць задач якога трымаецца ніжэй за абодва столі, пакуль ён нясе патрэбную нагрузку, а таксама журнал, які больш не паведамляе пра знясіленне задач або адгалінаванняў на той жа стадыі. Трымайце лікі да і пасля разам са змяненнем, каб наступнае расследаванне пачыналася з вымярэння, а не з той жа парады. Калі лік усё яшчэ дасягае столі, значыць арыфметыка была няправільнай, а не ліміт выпадкова занадта малы, і гэтую розніцу варта ведаць перад наступным перазапускам.