Devyni „Kubernetes“ našumo patarimai

Devyni „Kubernetes“ našumo patarimai

Sveiki visi! Mano vardas Olegas Sidorenkovas, dirbu „DomClick“ infrastruktūros komandos vadovu. Kubik gamyboje naudojame daugiau nei trejus metus ir per šį laiką su juo patyrėme daug įvairių įdomių akimirkų. Šiandien aš jums papasakosiu, kaip taikydami tinkamą požiūrį galite iš vanilinio „Kubernetes“ išspausti dar daugiau savo grupės našumo. Pasiruošt dėmesio marš!

Visi puikiai žinote, kad Kubernetes yra keičiamo dydžio atvirojo kodo sistema, skirta konteinerių orkestravimui; Na, arba 5 dvejetainiai failai, kurie veikia stebuklingai valdydami jūsų mikropaslaugų gyvavimo ciklą serverio aplinkoje. Be to, tai gana lankstus įrankis, kurį galima surinkti kaip „Lego“, kad būtų galima maksimaliai pritaikyti įvairioms užduotims.

Ir atrodo, kad viskas gerai: meskite serverius į klasterį kaip malkas į pakurą ir nepažinsite jokio sielvarto. Bet jei esate už aplinką, pagalvosite: „Kaip man išlaikyti ugnį ir tausoti mišką? Kitaip tariant, kaip rasti būdų, kaip pagerinti infrastruktūrą ir sumažinti išlaidas.

1. Stebėkite komandos ir taikomųjų programų išteklius

Devyni „Kubernetes“ našumo patarimai

Vienas iš labiausiai paplitusių, bet veiksmingų metodų yra užklausų/ribų įvedimas. Padalinkite programas pagal vardų sritis, o vardų sritis pagal kūrimo komandas. Prieš diegdami nustatykite procesoriaus laiko, atminties ir trumpalaikės saugyklos sunaudojimo programos reikšmes.

resources:
   requests:
     memory: 2Gi
     cpu: 250m
   limits:
     memory: 4Gi
     cpu: 500m

Remdamiesi patirtimi padarėme išvadą: neturėtumėte išpūsti užklausų iš limitų daugiau nei du kartus. Klasterio tūris apskaičiuojamas pagal užklausas, o jei programoms skirsite išteklius, pavyzdžiui, 5–10 kartų, tada įsivaizduokite, kas nutiks jūsų mazgui, kai jis bus užpildytas ankštimis ir staiga gaus apkrovą. Nieko gero. Mažiausiai, droseliai, o maksimaliai, atsisveikinsite su darbuotoju ir cikliškai apkrausite likusius mazgus, kai ankštys pradės judėti.

Be to, su pagalba limitranges Pradžioje galite nustatyti konteinerio išteklių reikšmes - minimalias, maksimalias ir numatytąsias:

➜  ~ kubectl describe limitranges --namespace ops
Name:       limit-range
Namespace:  ops
Type        Resource           Min   Max   Default Request  Default Limit  Max Limit/Request Ratio
----        --------           ---   ---   ---------------  -------------  -----------------------
Container   cpu                50m   10    100m             100m           2
Container   ephemeral-storage  12Mi  8Gi   128Mi            4Gi            -
Container   memory             64Mi  40Gi  128Mi            128Mi          2

Nepamirškite apriboti vardų erdvės išteklių, kad viena komanda negalėtų perimti visų klasterio išteklių:

➜  ~ kubectl describe resourcequotas --namespace ops
Name:                   resource-quota
Namespace:              ops
Resource                Used          Hard
--------                ----          ----
limits.cpu              77250m        80
limits.memory           124814367488  150Gi
pods                    31            45
requests.cpu            53850m        80
requests.memory         75613234944   150Gi
services                26            50
services.loadbalancers  0             0
services.nodeports      0             0

Kaip matyti iš aprašymo resourcequotas, jei operacijų komanda nori įdiegti blokus, kurie sunaudos dar 10 procesorių, planuotojas to neleis ir parodys klaidą:

Error creating: pods "nginx-proxy-9967d8d78-nh4fs" is forbidden: exceeded quota: resource-quota, requested: limits.cpu=5,requests.cpu=5, used: limits.cpu=77250m,requests.cpu=53850m, limited: limits.cpu=10,requests.cpu=10

Norėdami išspręsti tokią problemą, galite parašyti įrankį, pavyzdžiui, patinka tai, galintis saugoti ir nustatyti valdymo būsenos išteklius.

2. Pasirinkite optimalią failų saugyklą

Devyni „Kubernetes“ našumo patarimai

Čia norėčiau paliesti nuolatinių tomų ir Kubernetes darbuotojų mazgų disko posistemio temą. Tikiuosi, kad gamyboje niekas nenaudoja HDD „Kubo“, tačiau kartais įprasto SSD nebeužtenka. Susidūrėme su problema, kai žurnalai sunaikino diską dėl įvesties / išvesties operacijų, ir nėra daug sprendimų:

  • Naudokite didelio našumo SSD arba perjunkite į NVMe (jei tvarkote savo aparatinę įrangą).

  • Sumažinkite registravimo lygį.

  • Atlikite „protingą“ diską išprievartaujančių ankščių balansavimą (podAntiAffinity).

Aukščiau esančiame ekrane parodyta, kas nutinka nginx-ingress-controller diske, kai įjungtas access_logs registravimas (~12 tūkst. žurnalų/sek). Žinoma, ši sąlyga gali sukelti visų šio mazgo programų pablogėjimą.

Kalbant apie PV, deja, aš ne viską išbandžiau rūšis Nuolatiniai tomai. Naudokite geriausią jums tinkantį variantą. Istoriškai mūsų šalyje susiklostė taip, kad nedidelei daliai paslaugų reikia RWX apimties, o jau seniai šiai užduočiai buvo pradėta naudoti NFS saugykla. Pigu ir... pakankamai. Žinoma, jis ir aš valgėme šūdą – palaimink tave, bet mes išmokome tai sureguliuoti, ir man galvos nebeskauda. Ir jei įmanoma, perkelkite į S3 objektų saugyklą.

3. Surinkite optimizuotus vaizdus

Devyni „Kubernetes“ našumo patarimai

Geriausia naudoti konteineriams optimizuotus vaizdus, ​​kad „Kubernetes“ galėtų juos greičiau gauti ir efektyviau vykdyti. 

Optimizuotas reiškia, kad vaizdai:

  • turėti tik vieną programą arba atlikti tik vieną funkciją;

  • mažas dydis, nes dideli vaizdai tinkle perduodami blogiau;

  • turėti sveikatos ir parengties galutinius taškus, leidžiančius Kubernetes imtis veiksmų prastovos atveju;

  • naudoti konteineriams pritaikytas operacines sistemas (pvz., Alpine ar CoreOS), kurios yra atsparesnės konfigūracijos klaidoms;

  • naudokite kelių pakopų versijas, kad galėtumėte diegti tik sukompiliuotas programas, o ne pridedamus šaltinius.

Yra daug įrankių ir paslaugų, leidžiančių patikrinti ir optimizuoti vaizdus skrendant. Svarbu, kad jie visada būtų atnaujinami ir patikrinami dėl saugumo. Dėl to jūs gaunate:

  1. Sumažinta viso klasterio tinklo apkrova.

  2. Sutrumpėja konteinerio paleidimo laikas.

  3. Mažesnis viso „Docker“ registro dydis.

4. Naudokite DNS talpyklą

Devyni „Kubernetes“ našumo patarimai

Jei kalbėsime apie dideles apkrovas, gyvenimas yra gana niūrus, jei nederiname klasterio DNS sistemos. Kadaise Kubernetes kūrėjai palaikė savo kube-dns sprendimą. Čia taip pat buvo įdiegta, tačiau ši programinė įranga nebuvo itin sureguliuota ir nesuteikė reikiamo našumo, nors atrodė, kad tai paprasta užduotis. Tada pasirodė coredns, į kurį perėjome ir nesigailėjome; vėliau tai tapo numatyta K8s DNS paslauga. Kažkuriuo metu DNS sistemai išaugome iki 40 tūkstančių rps, ir šis sprendimas taip pat tapo nepakankamas. Tačiau laimei pasirodė Nodelocaldns, dar žinomas kaip mazgo vietinė talpykla, dar žinoma NodeLocal DNSCache.

Kodėl mes tai naudojame? „Linux“ branduolyje yra klaida, kuri, kai keli iškvietimai per conntrack NAT per UDP, sukelia varžybų sąlygą įrašams conntrack lentelėse ir prarandama dalis srauto per NAT (kiekviena kelionė per paslaugą yra NAT). „Nodelocaldns“ išsprendžia šią problemą, atsikratydamas NAT ir atnaujindamas ryšį su TCP į aukštesnės srovės DNS, taip pat lokaliai talpykloje saugodamas aukštesnės srovės DNS užklausas (įskaitant trumpą 5 sekundžių neigiamą talpyklą).

5. Automatiškai paskirstykite mastelius horizontaliai ir vertikaliai

Devyni „Kubernetes“ našumo patarimai

Ar galite drąsiai teigti, kad visos jūsų mikropaslaugos yra pasirengusios 2–3 kartus padidinti apkrovą? Kaip tinkamai paskirstyti išteklius savo programoms? Gali būti, kad keleto blokų leisti veikti virš darbo krūvio gali būti perteklinis, tačiau laikant juos atgal, kyla prastovų rizika dėl staigaus srauto į paslaugą padidėjimo. Tokios paslaugos kaip Horizontalus Pod Autoscaler и Vertical Pod Autoscaler.

SPS leidžia automatiškai padidinti jūsų talpyklų užklausas / apribojimus, atsižvelgiant į faktinį naudojimą. Kaip tai gali būti naudinga? Jei turite blokus, kurių dėl kokių nors priežasčių negalima pakeisti horizontaliai (tai nėra visiškai patikima), galite pabandyti patikėti jo išteklių pakeitimus VPA. Jo funkcija yra rekomendacijų sistema, pagrįsta istoriniais ir dabartiniais metrikos serverio duomenimis, todėl, jei nenorite automatiškai keisti užklausų / apribojimų, galite tiesiog stebėti rekomenduojamus konteinerių išteklius ir optimizuoti nustatymus, kad sutaupytumėte procesorių ir atmintis klasteryje.

Devyni „Kubernetes“ našumo patarimaiVaizdas paimtas iš https://levelup.gitconnected.com/kubernetes-autoscaling-101-cluster-autoscaler-horizontal-pod-autoscaler-and-vertical-pod-2a441d9ad231

Kubernetes planavimo priemonė visada pagrįsta užklausomis. Kad ir kokią reikšmę įvestumėte, planuotojas pagal ją ieškos tinkamo mazgo. Ribinės vertės reikalingos, kad kubelis suprastų, kada reikia išspausti ar nužudyti ankštį. Ir kadangi vienintelis svarbus parametras yra užklausų reikšmė, VPA veiks su ja. Kai vertikaliai padidinate programos mastelį, apibrėžiate, kokios užklausos turi būti. Kas tada atsitiks su ribomis? Šis parametras taip pat bus proporcingai pakeistas.

Pavyzdžiui, čia pateikiami įprasti podėlio nustatymai:

resources:
   requests:
     memory: 250Mi
     cpu: 200m
   limits:
     memory: 500Mi
     cpu: 350m

Rekomendacijų variklis nustato, kad jūsų programai reikia 300 m procesoriaus ir 500 Mi, kad jis tinkamai veiktų. Gausite šiuos nustatymus:

resources:
   requests:
     memory: 500Mi
     cpu: 300m
   limits:
     memory: 1000Mi
     cpu: 525m

Kaip minėta pirmiau, tai yra proporcingas mastelio keitimas, pagrįstas užklausų ir apribojimų santykiu manifeste:

  • CPU: 200m → 300m: santykis 1:1.75;

  • Atmintis: 250Mi → 500Mi: santykis 1:2.

dėl HPA, tada veikimo mechanizmas yra skaidresnis. Metrika, pvz., CPU ir atmintis, yra apribota, o jei visų kopijų vidurkis viršija slenkstį, programa padidinama +1 dalimi, kol vertė nukrenta žemiau slenksčio arba kol pasiekiamas maksimalus kopijų skaičius.

Devyni „Kubernetes“ našumo patarimaiVaizdas paimtas iš https://levelup.gitconnected.com/kubernetes-autoscaling-101-cluster-autoscaler-horizontal-pod-autoscaler-and-vertical-pod-2a441d9ad231

Be įprastų metrikų, tokių kaip centrinis procesorius ir atmintis, galite nustatyti tinkintų „Prometheus“ metrikų slenksčius ir su jomis dirbti, jei manote, kad tai tiksliausias nurodymas, kada reikia keisti programą. Kai programa stabilizuosis žemiau nurodytos metrikos slenksčio, HPA pradės mažinti rinkinių mastelį iki minimalaus kopijų skaičiaus arba tol, kol apkrova pasieks nurodytą slenkstį.

6. Nepamirškite apie Node Affinity ir Pod Affinity

Devyni „Kubernetes“ našumo patarimai

Ne visi mazgai veikia ta pačia aparatūra ir ne visuose blokuose reikia paleisti daug skaičiavimo reikalaujančias programas. „Kubernetes“ leidžia nustatyti mazgų ir ankščių specializaciją naudojant Mazgo giminingumas и Pod Affinity.

Jei turite mazgų, tinkamų daug skaičiuoti reikalaujančioms operacijoms, tada, siekiant maksimalaus efektyvumo, geriau susieti programas su atitinkamais mazgais. Norėdami tai padaryti, naudokite nodeSelector su mazgo etikete.

Tarkime, kad turite du mazgus: vieną su CPUType=HIGHFREQ ir daug greitų branduolių, kitas su MemoryType=HIGHMEMORY daugiau atminties ir greitesnis veikimas. Lengviausias būdas yra priskirti diegimą mazgui HIGHFREQpridedant prie skyriaus spec šis parinkiklis:

…
nodeSelector:
	CPUType: HIGHFREQ

Brangesnis ir konkretesnis būdas tai padaryti yra naudoti nodeAffinity lauke affinity razdela spec. Yra dvi parinktys:

  • requiredDuringSchedulingIgnoredDuringExecution: sunkus nustatymas (planavimo priemonė įdiegs blokus tik konkrečiuose mazguose (ir niekur kitur));

  • preferredDuringSchedulingIgnoredDuringExecution: minkštas nustatymas (planavimo priemonė bandys įdiegti konkrečiuose mazguose, o jei nepavyks, bandys įdiegti į kitą galimą mazgą).

Galite nurodyti konkrečią mazgų etikečių valdymo sintaksę, pvz., In, NotIn, Exists, DoesNotExist, Gt arba Lt. Tačiau atminkite, kad sudėtingi metodai ilguose etikečių sąrašuose sulėtins sprendimų priėmimą kritinėse situacijose. Kitaip tariant, būkite paprasta.

Kaip minėta aukščiau, „Kubernetes“ leidžia nustatyti esamų ankščių giminingumą. Tai reiškia, kad galite įsitikinti, kad tam tikri rinkiniai veikia kartu su kitomis toje pačioje pasiekiamumo zonoje (būtina debesims) arba mazguose.

В podAffinity maržos affinity razdela spec galimi tie patys laukai kaip ir atveju nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution и preferredDuringSchedulingIgnoredDuringExecution. Vienintelis skirtumas yra tas matchExpressions sujungs ankštis su mazgu, kuriame jau veikia ankštis su ta etikete.

„Kubernetes“ taip pat siūlo lauką podAntiAffinity, kuri, priešingai, nesuriša ankšties prie mazgo su specifinėmis ankštimis.

Apie posakius nodeAffinity Galima duoti tą patį patarimą: stenkitės, kad taisyklės būtų paprastos ir logiškos, nemėginkite perkrauti pod specifikacijos sudėtingu taisyklių rinkiniu. Labai lengva sukurti taisyklę, kuri neatitiks klasterio sąlygų, sukuriant nereikalingą planuotojo apkrovą ir sumažinant bendrą našumą.

7. Sutepimai ir tolerancijos

Yra ir kitas būdas valdyti planuoklį. Jei turite didelę klasterį su šimtais mazgų ir tūkstančiais mikropaslaugų, labai sunku neleisti, kad tam tikri blokai būtų talpinami tam tikruose mazguose.

Tam padeda nešvarumų mechanizmas – draudžiančios taisyklės. Pavyzdžiui, tam tikrais scenarijais galite uždrausti tam tikriems mazgams paleisti blokus. Norėdami pritaikyti užteršimą konkrečiam mazgui, turite naudoti parinktį taint kubectl. Nurodykite raktą ir vertę, tada kaip sugadinti NoSchedule arba NoExecute:

$ kubectl taint nodes node10 node-role.kubernetes.io/ingress=true:NoSchedule

Taip pat verta paminėti, kad užteršimo mechanizmas palaiko tris pagrindinius efektus: NoSchedule, NoExecute и PreferNoSchedule.

  • NoSchedule reiškia, kad kol kas atitinkamo įrašo pod specifikacijoje nebus tolerations, jo nebus galima įdiegti mazge (šiame pavyzdyje node10).

  • PreferNoSchedule - supaprastinta versija NoSchedule. Tokiu atveju planuotojas stengsis neskirti ankštų, kurios neturi atitinkamo įrašo tolerations vienam mazgui, tačiau tai nėra griežtas apribojimas. Jei klasteryje nėra išteklių, šiame mazge pradės diegti ankštys.

  • NoExecute - dėl šio poveikio ankštys, neturinčios atitinkamo įėjimo, nedelsiant evakuojamos tolerations.

Įdomu tai, kad šį elgesį galima atšaukti naudojant tolerancijos mechanizmą. Tai patogu, kai yra „uždraustas“ mazgas ir jame tereikia talpinti infrastruktūros paslaugas. Kaip tai padaryti? Leisti tik tas ankštis, kurioms yra tinkama tolerancija.

Štai kaip atrodytų ankšties specifikacija:

spec:
   tolerations:
     - key: "node-role.kubernetes.io/ingress"
        operator: "Equal"
        value: "true"
        effect: "NoSchedule"

Tai nereiškia, kad kitas perskirstymas atiteks būtent šiam mazgui, tai nėra mazgo giminystės mechanizmas ir nodeSelector. Tačiau derindami kelias funkcijas galite pasiekti labai lanksčius planavimo nustatymus.

8. Nustatykite Pod diegimo prioritetą

Vien todėl, kad mazgams priskirtos ankštys, dar nereiškia, kad visos ankštys turi būti traktuojamos vienodai. Pvz., Galbūt norėsite įdiegti kai kuriuos blokus prieš kitus.

„Kubernetes“ siūlo skirtingus būdus, kaip konfigūruoti „Pod Priority“ ir „Preemption“. Nustatymas susideda iš kelių dalių: objekto PriorityClass ir laukų aprašymus priorityClassName ankšties specifikacijoje. Pažiūrėkime į pavyzdį:

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority
value: 99999
globalDefault: false
description: "This priority class should be used for very important pods only"

Mes kuriame PriorityClass, nurodykite pavadinimą, aprašymą ir vertę. Kuo aukštesnis value, tuo didesnis prioritetas. Vertė gali būti bet koks 32 bitų sveikasis skaičius, mažesnis arba lygus 1 000 000 000. Didesnės vertės yra skirtos svarbioms sistemos grupėms, kurių paprastai negalima išvengti. Poslinkis įvyks tik tuo atveju, jei aukšto prioriteto ankštys neturi kur apsisukti, tada kai kurios ankštys iš tam tikro mazgo bus evakuojamos. Jei šis mechanizmas jums per standus, galite pridėti parinktį preemptionPolicy: Never, ir tada pirmumo nebus, podas stovės pirmas eilėje ir lauks, kol planuotojas suras laisvų išteklių.

Tada sukuriame ankštį, kurioje nurodome pavadinimą priorityClassName:

apiVersion: v1
kind: Pod
metadata:
  name: static-web
  labels:
    role: myrole
 spec:
  containers:
    - name: web
      image: nginx
      ports:
        - name: web
          containerPort: 80
          protocol: TCP
  priorityClassName: high-priority
          

Galite sukurti tiek prioritetinių klasių, kiek norite, nors rekomenduojama tuo nesijaudinti (tarkim, apsiribokite žemu, vidutiniu ir aukštu prioritetu).

Taigi, jei reikia, galite padidinti svarbiausių paslaugų, tokių kaip nginx-ingress-controller, coredns ir kt., diegimo efektyvumą.

9. Optimizuokite ETCD klasterį

Devyni „Kubernetes“ našumo patarimai

ETCD galima vadinti viso klasterio smegenimis. Labai svarbu išlaikyti aukštą šios duomenų bazės veikimą, nes nuo to priklauso operacijų greitis Cube. Gana standartinis ir tuo pat metu geras sprendimas būtų išlaikyti ETCD klasterį pagrindiniuose mazguose, kad būtų kuo mažiau uždelsta kube-apiserver. Jei negalite to padaryti, įdėkite ETCD kiek įmanoma arčiau, kad tarp dalyvių būtų geras pralaidumas. Taip pat atkreipkite dėmesį į tai, kiek mazgų iš ETCD gali iškristi nepakenkiant klasteriui

Devyni „Kubernetes“ našumo patarimai

Turėkite omenyje, kad pernelyg padidinus klasterio narių skaičių, gali padidėti atsparumas gedimams našumo sąskaita, viskas turėtų būti saikingai.

Jei kalbame apie paslaugos nustatymą, yra keletas rekomendacijų:

  1. Turėkite gerą aparatinę įrangą, atsižvelgiant į klasterio dydį (galite perskaityti čia).

  2. Pakoreguokite kelis parametrus, jei paskirstėte klasterį tarp poros DC arba tinklo, o diskai palieka daug norimų rezultatų (galite perskaityti čia).

išvada

Šiame straipsnyje aprašomi punktai, kurių mūsų komanda stengiasi laikytis. Tai ne žingsnis po žingsnio veiksmų aprašymas, o parinktys, kurios gali būti naudingos optimizuojant klasterio išlaidas. Akivaizdu, kad kiekvienas klasteris yra savaip unikalus, o konfigūracijos sprendimai gali labai skirtis, todėl būtų įdomu sulaukti jūsų atsiliepimų apie tai, kaip stebite savo Kubernetes klasterį ir kaip pagerinate jo veikimą. Pasidalinkite savo patirtimi komentaruose, bus įdomu sužinoti.

Šaltinis: www.habr.com