Պրոցեսորի սահմանափակումներ և ագրեսիվ ճնշում Kubernetes-ում

Նշում. թարգմ.Omio-ի՝ եվրոպական ճամփորդությունների ագրեգատորի այս աչք բացող պատմությունը ընթերցողներին տանում է հիմնական տեսությունից մինչև Kubernetes-ի կոնֆիգուրացիայի հետաքրքրաշարժ գործնական բարդությունները: Նման դեպքերին ծանոթ լինելն օգնում է ոչ միայն ընդլայնել ձեր մտահորիզոնը, այլև կանխել ոչ աննշան խնդիրները:

Պրոցեսորի սահմանափակումներ և ագրեսիվ ճնշում Kubernetes-ում

Երբևէ եղե՞լ է, որ հավելվածը խրվի տեղում, դադարի արձագանքել առողջական ստուգումներին և չկարողանալ պարզել, թե ինչու: Հնարավոր բացատրություններից մեկը կապված է պրոցեսորի ռեսուրսների քվոտայի սահմանափակումների հետ: Սա այն է, ինչի մասին մենք կխոսենք այս հոդվածում:

TL; DR.
Մենք խստորեն խորհուրդ ենք տալիս անջատել պրոցեսորի սահմանաչափերը Kubernetes-ում (կամ անջատել CFS քվոտաները Kubelet-ում), եթե դուք օգտագործում եք Linux միջուկի տարբերակը CFS քվոտայի սխալով: Միջուկում հասանելի լուրջ և լավ հայտնի վրիպակ, որը հանգեցնում է ավելորդ շնչափողի և ձգձգումների
.

Օմիոյում ամբողջ ենթակառուցվածքը կառավարվում է Kubernetes-ի կողմից. Մեր բոլոր պետական ​​և քաղաքացիություն չունեցող աշխատանքային բեռները գործում են բացառապես Kubernetes-ում (մենք օգտագործում ենք Google Kubernetes Engine-ը): Վերջին վեց ամսվա ընթացքում մենք սկսեցինք դիտարկել պատահական դանդաղումներ: Հավելվածները սառեցնում են կամ դադարում արձագանքել առողջական ստուգումներին, կորցնում են կապը ցանցին և այլն: Այս պահվածքը մեզ երկար տարակուսեց, և վերջապես մենք որոշեցինք լրջորեն վերաբերվել խնդրին։

Հոդվածի ամփոփում.

  • Մի քանի խոսք բեռնարկղերի և Kubernetes-ի մասին;
  • Ինչպես են իրականացվում պրոցեսորի հարցումները և սահմանափակումները.
  • Ինչպես է CPU-ի սահմանաչափը աշխատում բազմամիջուկ միջավայրում.
  • Ինչպես հետևել պրոցեսորի կլանմանը;
  • Խնդրի լուծում և նրբերանգներ.

Մի քանի խոսք բեռնարկղերի և Kubernetes-ի մասին

Kubernetes-ը, ըստ էության, ժամանակակից ստանդարտ է ենթակառուցվածքի աշխարհում: Նրա հիմնական խնդիրն է կոնտեյներային նվագախումբը։

Բեռնարկղեր

Նախկինում մենք պետք է ստեղծեինք արտեֆակտներ, ինչպիսիք են Java JAR/WAR-ները, Python Eggs-ը կամ գործարկվողները՝ սերվերների վրա գործարկելու համար: Այնուամենայնիվ, դրանք գործելու համար լրացուցիչ աշխատանք պետք է կատարվեր՝ գործարկման միջավայրի (Java/Python) տեղադրում, անհրաժեշտ ֆայլերի ճիշտ տեղերում տեղադրում, օպերացիոն համակարգի կոնկրետ տարբերակի հետ համատեղելիության ապահովում և այլն։ Այլ կերպ ասած, պետք էր զգույշ ուշադրություն դարձնել կոնֆիգուրացիայի կառավարմանը (որը հաճախ վեճի աղբյուր էր մշակողների և համակարգի ադմինիստրատորների միջև):

