Un arranque fallido de OpenVPN adoita chegar como unha queixa por recursos xunto cunha suxestión benintencionada de subir algún límite, e a suxestión só funciona aproximadamente a metade das veces. Detrás deses fallos hai dous contadores sen relación. Un é un límite do núcleo sobre o número de tarefas que posúe un identificador de usuario real, e herédase cando se executa o proceso. O outro é un orzamento de cgroup que o xestor de servizos aplica a unha unidade e a todo o que esta bifurca. Ler o valor efectivo de cada un, para a unidade que realmente se executa, custa menos que unha conxectura.

Dous contadores, dúas preguntas

LimitNPROC é RLIMIT_NPROC baixo un nome de systemd, e a súa unidade contable é o identificador de usuario real. Cada proceso que posúe ese usuario conta contra o mesmo total, incluído o traballo iniciado por outras unidades, por unha sesión de inicio ou por unha tarefa do planificador. O límite, xa que logo, non é un tope por servizo aínda que se defina dentro dunha unidade de servizo, e un servizo que bifurca un axudante por cada cliente compite con todo o demais que se executa con esa conta. Unha tarefa cron ocupada baixo o mesmo usuario pode empurrar unha unidade de VPN máis alá dunha liña que nunca cruzou por si soa.

TasksMax ten outro dono: o controlador pids do cgroup da unidade, que conta tarefas en lugar de procesos. Os fíos son tarefas, así que un demo que parece dun só fío pero ten un conxunto de traballadores pode consumir un orzamento que, a primeira vista, parece moito maior que o seu número de procesos. EffectiveTasksMax informa do que a xerarquía de cgroup permite realmente unha vez que os segmentos pais dixeron a súa.

Por que a excepción de root cambia a resposta

O núcleo non aplica RLIMIT_NPROC a un proceso que leva CAP_SYS_RESOURCE ou CAP_SYS_ADMIN, e por iso unha unidade que se executa como root sen renunciar aos privilexios queda efectivamente sen límite por ese axuste. Esta única excepción explica os consellos contraditorios que a xente intercambia: subir LimitNPROC repara un despregamento que renunciou aos privilexios e non fai absolutamente nada por un que seguiu privilexiado. Revise User= e se o demo cambia de identidade tras arrancar antes de dar mérito ou culpa a ese axuste. Unha unidade privilexiada que despois pasa a unha conta sen privilexios volve caer baixo o límite no momento do cambio, o que fai que a cronoloxía do fallo tamén valga a pena de ler.

A etapa do fallo acótao máis. Un rexeitamento durante a preparación da execución, un erro de bifurcación informado polo propio demo e unha creación de tarefa rexeitada dentro dun cgroup producen liñas de journal distintas, e só unha delas se responde cun orzamento maior.

Lea os valores efectivos, non os do intérprete

ulimit -u dun intérprete interactivo describe ese intérprete. Non describe o que o xestor de servizos pasou ao demo, e non di nada sobre a contabilidade de cgroup. Consulte a unidade no seu lugar, usando o nome de instancia que existe no host e non un exemplo dunha guía.

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

Dentro dun contedor a resposta necesita dúas lecturas máis, porque un valor interno de infinity só describe a visión do convidado. Pida ao propietario do host o teito de pids propio do contedor e confirme se o xestor de servizos interno pode delegar ese controlador. Unha unidade aniñada non pode soster un orzamento que o seu cgroup pai nunca concedeu.

Dimensione a corrección e demóstrea baixo carga

Escolla un número a partir da carga de traballo e non do texto do erro. Conte os procesos que o demo inicia por cliente conectado ou por invocación de axudante, multiplique pola concorrencia que se espera que soporte o despregamento, engada unha marxe para sesións administrativas e logo compare esa cifra cos dous valores efectivos. Unha substitución local de tipo drop-in mantén o cambio revisable e sobrevive ás actualizacións de paquetes, mentres que editar un ficheiro de unidade entregado oculta a modificación ata que a próxima actualización o substitúe. Escriba a aritmética xunto á substitución, porque a próxima persoa que a suba ou a baixe necesita as suposicións, non o número final.

Os cambios de orzamento aplícanse na execución, así que unha recarga por si soa non redimensiona os procesos que xa están en marcha. Reinicie a unidade polo seu ciclo de vida normal, aceptando a interrupción da sesión, e volva ler os contadores na instancia nova.

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

O que demostra a reparación é unha unidade reiniciada cuxo reconto de tarefas queda por baixo dos dous teitos mentres leva a carga prevista, ademais dun journal que xa non informa de esgotamento de tarefas ou de bifurcacións na mesma etapa. Garde os números de antes e despois co cambio para que a próxima investigación comece por unha medición e non polo mesmo consello. Se o reconto aínda acada o teito, a aritmética era errónea e non o límite demasiado pequeno por casualidade, e esa diferenza convén coñecela antes do próximo reinicio.

Artigos relacionados