Շատերը կարծում են, որ բավական է հավելվածը տեղափոխել Kubernetes (կամ օգտագործելով Helm-ը, կամ ձեռքով) - և երջանկություն կլինի: Բայց ամեն ինչ այդքան էլ պարզ չէ։
Թիմ Mail.ru Cloud Solutions թարգմանել է DevOps-ի ինժեներ Ջուլիան Գինդիի հոդվածը։ Նա պատմում է, թե ինչ որոգայթների է բախվել իր ընկերությունը միգրացիոն գործընթացի ժամանակ, որպեսզի դուք նույն փոցխին չքայլեք։
Քայլ առաջին. Ստեղծեք Pod-ի հարցումներ և սահմանափակումներ
Եկեք սկսենք ստեղծելով մաքուր միջավայր, որտեղ կաշխատեն մեր պատիճները: Kubernetes-ը հիանալի է pod պլանավորման և ձախողման հարցում: Բայց պարզվեց, որ ժամանակացույցը երբեմն չի կարող տեղադրել պատիճ, եթե դժվար է գնահատել, թե որքան ռեսուրս է անհրաժեշտ նրան հաջողությամբ աշխատելու համար: Այստեղ են հայտնվում ռեսուրսների և սահմանափակումների հարցումները: Շատ բանավեճեր կան հարցումների և սահմանափակումների սահմանման լավագույն մոտեցման մասին: Երբեմն թվում է, թե սա իսկապես ավելի շատ արվեստ է, քան գիտություն: Ահա մեր մոտեցումը.
Pod հարցումներ հիմնական արժեքն է, որն օգտագործվում է ժամանակացույցի կողմից պատիճը օպտիմալ տեղադրելու համար:
Of Kubernetes փաստաթղթերԶտիչ քայլը սահմանում է հանգույցների մի շարք, որտեղ կարելի է պլանավորել Pod: Օրինակ, PodFitsResources ֆիլտրը ստուգում է, թե արդյոք հանգույցն ունի բավարար ռեսուրսներ, որպեսզի բավարարի որոշակի ռեսուրսների պահանջները pod-ից:
Մենք օգտագործում ենք հավելվածների հարցումները այնպես, որ մենք կարող ենք գնահատել, թե քանի ռեսուրս է փաստորեն Հավելվածին անհրաժեշտ է, որ այն ճիշտ գործի: Այս կերպ ժամանակացույցը կարող է իրատեսորեն տեղադրել հանգույցները: Սկզբում մենք ցանկանում էինք չափից ավելի պլանավորել հարցումները՝ յուրաքանչյուր Pod-ի համար բավարար ռեսուրսներ ապահովելու համար, բայց մենք նկատեցինք, որ պլանավորման ժամանակը զգալիորեն ավելացել է, և որոշ Pods-ները լիովին պլանավորված չեն, կարծես ռեսուրսների հարցումներ չկան դրանց համար:
Այս դեպքում ժամանակացույցը հաճախ «քամում» էր պատյանները և չէր կարողանում դրանք վերադասավորել, քանի որ կառավարման հարթությունը պատկերացում չուներ, թե որքան ռեսուրսներ կպահանջվեն հավելվածին, ինչը պլանավորման ալգորիթմի հիմնական բաղադրիչն է:
Փոդի սահմանները ավելի հստակ սահման է պատիճի համար: Այն ներկայացնում է ռեսուրսների առավելագույն քանակը, որը կլաստերը կհատկացնի կոնտեյներին:
Կրկին, սկսած պաշտոնական փաստաթղթերԵթե կոնտեյները ունի 4 ԳԲ հիշողության սահմանաչափ, ապա kubelet-ը (և բեռնարկղի գործարկման ժամանակը) կգործադրի այն: Գործարկման ժամանակը թույլ չի տալիս, որ կոնտեյները օգտագործի նշված ռեսուրսի սահմանաչափից ավելին: Օրինակ, երբ բեռնարկղում գտնվող պրոցեսը փորձում է օգտագործել թույլատրվածից ավելի հիշողություն, համակարգի միջուկը դադարեցնում է պրոցեսը «հիշողությունից դուրս» (OOM) սխալով:
Կոնտեյները միշտ կարող է օգտագործել ավելի շատ ռեսուրսներ, քան նշված է ռեսուրսի հարցումը, բայց այն երբեք չի կարող օգտագործել սահմանից ավելին: Այս արժեքը դժվար է ճիշտ սահմանել, բայց դա շատ կարևոր է:
Իդեալում, մենք ցանկանում ենք, որ pod-ի ռեսուրսների պահանջները փոխվեն գործընթացի կյանքի ցիկլի ընթացքում՝ չխանգարելով համակարգի այլ գործընթացներին. սա սահմաններ սահմանելու նպատակն է:
Ցավոք, ես չեմ կարող կոնկրետ հրահանգներ տալ, թե ինչ արժեքներ պետք է սահմանել, բայց մենք ինքներս հավատարիմ ենք հետևյալ կանոններին.
Օգտագործելով բեռնվածության փորձարկման գործիք, մենք մոդելավորում ենք տրաֆիկի բազային մակարդակը և դիտում ենք pod ռեսուրսների օգտագործումը (հիշողություն և պրոցեսոր):
Սահմանեք պատի հարցումները կամայականորեն ցածր արժեքի (ռեսուրսների սահմանաչափով մոտ 5 անգամ, քան հարցումների արժեքը) և դիտարկեք: Երբ հարցումները չափազանց ցածր մակարդակի վրա են, գործընթացը չի կարող սկսվել՝ հաճախ առաջացնելով Go-ի գործարկման ժամանակի գաղտնի սխալներ:
Ես նշում եմ, որ ռեսուրսների ավելի բարձր սահմանաչափերը ավելի են դժվարացնում պլանավորումը, քանի որ պատիճը կարիք ունի բավարար ռեսուրսներով թիրախային հանգույցի:
Պատկերացրեք մի իրավիճակ, երբ դուք ունեք թեթև վեբ սերվեր՝ ռեսուրսների շատ բարձր սահմանաչափով, օրինակ՝ 4 ԳԲ հիշողություն: Այս գործընթացը, հավանաբար, պետք է չափավորվի հորիզոնական, և յուրաքանչյուր նոր պատիճ պետք է պլանավորվի առնվազն 4 ԳԲ հասանելի հիշողություն ունեցող հանգույցի վրա: Եթե այդպիսի հանգույց չկա, ապա կլաստերը պետք է նոր հանգույց ներկայացնի այս պատիճը մշակելու համար, որը կարող է որոշ ժամանակ տևել: Կարևոր է նվազագույն տարբերության հասնել ռեսուրսների հարցումների և սահմանաչափերի միջև՝ արագ և սահուն մասշտաբավորում ապահովելու համար:
Քայլ երկրորդ. Կենսունակության և պատրաստակամության թեստերի կարգավորում
Սա ևս մեկ նուրբ թեմա է, որը հաճախ քննարկվում է Kubernetes համայնքում: Կարևոր է լավ պատկերացում ունենալ Liveness և Readiness թեստերի մասին, քանի որ դրանք ապահովում են ծրագրաշարի կայուն աշխատանքի մեխանիզմ և նվազագույնի հասցնում պարապուրդը: Այնուամենայնիվ, դրանք կարող են լրջորեն ազդել ձեր հավելվածի աշխատանքի վրա, եթե ճիշտ կազմաձևված չեն: Ստորև ներկայացված է երկու նմուշների ամփոփ նկարագիրը:
Կենսունակություն ցույց է տալիս, թե արդյոք բեռնարկղը աշխատում է: Եթե այն ձախողվի, kubelet-ը սպանում է կոնտեյները, և վերագործարկման քաղաքականությունը միացված է դրա համար: Եթե բեռնարկղը հագեցած չէ Liveness Probe-ով, ապա լռելյայն վիճակը հաջող կլինի, ինչպես նշված է Kubernetes փաստաթղթեր.
Liveness զոնդերը պետք է լինեն էժան, այսինքն՝ չսպառեն շատ ռեսուրսներ, քանի որ դրանք հաճախ են աշխատում և պետք է տեղեկացնեն Kubernetes-ին, որ հավելվածն աշխատում է:
Եթե դուք ընտրեք ամեն վայրկյան գործարկելու տարբերակը, դա կավելացնի վայրկյանում 1 հարցում, այնպես որ տեղյակ եղեք, որ լրացուցիչ ռեսուրսներ կպահանջվեն այս տրաֆիկի մշակման համար:
Մեր ընկերությունում Liveness թեստերը փորձարկում են հավելվածի հիմնական բաղադրիչները, նույնիսկ եթե տվյալները (օրինակ՝ հեռավոր տվյալների բազայից կամ քեշից) ամբողջությամբ հասանելի չեն:
Մենք ստեղծել ենք «առողջության» վերջնակետ հավելվածներում, որը պարզապես վերադարձնում է 200 պատասխանի կոդը: Սա ցուցիչ է, որ գործընթացն աշխատում է և կարող է կարգավորել հարցումները (բայց ոչ երթևեկությունը դեռևս):
Նմուշ Պատրաստակամություն ցույց է տալիս, թե արդյոք կոնտեյները պատրաստ է սպասարկել հարցումները: Եթե պատրաստականության զոնդը ձախողվի, վերջնակետի վերահսկիչը հեռացնում է պատի IP հասցեն բոլոր ծառայությունների վերջնակետերից, որոնք համապատասխանում են pod-ին: Այս մասին ասվում է նաև Kubernetes-ի փաստաթղթերում։
Պատրաստակամության զոնդերը սպառում են ավելի շատ ռեսուրսներ, քանի որ դրանք պետք է հարվածեն հետնամասին այնպես, որ ցույց տան, որ հավելվածը պատրաստ է ընդունել հարցումները:
Համայնքում շատ բանավեճեր կան այն մասին, թե արդյոք ուղղակիորեն մուտք գործել տվյալների բազա: Հաշվի առնելով վերին ծախսերը (ստուգումները հաճախակի են, բայց դրանք կարելի է վերահսկել), մենք որոշեցինք, որ որոշ հավելվածների համար տրաֆիկի սպասարկման պատրաստակամությունը հաշվվում է միայն այն բանից հետո, երբ ստուգենք, որ տվյալների բազայից վերադարձվում են գրառումները: Լավ նախագծված պատրաստվածության փորձարկումներն ապահովեցին հասանելիության ավելի բարձր մակարդակ և վերացրեցին տեղակայման ժամանակ խափանումները:
Եթե որոշեք հարցումներ կատարել տվյալների բազայում՝ ձեր հավելվածի պատրաստվածությունը ստուգելու համար, համոզվեք, որ այն հնարավորինս էժան է: Եկեք վերցնենք այս հարցումը.
SELECT small_item FROM table LIMIT 1
Ահա մի օրինակ, թե ինչպես ենք մենք կարգավորում այս երկու արժեքները Kubernetes-ում.
periodSeconds նմուշի գործարկումների միջև սպասման միջակայքն է:
timeoutSeconds — վայրկյանների քանակը, որից հետո պատիճը համարվում է արտակարգ իրավիճակ: Սովորական ժամանակի ավարտ:
failureThreshold թեստի ձախողումների թիվն է՝ նախքան վերագործարկման ազդանշան ուղարկելը պատիճ:
successThreshold Հաջող փորձարկումների թիվն է՝ նախքան պատիճը պատրաստի վիճակի անցնելը (խափանումից հետո, երբ պատիճը գործարկվում է կամ վերականգնվում):
Քայլ երրորդ. Սահմանել Pod-ի լռելյայն ցանցային քաղաքականությունը
Kubernetes-ն ունի «հարթ» ցանցային տեղագրություն, լռելյայն բոլոր պատիճները ուղղակիորեն շփվում են միմյանց հետ։ Որոշ դեպքերում դա ցանկալի չէ։
Անվտանգության պոտենցիալ խնդիրն այն է, որ հարձակվողը կարող է օգտագործել մեկ խոցելի հավելված՝ երթևեկությունն ուղարկելու ցանցի բոլոր բլոկներին: Ինչպես անվտանգության շատ ոլորտներում, այստեղ էլ գործում է նվազագույն արտոնության սկզբունքը: Իդեալում, ցանցային քաղաքականությունը պետք է բացահայտորեն նշի, թե որ միացումներն են թույլատրվում, իսկ որոնք՝ ոչ:
Օրինակ, հետևյալ պարզ քաղաքականությունն է, որը մերժում է բոլոր մուտքային տրաֆիկը որոշակի անվանատարածքի համար.
Քայլ չորրորդ. Պատվերով վարքագիծ կեռիկների և սկզբնական բեռնարկղերի հետ
Մեր հիմնական նպատակներից մեկը Kubernetes-ում տեղակայումներ ապահովելն էր առանց ծրագրավորողների համար ընդհատումների: Սա դժվար է, քանի որ կան հավելվածները անջատելու և դրանց օգտագործված ռեսուրսները թողարկելու բազմաթիվ տարբերակներ:
Առանձնահատուկ դժվարություններ են առաջացել Nginx. Մենք նկատեցինք, որ այս Pods-ը հաջորդականությամբ տեղակայելիս ակտիվ կապերն ընդհատվել են նախքան հաջողությամբ ավարտելը:
Ինտերնետում լայնածավալ հետազոտություններից հետո պարզվեց, որ Kubernetes-ը չի սպասում, որ Nginx կապերն իրենց սպառեն նախքան pod-ն անջատելը: Pre-stop կեռիկի օգնությամբ մենք իրականացրեցինք հետևյալ ֆունկցիոնալությունը և ամբողջությամբ ազատվեցինք պարապուրդից.
#!/bin/bash
sleep 3
PID=$(cat /run/nginx.pid)
nginx -s quit
while [ -d /proc/$PID ]; do
echo "Waiting while shutting down nginx..."
sleep 10
done
Մեկ այլ չափազանց օգտակար պարադիգմ է init կոնտեյներների օգտագործումը հատուկ հավելվածների գործարկումը լուծելու համար: Սա հատկապես օգտակար է, եթե դուք ունեք ռեսուրսների ինտենսիվ տվյալների բազայի միգրացիայի գործընթաց, որը պետք է գործարկվի նախքան հավելվածի մեկնարկը: Դուք կարող եք նաև նշել ռեսուրսի ավելի բարձր սահմանաչափ այս գործընթացի համար՝ առանց հիմնական հավելվածի համար այդպիսի սահման սահմանելու:
Մեկ այլ ընդհանուր սխեման է մուտք գործել գաղտնիքներ init կոնտեյներով, որը տրամադրում է այդ հավատարմագրերը հիմնական մոդուլին, որը կանխում է գաղտնիքների չարտոնված մուտքը հիմնական հավելվածի մոդուլից:
Ինչպես միշտ, մեջբերում փաստաթղթերիցinit բեռնարկղերը ապահով կերպով գործարկում են օգտատիրոջ կոդը կամ կոմունալ ծրագրերը, որոնք հակառակ դեպքում կվտանգեն հավելվածի կոնտեյների պատկերի անվտանգությունը: Առանձին պահելով ավելորդ գործիքները՝ դուք սահմանափակում եք հավելվածի կոնտեյների պատկերի հարձակման մակերեսը:
Քայլ հինգերորդ. միջուկի կազմաձևում
Վերջապես, եկեք խոսենք ավելի առաջադեմ տեխնիկայի մասին:
Kubernetes-ը չափազանց ճկուն հարթակ է, որը թույլ է տալիս գործարկել ծանրաբեռնվածությունը, ինչպես որ հարմար եք գտնում: Մենք ունենք մի շարք բարձր արդյունավետ հավելվածներ, որոնք չափազանց ռեսուրսներ են պահանջում: Բեռնվածության լայնածավալ փորձարկում կատարելուց հետո մենք պարզեցինք, որ հավելվածներից մեկը դժվարանում էր հետևել սպասվող երթևեկության բեռին, երբ գործում էին լռելյայն Kubernetes-ի կարգավորումները:
Այնուամենայնիվ, Kubernetes-ը թույլ է տալիս գործարկել արտոնյալ կոնտեյներ, որը փոխում է միայն միջուկի պարամետրերը կոնկրետ pod-ի համար: Ահա թե ինչ ենք օգտագործել բաց կապերի առավելագույն քանակը փոխելու համար.
Սա ավելի առաջադեմ տեխնիկա է, որը հաճախ անհրաժեշտ չէ: Բայց եթե ձեր հավելվածը դժվարանում է հաղթահարել ծանր բեռը, կարող եք փորձել շտկել այս կարգավորումներից մի քանիսը: Լրացուցիչ տեղեկություններ այս գործընթացի և տարբեր արժեքներ սահմանելու մասին, ինչպես միշտ պաշտոնական փաստաթղթերում.
Վերջում
Թեև Kubernetes-ը կարող է թվալ որպես ներդաշնակ լուծում, կան մի քանի հիմնական քայլեր, որոնք պետք է ձեռնարկվեն՝ հավելվածները սահուն աշխատելու համար:
Kubernetes միգրացիայի ընթացքում կարևոր է հետևել «բեռնվածության փորձարկման ցիկլին». գործարկել հավելվածը, փորձարկել այն ծանրաբեռնվածության տակ, դիտարկել չափորոշիչները և մասշտաբային վարքագիծը, կարգավորել կոնֆիգուրացիան այս տվյալների հիման վրա, այնուհետև նորից կրկնել այս ցիկլը:
Իրատես եղեք սպասվող երթևեկության վերաբերյալ և փորձեք անցնել դրա սահմաններից՝ տեսնելու, թե որ բաղադրիչներն են առաջինը կոտրվում: Այս կրկնվող մոտեցմամբ թվարկված առաջարկներից միայն մի քանիսը կարող են բավարար լինել հաջողության հասնելու համար: Կամ կարող է պահանջվել ավելի խորը հարմարեցում:
Միշտ ինքներդ ձեզ տվեք հետևյալ հարցերը.
Քանի՞ ռեսուրս է սպառվում հավելվածների կողմից և ինչպե՞ս է փոխվելու այդ գումարը։
Որո՞նք են իրական մասշտաբի պահանջները: Միջին հաշվով որքա՞ն տրաֆիկ է սպասարկելու հավելվածը: Ինչ վերաբերում է պիկ երթեւեկությանը:
Որքա՞ն հաճախ կպահանջվի ծառայության մասշտաբը: Որքա՞ն արագ պետք է աշխատեն և աշխատեն նոր բլոկները՝ երթևեկություն ստանալու համար:
Որքանո՞վ են նրբագեղորեն փակվում պատիճները: Արդյո՞ք դա ընդհանրապես անհրաժեշտ է: Հնարավո՞ր է հասնել տեղակայման առանց պարապուրդի:
Ինչպե՞ս նվազագույնի հասցնել անվտանգության ռիսկերը և սահմանափակել վնասը ցանկացած վտանգված պատյաններից: Որևէ ծառայություններ ունե՞ն թույլտվություններ կամ մուտքեր, որոնք նրանց պետք չեն:
Kubernetes-ը տրամադրում է անհավանական հարթակ, որը թույլ է տալիս օգտագործել լավագույն փորձը՝ կլաստերի մեջ հազարավոր ծառայություններ տեղակայելու համար: Այնուամենայնիվ, բոլոր դիմումները տարբեր են: Երբեմն իրագործումը պահանջում է մի փոքր ավելի շատ աշխատանք:
Բարեբախտաբար, Kubernetes-ը տրամադրում է անհրաժեշտ կարգավորումները բոլոր տեխնիկական նպատակներին հասնելու համար: Օգտագործելով ռեսուրսների հարցումների և սահմանափակումների, Liveness և Readiness զոնդերի, սկզբնական կոնտեյներների, ցանցի քաղաքականության և միջուկի հատուկ թյունինգի համադրություն, դուք կարող եք հասնել բարձր կատարողականության, սխալների հանդուրժողականության և արագ մասշտաբայնության հետ մեկտեղ: