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
Поправката се доказва от рестартиран юнит, чийто брой задачи стои под двата тавана, докато носи предвиденото натоварване, плюс журнал, който вече не съобщава за изчерпване на задачи или разклонявания на същия етап. Пазете числата преди и след заедно с промяната, за да започне следващото разследване от измерване, а не от същия съвет. Ако броят все още достига тавана, сметката е била грешна, а не лимитът случайно твърде малък, и тази разлика си заслужава да се знае преди следващия рестарт.