Տարաները փոխեցին ամեն ինչ։ Այժմ արտեֆակտը կոնտեյների պատկեր է: Այն կարող է ներկայացվել որպես ընդլայնված գործարկվող ֆայլ, որը պարունակում է ոչ միայն ծրագիրը, այլև կատարման լիարժեք միջավայր (Java/Python/...), ինչպես նաև անհրաժեշտ ֆայլեր/փաթեթներ՝ նախապես տեղադրված և պատրաստ: վազել. Կոնտեյներները կարող են տեղակայվել և գործարկվել տարբեր սերվերների վրա՝ առանց լրացուցիչ քայլերի:

Բացի այդ, բեռնարկղերը գործում են իրենց սեփական ավազատուփ միջավայրում: Նրանք ունեն իրենց սեփական վիրտուալ ցանցային ադապտեր, սեփական ֆայլային համակարգ՝ սահմանափակ հասանելիությամբ, պրոցեսների իրենց հիերարխիան, պրոցեսորի և հիշողության իրենց սահմանափակումները և այլն։ Այս ամենը իրականացվում է Linux միջուկի հատուկ ենթահամակարգի շնորհիվ՝ անվանատարածքներ։

Կուբերնետես

Ինչպես արդեն նշվեց, Kubernetes-ը կոնտեյներային նվագախմբավոր է: Այն աշխատում է այսպես. դուք տալիս եք մեքենաների լողավազան, այնուհետև ասում եք. «Հեյ, Kubernetes, եկեք գործարկենք իմ կոնտեյների տասը օրինակ՝ յուրաքանչյուրը 2 պրոցեսորով և 3 ԳԲ հիշողությամբ, և շարունակենք դրանք աշխատել»: Մնացածը կզբաղվի Կուբերնետեսով։ Այն կգտնի ազատ հզորություն, կգործարկի կոնտեյներներ և անհրաժեշտության դեպքում կվերագործարկի դրանք, թարմացում կներկայացնի տարբերակները փոխելիս և այլն: Ըստ էության, Kubernetes-ը թույլ է տալիս հեռացնել ապարատային բաղադրիչը և դարձնում է համակարգերի լայն տեսականի, որոնք հարմար են հավելվածների տեղակայման և գործարկման համար:

Պրոցեսորի սահմանափակումներ և ագրեսիվ ճնշում Kubernetes-ում
Կուբերնետեսը աշխարհականի տեսանկյունից

Որոնք են հարցումները և սահմանափակումները Kubernetes-ում

Լավ, մենք ծածկել ենք տարաներ և Kubernetes: Մենք նաև գիտենք, որ մի քանի բեռնարկղեր կարող են մնալ նույն մեքենայի վրա:

Կոմունալ բնակարանի հետ կարելի է անալոգիա անել։ Ընդարձակ տարածք (մեքենաներ/միավորներ) վերցվում է և վարձով տրվում մի քանի վարձակալների (կոնտեյներներ): Kubernetes-ը հանդես է գալիս որպես ռիելթոր: Հարց է առաջանում՝ ինչպե՞ս պահել վարձակալներին միմյանց հետ կոնֆլիկտներից։ Իսկ եթե նրանցից մեկն, ասենք, որոշի լոգարանը պարտքով վերցնել օրվա կեսը։

Հենց այստեղ են գործում խնդրանքները և սահմանափակումները: CPU Հարցում անհրաժեշտ է բացառապես պլանավորման նպատակներով: Սա կոնտեյների «ցանկությունների ցանկի» նման մի բան է և օգտագործվում է ամենահարմար հանգույցը ընտրելու համար: Միևնույն ժամանակ պրոցեսորը Սահման կարելի է համեմատել վարձակալության պայմանագրի հետ. հենց որ մենք ընտրենք միավոր կոնտեյների համար, ապա չի կարող դուրս գալ սահմանված սահմաններից. Եվ հենց այստեղ է ծագում խնդիրը...

Ինչպես են հարցումներն ու սահմանափակումներն իրականացվում Kubernetes-ում

Kubernetes-ը օգտագործում է միջուկի մեջ ներկառուցված թրթլման մեխանիզմ (ժամացույցի ցիկլերի շրջանցում)՝ պրոցեսորի սահմանաչափերն իրականացնելու համար: Եթե ​​հավելվածը գերազանցում է սահմանաչափը, ապա throttling-ը միացված է (այսինքն՝ այն ստանում է ավելի քիչ CPU ցիկլեր): Հիշողության հարցումները և սահմանափակումները կազմակերպվում են տարբեր կերպ, ուստի դրանք ավելի հեշտ է հայտնաբերել: Դա անելու համար պարզապես ստուգեք pod-ի վերջին վերագործարկման կարգավիճակը՝ արդյոք այն «OOMKilled» է: CPU-ի կլանումը այնքան էլ պարզ չէ, քանի որ K8s-ը չափիչները հասանելի է դարձնում միայն օգտագործման, այլ ոչ թե cgroup-ների:

CPU հարցում

Պրոցեսորի սահմանափակումներ և ագրեսիվ ճնշում Kubernetes-ում
Ինչպես է իրականացվում պրոցեսորի հարցումը

Պարզության համար եկեք նայենք գործընթացին, օգտագործելով 4 միջուկային պրոցեսորով մեքենա, որպես օրինակ:

