LimitNPROC ընդդեմ TasksMax-ի՝ ինչ է հաշվում OpenVPN միավորը
LimitNPROC-ը հաշվում է մեկ օգտատիրոջ պրոցեսները ողջ համակարգում, TasksMax-ը սահմանափակում է մեկ միավորի cgroup-ը։ Նախքան դրանցից որևէ մեկը բարձրացնելը կարդացեք փաստացի արժեքները։
Ձախողված OpenVPN մեկնարկը հաճախ գալիս է որպես ռեսուրսների բողոք՝ ինչ-որ սահման բարձրացնելու բարի մտադրությամբ առաջարկի հետ միասին, և այդ առաջարկը աշխատում է միայն դեպքերի մոտ կեսում։ Այդ ձախողումների հետևում կանգնած են երկու անկապ հաշվիչներ։ Մեկը միջուկի սահմանն է իրական օգտատիրոջ ID-ին պատկանող առաջադրանքների քանակի վրա, և այն ժառանգվում է պրոցեսի գործարկման պահին։ Մյուսը cgroup բյուջե է, որը ծառայությունների կառավարիչը կիրառում է միավորի և այն ամենի վրա, ինչ այն ճյուղավորում է։ Յուրաքանչյուրի փաստացի արժեքը կարդալը, այն միավորի համար, որն իսկապես աշխատում է, ավելի քիչ արժե, քան գուշակությունը։
Երկու հաշվիչ, երկու հարց
LimitNPROC-ը RLIMIT_NPROC-ն է systemd անվան տակ, և նրա հաշվառման միավորը իրական օգտատիրոջ ID-ն է։ Այդ օգտատիրոջը պատկանող յուրաքանչյուր պրոցես հաշվվում է նույն գումարի մեջ, ներառյալ այլ միավորների, մուտքի նստաշրջանի կամ պլանավորիչի առաջադրանքի սկսած աշխատանքը։ Ուստի այս սահմանը ծառայության համար առանձին վերին սահման չէ, նույնիսկ երբ սահմանված է ծառայության միավորի ներսում, և ծառայությունը, որը յուրաքանչյուր հաճախորդի համար ճյուղավորում է օգնական, մրցակցում է այդ հաշվի տակ աշխատող մնացած ամեն ինչի հետ։ Նույն օգտատիրոջ տակ զբաղված cron առաջադրանքը կարող է VPN միավորը հրել մի գծից այն կողմ, որը այն ինքը երբեք չի հատել։
TasksMax-ն այլ սեփականատեր ունի՝ միավորի cgroup-ի pids կարգավորիչը, որը հաշվում է առաջադրանքներ, ոչ թե պրոցեսներ։ Թելերը առաջադրանքներ են, ուստի մեկ թելանի տեսք ունեցող, բայց աշխատողների լողավազան ունեցող դեմոնը կարող է սպառել բյուջե, որն առաջին հայացքից շատ ավելի մեծ է թվում, քան իր պրոցեսների թիվը։ EffectiveTasksMax-ը հաղորդում է, թե cgroup հիերարխիան իրականում ինչ է թույլատրում այն բանից հետո, երբ ծնող հատվածներն ասել են իրենցը։
Ինչու է root-ի բացառությունը փոխում պատասխանը
Միջուկը չի կիրառում RLIMIT_NPROC-ը այն պրոցեսի վրա, որը կրում է CAP_SYS_RESOURCE կամ CAP_SYS_ADMIN, դրա համար էլ առանց արտոնություններից հրաժարվելու root-ով աշխատող միավորը գործնականում անսահմանափակ է այդ կարգավորմամբ։ Այս միակ բացառությունը բացատրում է մարդկանց փոխանակած հակասական խորհուրդները՝ LimitNPROC-ը բարձրացնելը վերանորոգում է արտոնություններից հրաժարված տեղակայումը և ընդհանրապես ոչինչ չի անում արտոնյալ մնացածի համար։ Ստուգեք User=-ը և արդյոք դեմոնը մեկնարկից հետո փոխում է ինքնությունը, նախքան այդ կարգավորմանը վաստակ կամ մեղք վերագրելը։ Արտոնյալ միավորը, որը հետագայում անցնում է ոչ արտոնյալ հաշվի, անցման պահին նորից հայտնվում է սահմանից ներքև, ինչը ձախողման ժամանակագրությունն էլ է ընթերցանության արժանի դարձնում։
Ձախողման փուլը սա էլ ավելի է նեղացնում։ Կատարման նախապատրաստման ժամանակ մերժումը, դեմոնի իսկ հաղորդած ճյուղավորման սխալը և cgroup-ի ներսում մերժված առաջադրանքի ստեղծումը տարբեր journal տողեր են տալիս, և դրանցից միայն մեկին է պատասխանում ավելի մեծ բյուջեն։
Կարդացեք փաստացի արժեքները, ոչ թե shell-ի
Ինտերակտիվ shell-ի ulimit -u-ը նկարագրում է հենց այդ shell-ը։ Այն չի նկարագրում, թե ծառայությունների կառավարիչը ինչ է փոխանցել դեմոնին, և ոչինչ չի ասում 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
Ուղղումն ապացուցում է վերագործարկված միավորը, որի առաջադրանքների թիվը մնում է երկու վերին սահմաններից ներքև՝ կրելով նախատեսված ծանրաբեռնվածությունը, ինչպես նաև journal, որն այլևս նույն փուլում չի հաղորդում առաջադրանքների կամ ճյուղավորման սպառման մասին։ Պահեք առաջ և հետո թվերը փոփոխության հետ միասին, որպեսզի հաջորդ հետաքննությունը սկսվի չափումից, ոչ թե նույն խորհուրդից։ Եթե թիվը դեռ հասնում է վերին սահմանին, ապա թվաբանությունը սխալ էր, ոչ թե սահմանը պատահաբար շատ փոքր, և այդ տարբերությունը արժե իմանալ հաջորդ վերագործարկումից առաջ։