Kubernetes-ով սկսելիս սովորական է մոռանալ կոնտեյներային ռեսուրսների տեղադրման մասին: Այս պահին բավական է ապահովել, որ Docker պատկերն աշխատում է և կարող է տեղակայվել Kubernetes կլաստերում:
Սակայն հետագայում հավելվածը պետք է տեղակայվի արտադրական կլաստերում՝ այլ հավելվածների հետ միասին: Դա անելու համար դուք պետք է ռեսուրսներ հատկացնեք կոնտեյների համար և համոզվեք, որ դրանք բավարար են հավելվածը գործարկելու համար, և որ մյուս գործող հավելվածները խնդիրներ չեն ունենա:
Թիմ Kubernetes aaS Mail.ru-ից թարգմանել է հոդված կոնտեյներային ռեսուրսների (CPU & MEM), հարցումների և ռեսուրսների սահմանափակումների մասին: Դուք կիմանաք այս կարգավորումների առավելությունները և ինչ տեղի կունենա, եթե դրանք չկարգավորեք:
Հաշվողական ռեսուրսներ
Մենք ունենք երկու տեսակի ռեսուրսներ հետևյալ միավորներով.
Կենտրոնական պրոցեսորային միավոր (CPU) - միջուկներ;
Հիշողություն (MEM) - բայթ:
Ռեսուրսները նշված են յուրաքանչյուր կոնտեյների համար: Հետևյալ Pod YAML ֆայլում կտեսնեք ռեսուրսների բաժին, որը պարունակում է պահանջվող և սահմանափակ ռեսուրսներ.
Requested Pod Resources = բոլոր բեռնարկղերի պահանջվող ռեսուրսների գումարը;
Pod Resource Limit = Բոլոր Pod Resource Limit-ների գումարը:
Դաշտ resources.requested ճշգրտումից Pod-ը այն տարրերից մեկն է, որն օգտագործվում է ցանկալի հանգույցը գտնելու համար: Դուք արդեն կարող եք պլանավորել Pod-ի տեղակայումը դրա համար: Ինչպե՞ս գտնել հարմար հանգույց:
Kubernetes-ը բաղկացած է մի քանի բաղադրիչներից, ներառյալ հիմնական հանգույցը կամ հիմնական հանգույցը (Kubernetes Control Plane): Հիմնական հանգույցն ունի մի քանի գործընթացներ՝ kube-apiserver, kube-controller-manager և kube-scheduler:
Kube-scheduler գործընթացը պատասխանատու է նորաստեղծ բլոկների վերանայման և հնարավոր աշխատող հանգույցների գտնելու համար, որոնք համապատասխանում են բոլոր pod հարցումներին, ներառյալ պահանջվող ռեսուրսների քանակը: Kube-scheduler-ի կողմից հայտնաբերված հանգույցների ցանկը դասակարգված է: Պոդը նախատեսված է ամենաբարձր միավորներ ունեցող հանգույցի վրա:
Որտե՞ղ է տեղադրվելու մանուշակագույն պատը:
Նկարում դուք կարող եք տեսնել, որ kube-scheduler-ը պետք է պլանավորի նոր մանուշակագույն Pod: Kubernetes կլաստերը պարունակում է երկու հանգույց՝ A և B: Ինչպես տեսնում եք, kube-scheduler-ը չի կարող պլանավորել Pod A հանգույցի վրա. հասանելի (չպահանջված) ռեսուրսները չեն համապատասխանում մանուշակագույն Pod-ի հարցումներին: Այսպիսով, մանուշակագույն Pod-ի պահանջած 1 ԳԲ հիշողությունը չի տեղավորվի A հանգույցի վրա, քանի որ հասանելի հիշողությունը 0,5 ԳԲ է: Բայց B հանգույցը բավականաչափ ռեսուրսներ ունի: Արդյունքում, kube-scheduler-ը որոշում է, որ մանուշակագույն Pod-ի նպատակակետը B հանգույցն է:
Այժմ մենք գիտենք, թե ինչպես են պահանջվող ռեսուրսներն ազդում Pod-ը գործարկելու հանգույցի ընտրության վրա: Բայց ինչպիսի՞ն է սահմանային ռեսուրսների ազդեցությունը:
Ռեսուրսի սահմանաչափը սահման է, որը CPU/MEM-ը չի կարող անցնել: Այնուամենայնիվ, պրոցեսորի ռեսուրսը ճկուն է, ուստի կոնտեյներները, որոնք հասնում են իրենց պրոցեսորի սահմաններին, չեն հանգեցնի Pod-ի դուրս գալուն: Փոխարենը կսկսվի պրոցեսորի կլանումը: Եթե MEM-ի օգտագործման սահմանաչափը հասնի, կոնտեյները կդադարեցվի OOM-Killer-ի պատճառով և կվերագործարկվի, եթե թույլատրվում է RestartPolicy կարգավորումով:
Մանրամասնորեն պահանջված և առավելագույն ռեսուրսներ
Ռեսուրսների հաղորդակցություն Docker-ի և Kubernetes-ի միջև
Լավագույն միջոցը բացատրելու, թե ինչպես են աշխատում ռեսուրսների հարցումները և ռեսուրսների սահմանափակումները, դա Kubernetes-ի և Docker-ի միջև փոխհարաբերությունների ներկայացումն է: Վերևի նկարում կարող եք տեսնել, թե ինչպես են կապված Kubernetes դաշտերը և Docker-ի գործարկման դրոշները:
Ինչպես նշվեց վերևում, հիշողությունը չափվում է բայթերով: Հիմնված Kubernetes փաստաթղթեր, մենք կարող ենք նշել հիշողությունը որպես թիվ։ Սովորաբար դա ամբողջ թիվ է, օրինակ՝ 2678, այսինքն՝ 2678 բայթ։ Կարող եք նաև օգտագործել վերջածանցներ G и Gi, գլխավորը հիշելն է, որ դրանք համարժեք չեն։ Առաջինը տասնորդական է, իսկ երկրորդը՝ երկուական։ K8s փաստաթղթերում նշված օրինակի նման. 128974848, 129e6, 129M, 123Mi - դրանք գործնականում համարժեք են։
Kubernetes տարբերակ limits.memory համապատասխանում է դրոշին --memory Docker-ից։ Դեպքում request.memory Docker-ի համար սլաք չկա, քանի որ Docker-ը չի օգտագործում այս դաշտը: Դուք կարող եք հարցնել, արդյոք դա նույնիսկ անհրաժեշտ է: Այո, անհրաժեշտ է: Ինչպես նախկինում ասացի, դաշտը կարևոր է Կուբերնետեսի համար: Դրանից ստացված տեղեկատվության հիման վրա kube-scheduler-ը որոշում է, թե որ հանգույցի վրա է պլանավորել Pod-ը:
Ի՞նչ է պատահում, եթե խնդրանքի համար բավարար հիշողություն սահմանեք:
Եթե կոնտեյները հասել է պահանջվող հիշողության սահմաններին, ապա Pod-ը տեղադրվում է Pods-ի մի խմբում, որը կանգ է առնում, երբ հանգույցում բավարար հիշողություն չկա:
Ի՞նչ է պատահում, եթե հիշողության սահմանաչափը չափազանց ցածր եք սահմանում:
Եթե բեռնարկղը գերազանցի հիշողության սահմանաչափը, այն կդադարեցվի OOM-Killed-ի պատճառով: Եվ հնարավորության դեպքում կվերագործարկվի RestartPolicy-ի հիման վրա, որտեղ լռելյայն արժեքն է Always.
Ի՞նչ կլինի, եթե չնշեք պահանջվող հիշողությունը:
Kubernetes-ը կվերցնի սահմանային արժեքը և կսահմանի այն որպես լռելյայն արժեք:
Ի՞նչ կարող է պատահել, եթե հիշողության սահմանափակում չնշեք:
Բեռնարկղը սահմանափակումներ չունի, այն կարող է օգտագործել այնքան հիշողություն, որքան ցանկանում է: Եթե նա սկսի օգտագործել հանգույցի ողջ հասանելի հիշողությունը, ապա OOM-ը կսպանի նրան։ Այնուհետև կոնտեյները կվերագործարկվի, եթե հնարավոր է, RestartPolicy-ի հիման վրա:
Ի՞նչ կլինի, եթե չնշեք հիշողության սահմանաչափերը:
Սա ամենավատ սցենարն է. ժամանակացույցը չգիտի, թե որքան ռեսուրս է պահանջում կոնտեյները, և դա կարող է լուրջ խնդիրներ առաջացնել հանգույցի վրա: Այս դեպքում լավ կլիներ անվանատարածքի լռելյայն սահմանաչափեր (սահմանված է LimitRange-ի կողմից): Լռելյայն սահմանափակումներ չկան. Pod-ը սահմանափակումներ չունի, այն կարող է օգտագործել այնքան հիշողություն, որքան ցանկանում է:
Եթե պահանջվող հիշողությունը ավելին է, քան հանգույցը կարող է առաջարկել, ապա Pod-ը չի պլանավորվի: Կարևոր է հիշել դա Requests.memory - ոչ նվազագույն արժեքը: Սա հիշողության քանակի նկարագրությունն է, որը բավարար է բեռնարկղը շարունակաբար աշխատելու համար:
Սովորաբար խորհուրդ է տրվում սահմանել նույն արժեքը request.memory и limit.memory. Սա ապահովում է, որ Kubernetes-ը չի պլանավորի Pod-ը մի հանգույցի վրա, որն ունի բավարար հիշողություն՝ Pod-ը գործարկելու համար, բայց բավարար չէ այն գործարկելու համար: Հիշեք. Kubernetes Pod պլանավորումը հաշվի է առնում միայն requests.memoryԻսկ limits.memory հաշվի չի առնում.
CPU-ով ամեն ինչ մի փոքր ավելի բարդ է: Վերադառնալով Kubernetes-ի և Docker-ի հարաբերությունների պատկերին, դուք կարող եք դա տեսնել request.cpu համապատասխանում --cpu-sharesմինչդեռ limit.cpu համապատասխանում է դրոշին cpus Docker-ում։
Պրոցեսորը, որը պահանջում է Kubernetes-ը, բազմապատկվում է 1024-ով՝ պրոցեսորի ցիկլերի համամասնությամբ: Եթե ցանկանում եք պահանջել 1 ամբողջական միջուկ, ապա պետք է ավելացնեք cpu: 1ինչպես ցույց է տրված վերևում:
Ամբողջական միջուկի պահանջը (համամասնությունը = 1024) չի նշանակում, որ ձեր կոնտեյները այն կստանա: Եթե ձեր հյուրընկալող մեքենան ունի միայն մեկ միջուկ, և դուք աշխատում եք մեկից ավելի կոնտեյներով, ապա բոլոր կոնտեյներները պետք է կիսեն հասանելի պրոցեսորը նրանց միջև: Ինչպե՞ս է դա տեղի ունենում: Եկեք նայենք նկարին։
CPU Request - Single Core համակարգ
Եկեք պատկերացնենք, որ դուք ունեք մեկ միջուկով հյուրընկալող համակարգ, որն աշխատում է կոնտեյներներ: Մայրիկը (Kubernetes) թխեց կարկանդակ (CPU) և ցանկանում է այն բաժանել երեխաների միջև (տարաներ): Երեք երեխա ուզում է մի ամբողջ կարկանդակ (համամասնություն = 1024), մեկ երեխա ուզում է կես կարկանդակ (512): Մայրիկը ցանկանում է արդար լինել և պարզ հաշվարկ է անում:
# Сколько пирогов хотят дети?
# 3 ребенка хотят по целому пирогу и еще один хочет половину пирога
cakesNumberKidsWant = (3 * 1) + (1 * 0.5) = 3.5
# Выражение получается так:
3 (ребенка/контейнера) * 1 (целый пирог/полное ядро) + 1 (ребенок/контейнер) * 0.5 (половина пирога/половина ядра)
# Сколько пирогов испечено?
availableCakesNumber = 1
# Сколько пирога (максимально) дети реально могут получить?
newMaxRequest = 1 / 3.5 =~ 28%
Հաշվարկի հիման վրա երեք երեխա կստանա միջուկի 28%-ը, այլ ոչ թե ամբողջ միջուկը։ Չորրորդ երեխան կստանա ամբողջ միջուկի 14%-ը, ոչ թե կեսը: Բայց ամեն ինչ այլ կերպ կլինի, եթե դուք ունեք բազմամիջուկ համակարգ:
CPU Request - Multi-Core (4) համակարգ
Վերևի նկարում կարող եք տեսնել, որ երեք երեխա ուզում է մի ամբողջ կարկանդակ, իսկ մեկը՝ կեսը: Քանի որ մայրիկը չորս կարկանդակ է թխել, նրա երեխաներից յուրաքանչյուրը կստանա այնքան, որքան ցանկանում է: Բազմամիջուկ համակարգում պրոցեսորային ռեսուրսները բաշխվում են բոլոր հասանելի պրոցեսորային միջուկներում: Եթե կոնտեյները սահմանափակված է մեկից պակաս ամբողջական պրոցեսորի միջուկով, այն դեռ կարող է օգտագործել այն 100%-ով:
Վերոնշյալ հաշվարկները պարզեցված են՝ հասկանալու համար, թե ինչպես է պրոցեսորը բաշխվում բեռնարկղերի միջև: Իհարկե, բացի բուն կոնտեյներներից, կան նաև այլ գործընթացներ, որոնք օգտագործում են նաև պրոցեսորի ռեսուրսները: Երբ մեկ կոնտեյների գործընթացները անգործուն են, մյուսները կարող են օգտագործել դրա ռեսուրսը: CPU: "200m" համապատասխանում CPU: 0,2, ինչը նշանակում է մեկ միջուկի մոտավորապես 20%:
Հիմա անդրադառնանք limit.cpu. Պրոցեսորը, որը սահմանափակում է Kubernetes-ը, բազմապատկվում է 100-ով: Արդյունքն այն է, թե որքան ժամանակ է բեռնարկղը կարող օգտագործել յուրաքանչյուր 100 µs (cpu-period).
limit.cpu համապատասխանում է Docker դրոշին --cpus. Սա հինի նոր համադրություն է --cpu-period и --cpu-quota. Կարգավորելով այն՝ մենք նշում ենք, թե որքան հասանելի պրոցեսորային ռեսուրսներ կարող է օգտագործել բեռնարկղը մինչև կլանումը սկսելը.
cpus - համադրություն cpu-period и cpu-quota. cpus = 1.5 համարժեք պարամետրին cpu-period = 100000 и cpu-quota = 150000;
պրոցեսոր-քվոտա - ներսում միկրովայրկյանների քանակը cpu-period, որը սահմանափակված է կոնտեյներով:
Ի՞նչ է պատահում, եթե տեղադրեք ոչ բավարար պահանջված պրոցեսոր:
Եթե կոնտեյնին ավելին է պետք, քան այն տեղադրել է, այն պրոցեսորը կգողանա այլ գործընթացներից:
Ի՞նչ է պատահում, եթե CPU-ի սահմանաչափը չափազանց ցածր եք սահմանում:
Քանի որ պրոցեսորի ռեսուրսը կարգավորելի է, շնչափողությունը կմիանա:
Ի՞նչ կլինի, եթե չնշեք պրոցեսորի հարցումը:
Ինչպես հիշողության դեպքում, հարցման արժեքը հավասար է սահմանին:
Ի՞նչ կլինի, եթե չնշեք պրոցեսորի սահմանաչափը:
Բեռնարկղը կօգտագործի այնքան պրոցեսոր, որքան անհրաժեշտ է: Եթե անվանատարածքում սահմանված է լռելյայն պրոցեսորի քաղաքականություն (LimitRange), ապա այս սահմանը նույնպես օգտագործվում է կոնտեյների համար:
Ի՞նչ կլինի, եթե չնշեք հարցում կամ պրոցեսորի սահմանաչափ:
Ինչպես հիշողության դեպքում, սա ամենավատ սցենարն է: Ժամանակացույցը չգիտի, թե որքան ռեսուրսներ են անհրաժեշտ ձեր կոնտեյներին, և դա կարող է լուրջ խնդիրներ առաջացնել հանգույցի վրա: Սրանից խուսափելու համար հարկավոր է անվանատարածքների լռելյայն սահմանաչափեր սահմանել (LimitRange):
Հիշեք. եթե դուք պահանջեք ավելի շատ պրոցեսոր, քան հանգույցները կարող են տրամադրել, Pod-ը չի պլանավորվի: Requests.cpu - ոչ թե նվազագույն արժեքը, այլ մի արժեք, որը բավարար է Pod-ը գործարկելու և առանց ձախողումների աշխատելու համար: Եթե հավելվածը բարդ հաշվարկներ չի կատարում, լավագույն տարբերակը տեղադրելն է request.cpu <= 1 և գործարկել այնքան կրկնօրինակներ, որքան անհրաժեշտ է:
Պահանջվող ռեսուրսների կամ ռեսուրսների սահմանաչափի իդեալական քանակություն
Մենք իմացանք հաշվողական ռեսուրսների սահմանափակման մասին։ Հիմա ժամանակն է պատասխանել հարցին. «Քանի՞ ռեսուրս է պահանջում իմ Pod հավելվածը առանց որևէ խնդիրների գործարկելու համար: Ո՞րն է իդեալական գումարը:
Ցավոք, այս հարցերի հստակ պատասխանները չկան։ Եթե չգիտեք, թե ինչպես է աշխատում ձեր հավելվածը կամ որքան պրոցեսոր կամ հիշողություն է պետք, լավագույն տարբերակը հավելվածին շատ հիշողություն և պրոցեսոր տալն է, այնուհետև կատարողականության թեստերը:
Բացի կատարողականի թեստերից, մեկ շաբաթ վերահսկեք հավելվածի վարքագիծը մոնիտորինգում: Եթե գրաֆիկները ցույց են տալիս, որ ձեր հավելվածը ավելի քիչ ռեսուրսներ է սպառում, քան պահանջել եք, կարող եք նվազեցնել պահանջվող պրոցեսորի կամ հիշողության քանակը:
Որպես օրինակ տես սա Grafana վահանակ. Այն ցույց է տալիս պահանջվող ռեսուրսների կամ ռեսուրսների սահմանաչափի և ընթացիկ ռեսուրսների օգտագործման տարբերությունը:
Ամփոփում
Ռեսուրսների հայցումը և սահմանափակումը օգնում է պահպանել ձեր Kubernetes կլաստերը: Սահմանի ճիշտ կազմաձևումը նվազագույնի է հասցնում ծախսերը և պահում է հավելվածների աշխատանքը միշտ:
Մի խոսքով, պետք է հիշել մի քանի բան.
Պահանջվող ռեսուրսները կոնֆիգուրացիա են, որը հաշվի է առնվում գործարկման ժամանակ (երբ Kubernetes-ը նախատեսում է հյուրընկալել հավելվածը): Ի հակադրություն, ռեսուրսների սահմանափակումը կարևոր է գործարկման ժամանակ, երբ հավելվածն արդեն աշխատում է հանգույցում:
Հիշողության համեմատ՝ պրոցեսորը կարգավորվող ռեսուրս է։ Եթե պրոցեսորը բավարար չէ, ձեր Pod-ը չի անջատվի, և շնչափող մեխանիզմը կմիանա:
Պահանջվող ռեսուրսները և ռեսուրսների սահմանաչափը նվազագույն և առավելագույն արժեքներ չեն: Սահմանելով պահանջվող ռեսուրսները՝ դուք ապահովում եք, որ հավելվածը կաշխատի առանց խնդիրների:
Լավ պրակտիկա է հիշողության պահանջը հավասարեցնել հիշողության սահմանաչափին:
Ok տեղադրումը պահանջվում է CPU <=1, եթե հավելվածը բարդ հաշվարկներ չի կատարում։
Եթե դուք պահանջում եք ավելի շատ ռեսուրսներ, քան առկա են հանգույցում, ապա Pod-ը երբեք չի պլանավորվի այդ հանգույցում:
Պահանջվող ռեսուրսների/ռեսուրսների սահմանաչափերի ճիշտ քանակը որոշելու համար օգտագործեք բեռի փորձարկում և մոնիտորինգ:
Հուսով եմ, որ այս հոդվածը կօգնի ձեզ հասկանալ ռեսուրսների սահմանափակման հիմնական հայեցակարգը: Եվ դուք կկարողանաք կիրառել այս գիտելիքները ձեր աշխատանքում: