Njoggen Kubernetes Performance Tips

Njoggen Kubernetes Performance Tips

Hoi allegearre! Myn namme is Oleg Sidorenkov, ik wurkje by DomClick as haad fan it ynfrastruktuerteam. Wy hawwe Kubik brûkt yn produksje foar mear as trije jier, en yn dizze tiid hawwe wy in protte ferskillende nijsgjirrige mominten meimakke. Hjoed sil ik jo fertelle hoe't jo, mei de juste oanpak, noch mear prestaasjes kinne squeeze út vanille Kubernetes foar jo kluster. Ien-twa-trije!

Jo witte allegear goed dat Kubernetes in skalberber iepen boarnesysteem is foar kontenerorkestraasje; well, of 5 binaries dy't wurkje magy troch it behearen fan de libbenssyklus fan jo microservices yn in tsjinner omjouwing. Derneist is it in frij fleksibel ark dat kin wurde gearstald lykas Lego foar maksimale oanpassing foar ferskate taken.

En alles liket goed te wêzen: smyt tsjinners yn 'e kluster as brânhout yn in brânkast, en jo sille gjin fertriet witte. Mar as jo foar it miljeu binne, sille jo tinke: "Hoe kin ik it fjoer baarnend hâlde en it bosk sparje?" Mei oare wurden, hoe kinne jo manieren fine om ynfrastruktuer te ferbetterjen en kosten te ferminderjen.

1. Monitor team en applikaasje boarnen

Njoggen Kubernetes Performance Tips

Ien fan 'e meast foarkommende, mar effektive metoaden is de ynfiering fan fersiken / grinzen. Diel applikaasjes troch nammeromten, en nammeromten troch ûntwikkelingsteams. Stel foar ynset de applikaasjewearden yn foar it konsumpsje fan prosessortiid, ûnthâld en efemere opslach.

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

Troch ûnderfining kamen wy ta de konklúzje: jo moatte fersiken fan 'e grinzen net mear as twa kear opblaze. It folume fan it kluster wurdt berekkene op basis fan fersiken, en as jo applikaasjes in ferskil yn middels jouwe, bygelyks 5-10 kear, stel dan foar wat der mei jo knooppunt sil barre as it fol is mei pods en ynienen lading krijt. Neat goed. Op in minimum, throttling, en op in maksimum, sille jo ôfskied nimme fan 'e arbeider en krije in syklyske lading op' e oerbleaune knopen nei't de pods begjinne te bewegen.

Boppedat, mei help limitranges Oan it begjin kinne jo boarnewearden ynstelle foar de kontener - minimum, maksimum en standert:

➜  ~ 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

Ferjit net om nammeromteboarnen te beheinen sadat ien team net alle boarnen fan it kluster oernimme kin:

➜  ~ 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

As kin sjoen wurde út de beskriuwing resourcequotas, as it ops-team pods ynsette wol dy't noch 10 cpu sille konsumearje, sil de planner dit net tastean en sil in flater smyt:

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

Om sa'n probleem op te lossen, kinne jo in ark skriuwe, bygelyks, lykas dit, by steat om te bewarjen en commit de steat fan kommando middels.

2. Kies de optimale triem opslach

Njoggen Kubernetes Performance Tips

Hjir wol ik it ûnderwerp fan oanhâldende folumes en it skiifsubsysteem fan Kubernetes-wurkknooppunten oanreitsje. Ik hoopje dat gjinien de "Cube" op in HDD yn produksje brûkt, mar soms is in gewoane SSD net mear genôch. Wy tsjinkaam in probleem wêr't de logs de skiif fermoarde fanwegen I / O-operaasjes, en d'r binne net in protte oplossingen:

  • Brûk SSD's mei hege prestaasjes of wikselje nei NVMe (as jo jo eigen hardware beheare).

  • Ferminderje logging nivo.

  • Doch "tûke" balâns fan pods dy't de skiif ferkrêfte (podAntiAffinity).

It boppesteande skerm lit sjen wat der bart ûnder nginx-ingress-controller mei de skiif as tagongslogs-logging ynskeakele is (~ 12 tûzen logs / sek). Dizze betingst kin fansels liede ta de degradaasje fan alle applikaasjes op dit knooppunt.

Wat PV oanbelanget, och, ik haw net alles besocht soarten fan Persistente Volumes. Brûk de bêste opsje dy't by jo past. Histoarysk is it bard yn ús lân dat in lyts part fan tsjinsten fereaskje RWX folume, en in lange tiid lyn se begûn te brûken NFS opslach foar dizze taak. Goedkeap en... genôch. Fansels ieten hy en ik stront - seingje dy, mar wy learden it út te stimmen, en myn holle docht gjin sear mear. En as it mooglik is, ferpleatse nei S3-objekt opslach.

3. Sammelje optimalisearre ôfbyldings

Njoggen Kubernetes Performance Tips

It is it bêste om kontener-optimalisearre ôfbyldings te brûken, sadat Kubernetes se rapper kin ophelje en effisjinter útfiere. 

Optimalisearre betsjut dat de ôfbyldings:

  • befetsje mar ien applikaasje of útfiere mar ien funksje;

  • lyts yn grutte, om't grutte ôfbyldings slimmer oer it netwurk oerbrocht wurde;

  • hawwe einpunten foar sûnens en ree dy't Kubernetes tastean om aksje te nimmen yn gefal fan downtime;

  • brûke kontenerfreonlike bestjoeringssystemen (lykas Alpine of CoreOS), dy't mear resistint binne foar konfiguraasjeflaters;

  • brûk multi-stage builds sadat jo allinich kompilearre applikaasjes kinne ynsette en net de byhearrende boarnen.

D'r binne in protte ark en tsjinsten wêrmei jo ôfbyldings op 'e flecht kinne kontrolearje en optimalisearje. It is wichtich om se altyd by de tiid te hâlden en te testen foar feiligens. As resultaat krije jo:

  1. Fermindere netwurkbelêsting op it heule kluster.

  2. It ferminderjen fan opstarttiid fan kontener.

  3. Lytsere grutte fan jo hiele Docker-register.

4. Brûk DNS-cache

Njoggen Kubernetes Performance Tips

As wy prate oer hege loads, dan is it libben aardich swak sûnder it DNS-systeem fan it kluster ôfstimme. Eartiids stipe de Kubernetes-ûntwikkelders har kube-dns-oplossing. It waard hjir ek ymplementearre, mar dizze software wie net spesjaal ôfstimd en produsearre net de fereaske prestaasjes, hoewol it in ienfâldige taak like te wêzen. Doe ferskynden coredns, wêrfan wy oerstapten en gjin fertriet hienen; it waard letter de standert DNS-tsjinst yn K8s. Op in stuit groeiden wy nei 40 tûzen rps nei it DNS-systeem, en dizze oplossing waard ek net genôch. Mar, troch gelok, kaam Nodelocaldns út, aka node local cache, aka NodeLocal DNSCache.

Wêrom brûke wy dit? D'r is in brek yn 'e Linux-kernel dy't, as meardere oproppen fia conntrack NAT oer UDP, liede ta in racebetingst foar yngongen yn conntrack-tabellen, en in diel fan it ferkear troch NAT is ferlern (elke reis troch de tsjinst is NAT). Nodelocaldns lost dit probleem op troch NAT kwyt te reitsjen en de ferbining mei TCP te ferbetterjen nei streamop DNS, en ek lokaal caching upstream DNS-fragen (ynklusyf in koarte 5-sekonde negative cache).

5. Skaal pods horizontaal en fertikaal automatysk

Njoggen Kubernetes Performance Tips

Kinne jo mei fertrouwen sizze dat al jo mikrotsjinsten klear binne foar in twa oant trije kear ferheging fan lading? Hoe kinne jo boarnen goed tawize oan jo applikaasjes? It hâlden fan in pear pods dy't bûten de wurkdruk rinne kin oerstallich wêze, mar it hâlden fan se efterinoar rint it risiko fan downtime fan in hommelse tanimming fan ferkear nei de tsjinst. Tsjinsten lykas Horizontale Pod Autoscaler и Fertikale Pod Autoscaler.