K8s-ն օգտագործում է կառավարման խմբի մեխանիզմ (cgroups)՝ վերահսկելու ռեսուրսների բաշխումը (հիշողություն և պրոցեսոր): Դրա համար հասանելի է հիերարխիկ մոդել՝ երեխան ժառանգում է ծնողական խմբի սահմանները: Բաշխման մանրամասները պահվում են վիրտուալ ֆայլային համակարգում (/sys/fs/cgroup) Պրոցեսորի դեպքում սա է /sys/fs/cgroup/cpu,cpuacct/*.

K8s-ն օգտագործում է ֆայլ cpu.share պրոցեսորային ռեսուրսներ բաշխելու համար: Մեր դեպքում, root cgroup-ը ստանում է պրոցեսորի ռեսուրսների 4096 բաժնետոմս՝ հասանելի պրոցեսորի հզորության 100%-ը (1 միջուկ = 1024, սա ֆիքսված արժեք է): Արմատային խումբը ռեսուրսները բաշխում է համամասնորեն՝ կախված նրանում գրանցված ժառանգների բաժնետոմսերից cpu.share, և նրանք իրենց հերթին նույնն են անում իրենց ժառանգների հետ և այլն։ Տիպիկ Kubernetes հանգույցում արմատային c խումբը ունի երեք երեխա. system.slice, user.slice и kubepods. Առաջին երկու ենթախմբերն օգտագործվում են ռեսուրսները բաշխելու համակարգի կրիտիկական բեռների և K8-ից դուրս օգտագործողների ծրագրերի միջև: Վերջինը - kubepods — ստեղծվել է Kubernetes-ի կողմից՝ ռեսուրսները փոդերի միջև բաշխելու համար:

Վերևի դիագրամը ցույց է տալիս, որ առաջին և երկրորդ ենթախմբերը ստացել են յուրաքանչյուրը 1024 բաժնետոմսեր՝ հատկացված kuberpod ենթախմբի հետ 4096 բաժնետոմսեր Ինչպես է դա հնարավոր. ի վերջո, արմատային խմբին հասանելի է միայն 4096 բաժնետոմսերը, և նրա ժառանգների բաժնետոմսերի գումարը զգալիորեն գերազանցում է այս թիվը (6144)? Բանն այն է, որ արժեքը տրամաբանական իմաստ ունի, ուստի Linux-ի ժամանակացույցը (CFS) օգտագործում է այն՝ CPU-ի ռեսուրսները համաչափ բաշխելու համար: Մեր դեպքում առաջին երկու խմբերը ստանում են 680 իրական բաժնետոմսեր (16,6-ի 4096%), իսկ մնացածը ստանում է kubepod-ը 2736 բաժնետոմսեր Պարապուրդի դեպքում առաջին երկու խմբերը չեն օգտագործի հատկացված միջոցները։

Բարեբախտաբար, ժամանակացույցն ունի պրոցեսորի չօգտագործված ռեսուրսների վատնումից խուսափելու մեխանիզմ: Այն փոխանցում է «անգործուն» հզորությունը համաշխարհային լողավազան, որտեղից այն բաշխվում է այն խմբերին, որոնք լրացուցիչ պրոցեսորային հզորության կարիք ունեն (փոխանցումը կատարվում է խմբաքանակով՝ կլորացման կորուստներից խուսափելու համար): Նմանատիպ մեթոդ կիրառվում է ժառանգների բոլոր ժառանգների նկատմամբ։

Այս մեխանիզմը ապահովում է պրոցեսորի հզորության արդար բաշխում և երաշխավորում, որ ոչ ոք պրոցես չի «գողանում» ռեսուրսները մյուսներից:

CPU սահմանաչափ

Չնայած այն հանգամանքին, որ K8-ներում սահմանափակումների և հարցումների կազմաձևերը նման են, դրանց իրականացումը արմատապես տարբերվում է. ամենամոլորեցնողը և ամենաքիչ փաստագրված մասը:

K8-ը միանում է CFS քվոտայի մեխանիզմ սահմաններ կիրառելու համար։ Նրանց կարգավորումները նշված են ֆայլերում cfs_period_us и cfs_quota_us cgroup գրացուցակում (ֆայլը նույնպես գտնվում է այնտեղ cpu.share).

Ի տարբերություն cpu.share, քվոտան հիմնված է ժամանակահատված, և ոչ պրոցեսորի առկա հզորության վրա: cfs_period_us նշում է ժամանակաշրջանի (դարաշրջանի) տևողությունը՝ այն միշտ 100000 մկվ է (100 մվ): K8s-ում այս արժեքը փոխելու տարբերակ կա, բայց առայժմ այն ​​հասանելի է միայն ալֆայում: Ժամանակացույցն օգտագործում է դարաշրջանը՝ օգտագործված քվոտաները վերագործարկելու համար: Երկրորդ ֆայլ cfs_quota_us, նշում է հասանելի ժամանակը (քվոտան) յուրաքանչյուր դարաշրջանում։ Նշենք, որ այն նույնպես նշված է միկրովայրկյաններով։ Քվոտան կարող է գերազանցել դարաշրջանի տևողությունը. այլ կերպ ասած, այն կարող է լինել ավելի քան 100 ms:

Դիտարկենք երկու սցենար 16 միջուկային մեքենաների վրա (ամենատարածված համակարգչի տեսակը, որը մենք ունենք Omio-ում).

Պրոցեսորի սահմանափակումներ և ագրեսիվ ճնշում Kubernetes-ում
Սցենար 1. 2 շղթա և 200 ms սահմանաչափ: Ոչ մի շնչափող

Պրոցեսորի սահմանափակումներ և ագրեսիվ ճնշում Kubernetes-ում
Սցենար 2. 10 թելեր և 200 ms սահմանափակում: Շեղումը սկսվում է 20 ms-ից հետո, պրոցեսորի ռեսուրսների հասանելիությունը վերականգնվում է ևս 80 ms-ից հետո

Ենթադրենք, դուք սահմանել եք պրոցեսորի սահմանաչափը 2 միջուկներ; Kubernetes-ը այս արժեքը կթարգմանի 200 ms: Սա նշանակում է, որ կոնտեյները կարող է օգտագործել առավելագույնը 200 մս պրոցեսորի ժամանակ՝ առանց շնչափողի:

Եվ հենց այստեղ է սկսվում զվարճանքը: Ինչպես նշվեց վերևում, հասանելի քվոտան 200 մվ է: Եթե ​​զուգահեռ եք աշխատում տասը թելերը 12 միջուկանի մեքենայի վրա (տե՛ս 2-րդ սցենարի նկարը), մինչդեռ մնացած բոլոր պատյանները անգործուն են, քվոտան կսպառվի ընդամենը 20 մվ-ում (քանի որ 10 * 20 ms = 200 մվ), և այս պատի բոլոր թելերը կկախվեն: » (շնչափող) հաջորդ 80 ms-ի համար: Արդեն նշված ժամանակացույցի սխալ, որի պատճառով առաջանում է չափից ավելի շնչափողություն, և տարան չի կարողանում նույնիսկ գոյություն ունեցող քվոտան կատարել։

Ինչպե՞ս գնահատել շնչափողությունը պատիճներում:

Պարզապես մուտք գործեք պատիճ և գործարկեք cat /sys/fs/cgroup/cpu/cpu.stat.

  • nr_periods - ժամանակացույցի ժամանակաշրջանների ընդհանուր թիվը.
  • nr_throttled - բաղադրության մեջ շնչափող ժամանակաշրջանների քանակը nr_periods;
  • throttled_time - կուտակային շնչափող ժամանակը նանովայրկյաններով:

Պրոցեսորի սահմանափակումներ և ագրեսիվ ճնշում Kubernetes-ում

Ի՞նչ է իրականում կատարվում:

Արդյունքում, մենք ստանում ենք բարձր throttling բոլոր դիմումների. Երբեմն նա ներս է մտնում մեկուկես անգամ հաշվարկվածից ուժեղ!

Սա հանգեցնում է տարբեր սխալների՝ պատրաստության ստուգման ձախողումներ, կոնտեյների սառեցում, ցանցային կապի ընդմիջումներ, սպասարկման զանգերի ժամանակի ընդհատումներ: Սա, ի վերջո, հանգեցնում է հետաձգման ավելացման և սխալի ավելի բարձր մակարդակի:

Որոշում և հետևանքներ

Այստեղ ամեն ինչ պարզ է. Մենք հրաժարվեցինք պրոցեսորի սահմանափակումներից և սկսեցինք թարմացնել OS միջուկը կլաստերներում մինչև վերջին տարբերակը, որտեղ սխալը շտկվեց: Սխալների թիվը (HTTP 5xx) մեր ծառայություններում անմիջապես զգալիորեն նվազել է.

HTTP 5xx սխալներ

Պրոցեսորի սահմանափակումներ և ագրեսիվ ճնշում Kubernetes-ում
HTTP 5xx սխալներ մեկ կարևոր ծառայության համար

Արձագանքման ժամանակը p95

Պրոցեսորի սահմանափակումներ և ագրեսիվ ճնշում Kubernetes-ում
Կրիտիկական ծառայության հարցումների ուշացում, 95-րդ տոկոսը

Գործառնական ծախսեր

Պրոցեսորի սահմանափակումներ և ագրեսիվ ճնշում Kubernetes-ում
Անցած օրինակի ժամերի քանակը

Ինչ է բռնում:

Ինչպես նշված է հոդվածի սկզբում.

Կոմունալ բնակարանի հետ կարելի է անալոգիա անել... Kubernetes-ը հանդես է գալիս որպես ռիելթոր։ Բայց ինչպե՞ս պահել վարձակալներին միմյանց հետ կոնֆլիկտներից: Իսկ եթե նրանցից մեկն, ասենք, որոշի լոգարանը պարտքով վերցնել օրվա կեսը։

Ահա բռնելն է: Մեկ անփույթ բեռնարկղը կարող է խժռել մեքենայի բոլոր առկա պրոցեսորային ռեսուրսները: Եթե ​​դուք ունեք խելացի հավելվածների փաթեթ (օրինակ՝ JVM, Go, Node VM-ը ճիշտ կազմաձևված են), ապա դա խնդիր չէ. դուք կարող եք երկար ժամանակ աշխատել նման պայմաններում։ Բայց եթե հավելվածները վատ օպտիմիզացված են կամ ընդհանրապես օպտիմիզացված չեն (FROM java:latest), իրավիճակը կարող է դուրս գալ վերահսկողությունից։ Omio-ում մենք ունենք ավտոմատացված բազային Dockerfiles՝ համապատասխան լռելյայն կարգավորումներով հիմնական լեզուների փաթեթի համար, ուստի այս խնդիրը գոյություն չուներ:

Խորհուրդ ենք տալիս վերահսկել չափումները ՕԳՏԱԳՈՐԾՈՒՄ (օգտագործում, հագեցվածություն և սխալներ), API-ի ուշացումներ և սխալի մակարդակ: Համոզվեք, որ արդյունքները համապատասխանում են սպասելիքներին:

Սայլակ

Սա մեր պատմությունն է։ Հետևյալ նյութերը մեծապես օգնեցին հասկանալ, թե ինչ է կատարվում.

Kubernetes-ի սխալի մասին հաղորդում է.

Դուք բախվե՞լ եք նմանատիպ խնդիրների ձեր պրակտիկայում կամ ունեք փորձ՝ կապված բեռնարկղային արտադրական միջավայրերում շնչահեղձման հետ: Կիսվեք ձեր պատմությունը մեկնաբանություններում:

PS թարգմանչից

Կարդացեք նաև մեր բլոգում.

Source: www.habr.com

Добавить комментарий