Հինգ վրիպում Kubernetes-ում առաջին հավելվածը տեղակայելիս

Հինգ վրիպում Kubernetes-ում առաջին հավելվածը տեղակայելիսԱնհաջողություն Արիս Դրիմերի կողմից

Շատերը կարծում են, որ բավական է հավելվածը տեղափոխել Kubernetes (կամ օգտագործելով Helm-ը, կամ ձեռքով) - և երջանկություն կլինի: Բայց ամեն ինչ այդքան էլ պարզ չէ։

Թիմ Mail.ru Cloud Solutions թարգմանել է DevOps-ի ինժեներ Ջուլիան Գինդիի հոդվածը։ Նա պատմում է, թե ինչ որոգայթների է բախվել իր ընկերությունը միգրացիոն գործընթացի ժամանակ, որպեսզի դուք նույն փոցխին չքայլեք։

Քայլ առաջին. Ստեղծեք Pod-ի հարցումներ և սահմանափակումներ

Եկեք սկսենք ստեղծելով մաքուր միջավայր, որտեղ կաշխատեն մեր պատիճները: Kubernetes-ը հիանալի է pod պլանավորման և ձախողման հարցում: Բայց պարզվեց, որ ժամանակացույցը երբեմն չի կարող տեղադրել պատիճ, եթե դժվար է գնահատել, թե որքան ռեսուրս է անհրաժեշտ նրան հաջողությամբ աշխատելու համար: Այստեղ են հայտնվում ռեսուրսների և սահմանափակումների հարցումները: Շատ բանավեճեր կան հարցումների և սահմանափակումների սահմանման լավագույն մոտեցման մասին: Երբեմն թվում է, թե սա իսկապես ավելի շատ արվեստ է, քան գիտություն: Ահա մեր մոտեցումը.

Pod հարցումներ հիմնական արժեքն է, որն օգտագործվում է ժամանակացույցի կողմից պատիճը օպտիմալ տեղադրելու համար:

Of Kubernetes փաստաթղթերԶտիչ քայլը սահմանում է հանգույցների մի շարք, որտեղ կարելի է պլանավորել Pod: Օրինակ, PodFitsResources ֆիլտրը ստուգում է, թե արդյոք հանգույցն ունի բավարար ռեսուրսներ, որպեսզի բավարարի որոշակի ռեսուրսների պահանջները pod-ից:

Մենք օգտագործում ենք հավելվածների հարցումները այնպես, որ մենք կարող ենք գնահատել, թե քանի ռեսուրս է փաստորեն Հավելվածին անհրաժեշտ է, որ այն ճիշտ գործի: Այս կերպ ժամանակացույցը կարող է իրատեսորեն տեղադրել հանգույցները: Սկզբում մենք ցանկանում էինք չափից ավելի պլանավորել հարցումները՝ յուրաքանչյուր Pod-ի համար բավարար ռեսուրսներ ապահովելու համար, բայց մենք նկատեցինք, որ պլանավորման ժամանակը զգալիորեն ավելացել է, և որոշ Pods-ները լիովին պլանավորված չեն, կարծես ռեսուրսների հարցումներ չկան դրանց համար:

Այս դեպքում ժամանակացույցը հաճախ «քամում» էր պատյանները և չէր կարողանում դրանք վերադասավորել, քանի որ կառավարման հարթությունը պատկերացում չուներ, թե որքան ռեսուրսներ կպահանջվեն հավելվածին, ինչը պլանավորման ալգորիթմի հիմնական բաղադրիչն է:

Փոդի սահմանները ավելի հստակ սահման է պատիճի համար: Այն ներկայացնում է ռեսուրսների առավելագույն քանակը, որը կլաստերը կհատկացնի կոնտեյներին:

Կրկին, սկսած պաշտոնական փաստաթղթերԵթե ​​կոնտեյները ունի 4 ԳԲ հիշողության սահմանաչափ, ապա kubelet-ը (և բեռնարկղի գործարկման ժամանակը) կգործադրի այն: Գործարկման ժամանակը թույլ չի տալիս, որ կոնտեյները օգտագործի նշված ռեսուրսի սահմանաչափից ավելին: Օրինակ, երբ բեռնարկղում գտնվող պրոցեսը փորձում է օգտագործել թույլատրվածից ավելի հիշողություն, համակարգի միջուկը դադարեցնում է պրոցեսը «հիշողությունից դուրս» (OOM) սխալով:

Կոնտեյները միշտ կարող է օգտագործել ավելի շատ ռեսուրսներ, քան նշված է ռեսուրսի հարցումը, բայց այն երբեք չի կարող օգտագործել սահմանից ավելին: Այս արժեքը դժվար է ճիշտ սահմանել, բայց դա շատ կարևոր է:

Իդեալում, մենք ցանկանում ենք, որ pod-ի ռեսուրսների պահանջները փոխվեն գործընթացի կյանքի ցիկլի ընթացքում՝ չխանգարելով համակարգի այլ գործընթացներին. սա սահմաններ սահմանելու նպատակն է:

Ցավոք, ես չեմ կարող կոնկրետ հրահանգներ տալ, թե ինչ արժեքներ պետք է սահմանել, բայց մենք ինքներս հավատարիմ ենք հետևյալ կանոններին.

  1. Օգտագործելով բեռնվածության փորձարկման գործիք, մենք մոդելավորում ենք տրաֆիկի բազային մակարդակը և դիտում ենք pod ռեսուրսների օգտագործումը (հիշողություն և պրոցեսոր):
  2. Սահմանեք պատի հարցումները կամայականորեն ցածր արժեքի (ռեսուրսների սահմանաչափով մոտ 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-ում.

livenessProbe: 
 httpGet:   
   path: /api/liveness    
   port: http 
readinessProbe:  
 httpGet:    
   path: /api/readiness    
   port: http  periodSeconds: 2

Դուք կարող եք ավելացնել որոշ լրացուցիչ կազմաձևման տարբերակներ.

  • initialDelaySeconds - քանի՞ վայրկյան կանցնի կոնտեյների գործարկման և զոնդերի գործարկման մեկնարկի միջև:
  • periodSeconds նմուշի գործարկումների միջև սպասման միջակայքն է:
  • timeoutSeconds — վայրկյանների քանակը, որից հետո պատիճը համարվում է արտակարգ իրավիճակ: Սովորական ժամանակի ավարտ:
  • failureThreshold թեստի ձախողումների թիվն է՝ նախքան վերագործարկման ազդանշան ուղարկելը պատիճ:
  • successThreshold Հաջող փորձարկումների թիվն է՝ նախքան պատիճը պատրաստի վիճակի անցնելը (խափանումից հետո, երբ պատիճը գործարկվում է կամ վերականգնվում):

Քայլ երրորդ. Սահմանել Pod-ի լռելյայն ցանցային քաղաքականությունը

Kubernetes-ն ունի «հարթ» ցանցային տեղագրություն, լռելյայն բոլոր պատիճները ուղղակիորեն շփվում են միմյանց հետ։ Որոշ դեպքերում դա ցանկալի չէ։

Անվտանգության պոտենցիալ խնդիրն այն է, որ հարձակվողը կարող է օգտագործել մեկ խոցելի հավելված՝ երթևեկությունն ուղարկելու ցանցի բոլոր բլոկներին: Ինչպես անվտանգության շատ ոլորտներում, այստեղ էլ գործում է նվազագույն արտոնության սկզբունքը: Իդեալում, ցանցային քաղաքականությունը պետք է բացահայտորեն նշի, թե որ միացումներն են թույլատրվում, իսկ որոնք՝ ոչ:

Օրինակ, հետևյալ պարզ քաղաքականությունն է, որը մերժում է բոլոր մուտքային տրաֆիկը որոշակի անվանատարածքի համար.

---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:  
 name: default-deny-ingress
spec:  
 podSelector: {}  
 policyTypes:  
   - Ingress

Այս կոնֆիգուրացիայի պատկերացում.

Հինգ վրիպում Kubernetes-ում առաջին հավելվածը տեղակայելիս
(https://miro.medium.com/max/875/1*-eiVw43azgzYzyN1th7cZg.gif)
Մանրամասները այստեղ.

Քայլ չորրորդ. Պատվերով վարքագիծ կեռիկների և սկզբնական բեռնարկղերի հետ

Մեր հիմնական նպատակներից մեկը Kubernetes-ում տեղակայումներ ապահովելն էր առանց ծրագրավորողների համար ընդհատումների: Սա դժվար է, քանի որ կան հավելվածները անջատելու և դրանց օգտագործված ռեսուրսները թողարկելու բազմաթիվ տարբերակներ:

Առանձնահատուկ դժվարություններ են առաջացել Nginx. Մենք նկատեցինք, որ այս Pods-ը հաջորդականությամբ տեղակայելիս ակտիվ կապերն ընդհատվել են նախքան հաջողությամբ ավարտելը:

Ինտերնետում լայնածավալ հետազոտություններից հետո պարզվեց, որ Kubernetes-ը չի սպասում, որ Nginx կապերն իրենց սպառեն նախքան pod-ն անջատելը: Pre-stop կեռիկի օգնությամբ մենք իրականացրեցինք հետևյալ ֆունկցիոնալությունը և ամբողջությամբ ազատվեցինք պարապուրդից.

lifecycle: 
 preStop:
   exec:
     command: ["/usr/local/bin/nginx-killer.sh"]

Սակայն nginx-killer.sh:

#!/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-ի համար: Ահա թե ինչ ենք օգտագործել բաց կապերի առավելագույն քանակը փոխելու համար.

initContainers:
  - name: sysctl
     image: alpine:3.10
     securityContext:
         privileged: true
      command: ['sh', '-c', "sysctl -w net.core.somaxconn=32768"]

Սա ավելի առաջադեմ տեխնիկա է, որը հաճախ անհրաժեշտ չէ: Բայց եթե ձեր հավելվածը դժվարանում է հաղթահարել ծանր բեռը, կարող եք փորձել շտկել այս կարգավորումներից մի քանիսը: Լրացուցիչ տեղեկություններ այս գործընթացի և տարբեր արժեքներ սահմանելու մասին, ինչպես միշտ պաշտոնական փաստաթղթերում.

Վերջում

Թեև Kubernetes-ը կարող է թվալ որպես ներդաշնակ լուծում, կան մի քանի հիմնական քայլեր, որոնք պետք է ձեռնարկվեն՝ հավելվածները սահուն աշխատելու համար:

Kubernetes միգրացիայի ընթացքում կարևոր է հետևել «բեռնվածության փորձարկման ցիկլին». գործարկել հավելվածը, փորձարկել այն ծանրաբեռնվածության տակ, դիտարկել չափորոշիչները և մասշտաբային վարքագիծը, կարգավորել կոնֆիգուրացիան այս տվյալների հիման վրա, այնուհետև նորից կրկնել այս ցիկլը:

Իրատես եղեք սպասվող երթևեկության վերաբերյալ և փորձեք անցնել դրա սահմաններից՝ տեսնելու, թե որ բաղադրիչներն են առաջինը կոտրվում: Այս կրկնվող մոտեցմամբ թվարկված առաջարկներից միայն մի քանիսը կարող են բավարար լինել հաջողության հասնելու համար: Կամ կարող է պահանջվել ավելի խորը հարմարեցում:

Միշտ ինքներդ ձեզ տվեք հետևյալ հարցերը.

  1. Քանի՞ ռեսուրս է սպառվում հավելվածների կողմից և ինչպե՞ս է փոխվելու այդ գումարը։
  2. Որո՞նք են իրական մասշտաբի պահանջները: Միջին հաշվով որքա՞ն տրաֆիկ է սպասարկելու հավելվածը: Ինչ վերաբերում է պիկ երթեւեկությանը:
  3. Որքա՞ն հաճախ կպահանջվի ծառայության մասշտաբը: Որքա՞ն արագ պետք է աշխատեն և աշխատեն նոր բլոկները՝ երթևեկություն ստանալու համար:
  4. Որքանո՞վ են նրբագեղորեն փակվում պատիճները: Արդյո՞ք դա ընդհանրապես անհրաժեշտ է: Հնարավո՞ր է հասնել տեղակայման առանց պարապուրդի:
  5. Ինչպե՞ս նվազագույնի հասցնել անվտանգության ռիսկերը և սահմանափակել վնասը ցանկացած վտանգված պատյաններից: Որևէ ծառայություններ ունե՞ն թույլտվություններ կամ մուտքեր, որոնք նրանց պետք չեն:

Kubernetes-ը տրամադրում է անհավանական հարթակ, որը թույլ է տալիս օգտագործել լավագույն փորձը՝ կլաստերի մեջ հազարավոր ծառայություններ տեղակայելու համար: Այնուամենայնիվ, բոլոր դիմումները տարբեր են: Երբեմն իրագործումը պահանջում է մի փոքր ավելի շատ աշխատանք:

Բարեբախտաբար, Kubernetes-ը տրամադրում է անհրաժեշտ կարգավորումները բոլոր տեխնիկական նպատակներին հասնելու համար: Օգտագործելով ռեսուրսների հարցումների և սահմանափակումների, Liveness և Readiness զոնդերի, սկզբնական կոնտեյներների, ցանցի քաղաքականության և միջուկի հատուկ թյունինգի համադրություն, դուք կարող եք հասնել բարձր կատարողականության, սխալների հանդուրժողականության և արագ մասշտաբայնության հետ մեկտեղ:

Էլ ի՞նչ կարդալ.

  1. Արտադրական միջավայրում բեռնարկղերի և Kubernetes-ի գործարկման լավագույն պրակտիկաները և լավագույն փորձը.
  2. 90+ օգտակար գործիքներ Kubernetes-ի համար՝ տեղակայում, կառավարում, մոնիտորինգ, անվտանգություն և այլն.
  3. Մեր ալիքը Kubernetes-ի շուրջ Telegram-ում.

Source: www.habr.com

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