VPA kinne jo automatysk fersiken / limiten fan jo konteners yn 'e pod ferheegje ôfhinklik fan werklik gebrûk. Hoe kin it nuttich wêze? As jo ​​​​pods hawwe dy't om ien of oare reden net horizontaal kinne wurde skaleare (wat net folslein betrouber is), dan kinne jo besykje wizigingen oan har boarnen oan VPA te fertrouwen. De funksje dêrfan is in oanbefellingssysteem basearre op histoaryske en aktuele gegevens fan 'e metryske tsjinner, dus as jo fersiken/grinzen net automatysk wizigje wolle, kinne jo gewoan de oanrikkemandearre boarnen foar jo konteners kontrolearje en de ynstellingen optimalisearje om CPU en te bewarjen ûnthâld yn it kluster.

Njoggen Kubernetes Performance TipsOfbylding nommen fan https://levelup.gitconnected.com/kubernetes-autoscaling-101-cluster-autoscaler-horizontal-pod-autoscaler-and-vertical-pod-2a441d9ad231

De planner yn Kubernetes is altyd basearre op oanfragen. Hokker wearde jo dêr ek pleatse, sil de planner sykje nei in geskikt knooppunt basearre op it. De grinzenwearden binne nedich foar de cubelet om te begripen wannear't de pod throttle of deadzje moat. En om't de ienige wichtige parameter de oanfraachwearde is, sil VPA dermei wurkje. Elke kear as jo in applikaasje fertikaal skaalje, definiearje jo wat de oanfragen moatte wêze. Wat bart der dan mei de grinzen? Dizze parameter sil ek proporsjoneel skaal wurde.

Hjir binne bygelyks de gewoane pod-ynstellingen:

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

De oanbefellingsmotor bepaalt dat jo applikaasje 300m CPU en 500Mi fereasket om goed te rinnen. Jo sille de folgjende ynstellings krije:

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

Lykas hjirboppe neamde, is dit proporsjonele skaalfergrutting basearre op de ferhâlding oanfragen/grinzen yn it manifest:

  • CPU: 200m → 300m: ferhâlding 1:1.75;

  • Unthâld: 250Mi → 500Mi: ferhâlding 1:2.

Wetter - Agrarwetter hPa, dan is it meganisme fan wurking transparanter. Metriken lykas CPU en ûnthâld binne drompelich, en as it gemiddelde fan alle replika's de drompel grutter is, wurdt de applikaasje skalearre mei +1 sub oant de wearde ûnder de drompel falt of oant it maksimum oantal replika's wurdt berikt.

Njoggen Kubernetes Performance TipsOfbylding nommen fan https://levelup.gitconnected.com/kubernetes-autoscaling-101-cluster-autoscaler-horizontal-pod-autoscaler-and-vertical-pod-2a441d9ad231

Njonken de gewoane metriken lykas CPU en ûnthâld, kinne jo drompels ynstelle op jo oanpaste metriken fan Prometheus en mei har wurkje as jo tinke dat dit de meast krekte yndikaasje is fan wannear't jo jo applikaasje skaalje moatte. Sadree't de applikaasje stabilisearret ûnder de opjûne metryske drompel, sil HPA begjinne mei it skaaljen fan pods nei it minimale oantal replika's of oant de lading de opjûne drompel foldocht.

6. Ferjit net oer Node Affinity en Pod Affinity

Njoggen Kubernetes Performance Tips

Net alle knooppunten rinne op deselde hardware, en net alle pods moatte kompute-yntinsive applikaasjes útfiere. Kubernetes kinne jo ynstelle de spesjalisaasje fan knopen en pods mei help Node Affiniteit и Pod Affiniteit.

As jo ​​knooppunten hawwe dy't geskikt binne foar komputer-yntinsive operaasjes, dan foar maksimale effisjinsje is it better om applikaasjes te ferbinen oan 'e oerienkommende knooppunten. Om dit te brûken nodeSelector mei in knooppunt label.

Litte we sizze dat jo twa knopen hawwe: ien mei CPUType=HIGHFREQ en in grut oantal flugge kearnen, in oar mei MemoryType=HIGHMEMORY mear ûnthâld en flugger prestaasjes. De maklikste manier is om ynset te jaan oan in knooppunt HIGHFREQtroch tafoegjen oan de seksje spec dizze selector:

…
nodeSelector:
	CPUType: HIGHFREQ

In djoerdere en spesifike manier om dit te dwaan is te brûken nodeAffinity yn fjild affinity ôfdieling spec. Der binne twa opsjes:

  • requiredDuringSchedulingIgnoredDuringExecution: hurde ynstelling (de planner sil pods allinich ynsette op spesifike knopen (en nearne oars));

  • preferredDuringSchedulingIgnoredDuringExecution: sêfte ynstelling (de planner sil besykje te ynsetten nei spesifike knopen, en as dat mislearret, sil it besykje te ynsetten nei de folgjende beskikbere node).

Jo kinne in spesifike syntaksis opjaan foar it behearen fan node-labels, lykas In, NotIn, Exists, DoesNotExist, Gt of Lt. Unthâld lykwols dat komplekse metoaden yn lange listen mei etiketten beslútfoarming yn krityske situaasjes sille fertrage. Mei oare wurden, hâld it ienfâldich.

Lykas hjirboppe neamd, lit Kubernetes jo de affiniteit fan 'e hjoeddeistige pods ynstelle. Dat is, jo kinne derfoar soargje dat bepaalde pods gearwurkje mei oare pods yn deselde beskikberensône (relevant foar wolken) of knopen.

В podAffinity fjilden affinity ôfdieling spec deselde fjilden binne beskikber as yn it gefal fan nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution и preferredDuringSchedulingIgnoredDuringExecution. It ienige ferskil is dat matchExpressions sil de pods bine oan in knooppunt dat al in pod mei dat label draait.

Kubernetes biedt ek in fjild podAntiAffinity, dy't, krekt oarsom, de pod net bynt oan in knooppunt mei spesifike pods.

Oer útdrukkingen nodeAffinity Itselde advys kin jûn wurde: besykje de regels ienfâldich en logysk te hâlden, besykje de podspesifikaasje net te oerladen mei in komplekse set regels. It is heul maklik om in regel te meitsjen dy't net oerienkomt mei de betingsten fan it kluster, it meitsjen fan ûnnedige lêst op 'e planner en it ferminderjen fan totale prestaasjes.

7. Taints & tolerânsjes

D'r is in oare manier om de planner te behearjen. As jo ​​​​in grut kluster hawwe mei hûnderten knopen en tûzenen mikrotsjinsten, dan is it heul lestich om bepaalde pods net op bepaalde knopen te hostjen.

It meganisme fan tinzen - regels ferbiede - helpt hjirmei. Bygelyks, yn bepaalde senario's kinne jo bepaalde knooppunten ferbiede om pods te rinnen. Om taint oan te passen op in spesifyk knooppunt moatte jo de opsje brûke taint yn kub. Spesifisearje de kaai en wearde en dan taint like NoSchedule of NoExecute:

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

It is ek de muoite wurdich op te merken dat it smoargensmeganisme trije haadeffekten stipet: NoSchedule, NoExecute и PreferNoSchedule.

  • NoSchedule betsjut dat d'r foar no gjin oerienkommende yngong sil wêze yn 'e podspesifikaasje tolerations, sil it net kinne wurde ynset op it knooppunt (yn dit foarbyld node10).

  • PreferNoSchedule - ferienfâldige ferzje NoSchedule. Yn dit gefal sil de planner besykje gjin pods te allocearjen dy't gjin oerienkommende yngong hawwe tolerations per knooppunt, mar dit is net in hurde beheining. As d'r gjin boarnen binne yn it kluster, dan sille pods begjinne te ynsetten op dit knooppunt.

  • NoExecute - dit effekt triggert de direkte evakuaasje fan pods dy't gjin oerienkommende yngong hawwe tolerations.

Opfallend is dat dit gedrach kin wurde annulearre mei it toleraasjemeganisme. Dit is handich as d'r in "ferbean" knooppunt is en jo der allinich ynfrastruktuertsjinsten op moatte pleatse. Hoe it te dwaan? Tastean allinnich dy pods dêr't der in geskikte tolerânsje.

Hjir is hoe't de pod-spesifikaasje der útsjen soe:

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

Dit betsjut net dat de folgjende weryndieling op dit bepaalde knooppunt sil falle, dit is net it meganisme foar knooppuntaffiniteit en nodeSelector. Mar troch ferskate funksjes te kombinearjen, kinne jo heul fleksibele plannerynstellingen berikke.

8. Set Pod Deployment Prioriteit

Krekt om't jo pods hawwe tawiisd oan knopen, betsjut net dat alle pods moatte wurde behannele mei deselde prioriteit. Jo kinne bygelyks guon pods foar oaren ynsette.

Kubernetes biedt ferskate manieren om Pod Priority en Preemption te konfigurearjen. De ynstelling bestiet út ferskate dielen: foarwerp PriorityClass en fjild beskriuwings priorityClassName yn de pod spesifikaasje. Litte wy nei in foarbyld sjen:

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"

Wy meitsje PriorityClass, jou it in namme, beskriuwing en wearde. De hegere value, wat heger de prioriteit. De wearde kin elk 32-bit hiel getal wêze minder as of gelyk oan 1. Hegere wearden binne reservearre foar missy-krityske systeempods dy't yn 't algemien net kinne wurde foarkommen. Ferpleatsing sil allinich foarkomme as in pod mei hege prioriteit gjin plak hat om om te draaien, dan wurde guon fan 'e pods fan in bepaalde knoop evakuearre. As dit meganisme te stiif is foar jo, kinne jo de opsje tafoegje preemptionPolicy: Never, en dan sil d'r gjin preemption wêze, de pod sil earst yn 'e wachtrige stean en wachtsje op' e planner om fergees boarnen foar te finen.

Dêrnei meitsje wy in pod wêryn wy de namme oanjaan 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
          

Jo kinne safolle prioriteitsklassen oanmeitsje as jo wolle, hoewol it wurdt oanrikkemandearre om dit net mei te nimmen (sizze, beheine josels ta lege, medium en hege prioriteit).

Sa kinne jo, as it nedich is, de effisjinsje ferheegje fan it ynsetten fan krityske tsjinsten lykas nginx-ingress-controller, coredns, ensfh.

9. Optimalisearje it ETCD-kluster

Njoggen Kubernetes Performance Tips

ETCD kin neamd wurde it harsens fan it hiele kluster. It is heul wichtich om de wurking fan dizze databank op in heech nivo te behâlden, om't de snelheid fan operaasjes yn Cube derfan hinget. In frij standert, en tagelyk, goede oplossing soe wêze om it ETCD-kluster op 'e masterknooppunten te hâlden om in minimale fertraging nei de kube-apiserver te hawwen. As jo ​​dit net kinne, pleats dan de ETCD sa ticht mooglik, mei in goede bânbreedte tusken dielnimmers. Jou ek omtinken oan hoefolle knopen fan ETCD kinne falle út sûnder skea oan it kluster

Njoggen Kubernetes Performance Tips

Hâld der rekken mei dat it oermjittich fergrutsjen fan it oantal leden yn in kluster kin tanimme skuld tolerânsje ten koste fan prestaasjes, alles moat wêze yn moderaasje.

As wy prate oer it ynstellen fan de tsjinst, binne d'r in pear oanbefellings:

  1. Hawwe goede hardware, basearre op de grutte fan it kluster (jo kinne lêze hjir).

  2. Tweak in pear parameters as jo in kluster hawwe ferspraat tusken in pear DC's as jo netwurk en skiven litte in protte te winskjen oer (jo kinne lêze hjir).

konklúzje

Dit artikel beskriuwt de punten dy't ús team besiket te foldwaan. Dit is gjin stap-foar-stap beskriuwing fan aksjes, mar opsjes dy't nuttich kinne wêze foar it optimalisearjen fan klusteroverhead. It is dúdlik dat elk kluster unyk is op syn eigen manier, en konfiguraasjeoplossingen kinne sterk ferskille, dus it soe ynteressant wêze om jo feedback te krijen oer hoe't jo jo Kubernetes-kluster kontrolearje en hoe't jo de prestaasjes ferbetterje. Diel jo ûnderfining yn 'e kommentaren, it sil ynteressant wêze om te witten.

Boarne: www.habr.com