Неуспешно покретање 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

Поправку доказује поново покренута јединица чији број задатака стоји испод оба плафона док носи предвиђено оптерећење, плус журнал који више не пријављује исцрпљивање задатака или разгранавања у истој фази. Сачувајте бројеве пре и после уз промену како би следећа истрага почела од мерења, а не од истог савета. Ако број још достиже плафон, рачуница је била погрешна, а не лимит случајно премали, и ту разлику вреди знати пре следећег рестарта.

Повезани чланци