Deväť tipov na výkon Kubernetes

Deväť tipov na výkon Kubernetes

Ahojte všetci! Volám sa Oleg Sidorenkov, pracujem v DomClick ako vedúci tímu infraštruktúry. Kubíka používame vo výrobe už viac ako tri roky a za túto dobu sme s ním zažili veľa rôznych zaujímavých momentov. Dnes vám poviem, ako môžete správnym prístupom vyžmýkať ešte viac výkonu z vanilkového Kubernetes pre váš cluster. Pripraviť sa, pozor, štart!

Všetci veľmi dobre viete, že Kubernetes je škálovateľný open source systém pre orchestráciu kontajnerov; dobre, alebo 5 binárnych súborov, ktoré fungujú magicky tým, že spravujú životný cyklus vašich mikroslužieb v prostredí servera. Okrem toho je to pomerne flexibilný nástroj, ktorý možno zostaviť ako Lego pre maximálne prispôsobenie pre rôzne úlohy.

A všetko sa zdá byť v poriadku: hádžte servery do klastra ako palivové drevo do ohniska a nebudete poznať žiadny smútok. Ale ak ste za životné prostredie, budete si myslieť: "Ako môžem udržať oheň a ušetriť les?" Inými slovami, ako nájsť spôsoby, ako zlepšiť infraštruktúru a znížiť náklady.

1. Monitorujte tímové a aplikačné zdroje

Deväť tipov na výkon Kubernetes

Jednou z najbežnejších, ale účinných metód je zavedenie požiadaviek/limitov. Rozdeľte aplikácie podľa menných priestorov a menných priestorov podľa vývojových tímov. Pred nasadením nastavte aplikačné hodnoty spotreby času procesora, pamäte a dočasného úložiska.

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

Na základe skúseností sme dospeli k záveru: požiadavky z limitov by ste nemali navyšovať viac ako dvakrát. Objem klastra sa vypočítava na základe požiadaviek a ak dáte aplikáciám rozdiel v zdrojoch, napríklad 5-10 krát, predstavte si, čo sa stane s vaším uzlom, keď sa naplní podmi a náhle dostane zaťaženie. Nič dobré. Minimálne, škrtenie a maximum, sa rozlúčite s pracovníkom a budete cyklicky zaťažovať zostávajúce uzly, keď sa moduly začnú pohybovať.

Navyše s pomocou limitranges Na začiatku môžete nastaviť hodnoty zdrojov pre kontajner - minimálne, maximálne a predvolené:

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

Nezabudnite obmedziť zdroje menného priestoru, aby jeden tím nemohol prevziať všetky prostriedky klastra:

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

Ako vidno z popisu resourcequotas, ak chce ops tím nasadiť moduly, ktoré spotrebujú ďalších 10 cpu, plánovač to nedovolí a vyvolá chybu:

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

Na vyriešenie takéhoto problému môžete napísať nástroj, napríklad ako toto, schopný uložiť a odovzdať stav zdrojov velenia.

2. Vyberte optimálne ukladanie súborov

Deväť tipov na výkon Kubernetes

Tu by som sa chcel dotknúť témy trvalých zväzkov a diskového subsystému pracovných uzlov Kubernetes. Dúfam, že “Kocku” na HDD vo výrobe nikto nepoužíva, ale občas už obyčajný SSD nestačí. Narazili sme na problém, keď protokoly zabíjali disk kvôli I/O operáciám, a neexistuje veľa riešení:

  • Použite vysokovýkonné SSD disky alebo prejdite na NVMe (ak spravujete vlastný hardvér).

  • Znížte úroveň protokolovania.

  • Urobte „inteligentné“ vyváženie strukov, ktoré znásilňujú disk (podAntiAffinity).

Vyššie uvedená obrazovka ukazuje, čo sa stane pod nginx-ingress-controller na disku, keď je povolené protokolovanie access_logs (~12 XNUMX protokolov/s). Tento stav môže samozrejme viesť k znehodnoteniu všetkých aplikácií na tomto uzle.

Čo sa týka PV, žiaľ, neskúšal som všetko typy Trvalé objemy. Použite najlepšiu možnosť, ktorá vám vyhovuje. Historicky sa u nás stávalo, že malá časť služieb vyžaduje RWX zväzky a už dávno začali na túto úlohu využívať NFS úložisko. Lacné a... dosť. Samozrejme, on a ja sme jedli hovno - žehnaj, ale naučili sme sa to vyladiť a hlava ma už nebolí. A ak je to možné, presuňte sa na úložisko objektov S3.

3. Zbierajte optimalizované obrázky

Deväť tipov na výkon Kubernetes

Najlepšie je použiť obrázky optimalizované pre kontajnery, aby ich Kubernetes mohol načítať rýchlejšie a vykonávať ich efektívnejšie. 

Optimalizované znamená, že obrázky:

  • obsahovať iba jednu aplikáciu alebo vykonávať iba jednu funkciu;

  • malá veľkosť, pretože veľké obrázky sa cez sieť prenášajú horšie;

  • mať koncové body zdravia a pripravenosti, ktoré umožňujú spoločnosti Kubernetes konať v prípade výpadku;

  • používať operačné systémy vhodné pre kontajnery (ako Alpine alebo CoreOS), ktoré sú odolnejšie voči chybám v konfigurácii;

  • používajte viacstupňové zostavy, aby ste mohli nasadiť iba skompilované aplikácie a nie sprievodné zdroje.

Existuje mnoho nástrojov a služieb, ktoré vám umožňujú kontrolovať a optimalizovať obrázky za chodu. Je dôležité, aby boli vždy aktuálne a testované na bezpečnosť. V dôsledku toho získate:

  1. Znížené zaťaženie siete v celom klastri.

  2. Skrátenie času spustenia kontajnera.

  3. Menšia veľkosť celého registra Docker.

4. Použite vyrovnávaciu pamäť DNS

Deväť tipov na výkon Kubernetes

Ak hovoríme o vysokých zaťaženiach, potom je život dosť mizerný bez vyladenia systému DNS klastra. Kedysi dávno vývojári Kubernetes podporovali svoje riešenie kube-dns. Bol implementovaný aj tu, no tento softvér nebol nijak zvlášť vyladený a neprodukoval požadovaný výkon, hoci sa zdalo, že ide o jednoduchú úlohu. Potom sa objavil Coredns, na ktorý sme prešli a nemali sme smútok; neskôr sa stal predvolenou službou DNS v K8s. V určitom okamihu sme narástli na 40 XNUMX rps systému DNS a toto riešenie sa tiež stalo nedostatočným. Ale našťastie vyšiel Nodelocaldns, alias node local cache, aka NodeLocal DNSCache.

Prečo to používame? V linuxovom jadre je chyba, ktorá pri viacerých volaniach cez conntrack NAT cez UDP vedie k race condition pre záznamy v conntrack tabuľkách a časť prevádzky cez NAT sa stratí (každá cesta cez Službu je NAT). Nodelocaldns rieši tento problém odstránením NAT a aktualizáciou pripojenia na TCP na upstream DNS, ako aj lokálnym ukladaním upstream DNS dotazov (vrátane krátkej 5-sekundovej negatívnej cache).

5. Automaticky upravte vodorovné a zvislé šupky

Deväť tipov na výkon Kubernetes

Môžete s istotou povedať, že všetky vaše mikroslužby sú pripravené na dvoj- až trojnásobné zvýšenie zaťaženia? Ako správne alokovať zdroje vašim aplikáciám? Udržiavanie niekoľkých modulov v prevádzke nad rámec pracovného zaťaženia môže byť nadbytočné, ale ich udržiavanie chrbtom k sebe predstavuje riziko prestojov v dôsledku náhleho zvýšenia návštevnosti služby. Služby ako napr Autoscaler horizontálneho podstavca и Vertikálny stojan Autoscaler.

VPA vám umožňuje automaticky zvyšovať požiadavky/limity vašich kontajnerov v podu v závislosti od skutočného použitia. Ako to môže byť užitočné? Ak máte moduly, ktoré sa z nejakého dôvodu nedajú horizontálne zmenšiť (čo nie je úplne spoľahlivé), môžete skúsiť zveriť zmeny jeho zdrojov spoločnosti VPA. Jeho funkciou je systém odporúčaní založený na historických a aktuálnych údajoch z metrického servera, takže ak nechcete automaticky meniť požiadavky/limity, môžete jednoducho sledovať odporúčané zdroje pre vaše kontajnery a optimalizovať nastavenia, aby ste ušetrili CPU a pamäť v klastri.

Deväť tipov na výkon KubernetesObrázok prevzatý z https://levelup.gitconnected.com/kubernetes-autoscaling-101-cluster-autoscaler-horizontal-pod-autoscaler-and-vertical-pod-2a441d9ad231

Plánovač v Kubernetes je vždy založený na požiadavkách. Nech tam zadáte akúkoľvek hodnotu, plánovač na základe nej vyhľadá vhodný uzol. Hraničné hodnoty sú potrebné na to, aby kocka pochopila, kedy priškrtiť alebo zabiť lusk. A keďže jediným dôležitým parametrom je hodnota requestov, VPA s ňou bude pracovať. Kedykoľvek vertikálne škálujete aplikáciu, definujete, aké by mali byť požiadavky. Čo sa potom stane s limitmi? Tento parameter sa tiež proporcionálne upraví.

Tu sú napríklad obvyklé nastavenia modulu:

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

Nástroj odporúčaní určí, že vaša aplikácia vyžaduje na správne fungovanie 300 m CPU a 500 Mi. Získate nasledujúce nastavenia:

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

Ako je uvedené vyššie, ide o proporcionálne škálovanie založené na pomere požiadaviek/limitov v manifeste:

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

  • Pamäť: 250Mi → 500Mi: pomer 1:2.

Pokiaľ ide o HPA, potom je mechanizmus fungovania transparentnejší. Metriky ako CPU a pamäť sú limitované a ak priemer všetkých replík prekročí prah, aplikácia sa škáluje o +1 sub, kým hodnota neklesne pod prah alebo kým sa nedosiahne maximálny počet replík.

Deväť tipov na výkon KubernetesObrázok prevzatý z https://levelup.gitconnected.com/kubernetes-autoscaling-101-cluster-autoscaler-horizontal-pod-autoscaler-and-vertical-pod-2a441d9ad231

Okrem zvyčajných metrík, ako je CPU a pamäť, môžete nastaviť prahové hodnoty pre svoje vlastné metriky od spoločnosti Prometheus a pracovať s nimi, ak si myslíte, že je to najpresnejší údaj o tom, kedy škálovať vašu aplikáciu. Keď sa aplikácia stabilizuje pod špecifikovaným metrickým prahom, HPA začne zmenšovať moduly na minimálny počet replík alebo kým záťaž nedosiahne špecifikovanú prahovú hodnotu.

6. Nezabudnite na Node Affinity a Pod Affinity

Deväť tipov na výkon Kubernetes

Nie všetky uzly bežia na rovnakom hardvéri a nie všetky moduly musia spúšťať výpočtovo náročné aplikácie. Kubernetes vám umožňuje nastaviť špecializáciu pomocou uzlov a podov Afinita uzla и Pod Affinity.

Ak máte uzly, ktoré sú vhodné na výpočtovo náročné operácie, potom pre maximálnu efektivitu je lepšie prepojiť aplikácie s príslušnými uzlami. Na tento účel použite nodeSelector s označením uzla.

Povedzme, že máte dva uzly: jeden s CPUType=HIGHFREQ a veľké množstvo rýchlych jadier, ďalšie s MemoryType=HIGHMEMORY viac pamäte a rýchlejší výkon. Najjednoduchším spôsobom je priradiť nasadenie k uzlu HIGHFREQpridaním do sekcie spec tento selektor:

…
nodeSelector:
	CPUType: HIGHFREQ

Drahším a špecifickým spôsobom, ako to urobiť, je použiť nodeAffinity v poli affinity razdela spec. Sú dve možnosti:

  • requiredDuringSchedulingIgnoredDuringExecution: tvrdé nastavenie (plánovač rozmiestni moduly iba na konkrétnych uzloch (a nikde inde));

  • preferredDuringSchedulingIgnoredDuringExecution: mäkké nastavenie (plánovač sa pokúsi nasadiť do konkrétnych uzlov, a ak to zlyhá, pokúsi sa nasadiť do ďalšieho dostupného uzla).

Môžete zadať špecifickú syntax pre správu návestí uzlov, ako napr In, NotIn, Exists, DoesNotExist, Gt alebo Lt. Pamätajte však, že zložité metódy v dlhých zoznamoch štítkov spomaľujú rozhodovanie v kritických situáciách. Inými slovami, majte to jednoduché.

Ako je uvedené vyššie, Kubernetes vám umožňuje nastaviť afinitu aktuálnych modulov. To znamená, že sa môžete uistiť, že určité moduly fungujú spolu s inými modulmi v rovnakej zóne dostupnosti (relevantné pre cloudy) alebo uzlami.

В podAffinity poľa affinity razdela spec k dispozícii sú rovnaké polia ako v prípade nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution и preferredDuringSchedulingIgnoredDuringExecution. Jediný rozdiel je v tom matchExpressions pripojí moduly k uzlu, ktorý už spúšťa modul s týmto označením.

Kubernetes ponúka aj pole podAntiAffinity, ktorý naopak neviaže lusk na uzol so špecifickými strúčikmi.

O výrazoch nodeAffinity Dá sa poskytnúť rovnaká rada: snažte sa zachovať jednoduché a logické pravidlá, nesnažte sa preťažiť špecifikáciu modulu zložitým súborom pravidiel. Je veľmi jednoduché vytvoriť pravidlo, ktoré nebude zodpovedať podmienkam klastra, čo zbytočne zaťažuje plánovač a znižuje celkový výkon.

7. Nákazy a tolerancie

Existuje ďalší spôsob, ako spravovať plánovač. Ak máte veľký klaster so stovkami uzlov a tisíckami mikroslužieb, potom je veľmi ťažké nepovoliť hosťovanie určitých modulov na určitých uzloch.

Mechanizmus špinenia – zakazujúce pravidlá – tomu pomáha. Napríklad v určitých scenároch môžete určitým uzlom zakázať spúšťanie modulov. Ak chcete použiť poškvrnu na konkrétny uzol, musíte použiť túto možnosť taint v kubectl. Zadajte kľúč a hodnotu a potom napíšte ako NoSchedule alebo NoExecute:

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

Za zmienku tiež stojí, že mechanizmus pokazenia podporuje tri hlavné efekty: NoSchedule, NoExecute и PreferNoSchedule.

  • NoSchedule znamená, že nateraz nebude v špecifikácii modulu žiadna zodpovedajúca položka tolerations, nebude možné ho nasadiť v uzle (v tomto príklade node10).

  • PreferNoSchedule - zjednodušená verzia NoSchedule. V tomto prípade sa plánovač pokúsi neprideliť moduly, ktoré nemajú zodpovedajúci záznam tolerations na uzol, ale toto nie je tvrdé obmedzenie. Ak v klastri nie sú žiadne prostriedky, moduly sa začnú nasadzovať na tento uzol.

  • NoExecute - tento efekt spúšťa okamžitú evakuáciu strukov, ktoré nemajú zodpovedajúci vstup tolerations.

Je zaujímavé, že toto správanie je možné zrušiť pomocou tolerančného mechanizmu. To je výhodné, keď existuje „zakázaný“ uzol a potrebujete naň umiestniť iba infraštruktúrne služby. Ako to spraviť? Povoľte len tie struky, pre ktoré existuje vhodná tolerancia.

Takto by vyzerala špecifikácia modulu:

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

To neznamená, že ďalšie premiestnenie pripadne na tento konkrétny uzol, nejde o mechanizmus afinity uzla a nodeSelector. Ale kombináciou niekoľkých funkcií môžete dosiahnuť veľmi flexibilné nastavenia plánovača.

8. Nastavte prioritu nasadenia modulov

To, že máte moduly priradené k uzlom, neznamená, že so všetkými modulmi sa musí zaobchádzať s rovnakou prioritou. Môžete napríklad chcieť nasadiť niektoré moduly pred ostatnými.

Kubernetes ponúka rôzne spôsoby konfigurácie priority a preempcie pod. Nastavenie pozostáva z niekoľkých častí: objekt PriorityClass a popisy polí priorityClassName v špecifikácii pod. Pozrime sa na príklad:

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"

tvoríme PriorityClass, uveďte názov, popis a hodnotu. Čím vyššie value, tým vyššia priorita. Hodnota môže byť ľubovoľné 32-bitové celé číslo menšie alebo rovné 1 000 000 000. Vyššie hodnoty sú vyhradené pre kritické systémové moduly, ktoré vo všeobecnosti nie je možné vylúčiť. K premiestneniu dôjde iba vtedy, ak modul s vysokou prioritou nemá miesto, kde by sa mohol otočiť, potom budú niektoré moduly z určitého uzla evakuované. Ak je tento mechanizmus pre vás príliš tuhý, môžete pridať možnosť preemptionPolicy: Never, a potom nedôjde k žiadnej preempcii, modul sa postaví ako prvý vo fronte a počká, kým preň plánovač nájde voľné zdroje.

Ďalej vytvoríme pod, v ktorom uvedieme názov 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
          

Môžete vytvoriť toľko prioritných tried, koľko chcete, aj keď sa odporúča nenechať sa tým uniesť (povedzme, obmedziť sa na nízku, strednú a vysokú prioritu).

V prípade potreby teda môžete zvýšiť efektivitu nasadenia kritických služieb, ako sú nginx-ingress-controller, coredns atď.

9. Optimalizujte klaster ETCD

Deväť tipov na výkon Kubernetes

ETCD možno nazvať mozgom celého klastra. Je veľmi dôležité udržiavať prevádzku tejto databázy na vysokej úrovni, pretože od nej závisí rýchlosť operácií v Cube. Pomerne štandardným a zároveň dobrým riešením by bolo ponechať klaster ETCD na nadradených uzloch, aby mal kube-apiserver minimálne oneskorenie. Ak to nemôžete urobiť, umiestnite ETCD čo najbližšie, s dobrou šírkou pásma medzi účastníkmi. Venujte pozornosť aj tomu, koľko uzlov z ETCD môže vypadnúť bez poškodenia klastra

Deväť tipov na výkon Kubernetes

Majte na pamäti, že nadmerné zvýšenie počtu členov v klastri môže zvýšiť odolnosť voči chybám na úkor výkonu, všetko by malo byť s mierou.

Ak hovoríme o nastavení služby, existuje niekoľko odporúčaní:

  1. Majte dobrý hardvér na základe veľkosti klastra (môžete si prečítať tu).

  2. Vylaďte niekoľko parametrov, ak ste rozložili klaster medzi pár DC alebo vašu sieť a disky ponechajú veľa na želanie (môžete si prečítať tu).

Záver

Tento článok popisuje body, ktoré sa náš tím snaží dodržiavať. Toto nie je podrobný popis akcií, ale možnosti, ktoré môžu byť užitočné na optimalizáciu réžie klastra. Je jasné, že každý klaster je jedinečný svojím vlastným spôsobom a konfiguračné riešenia sa môžu značne líšiť, takže by bolo zaujímavé získať vašu spätnú väzbu o tom, ako monitorujete svoj klaster Kubernetes a ako zlepšujete jeho výkon. Podeľte sa o svoje skúsenosti v komentároch, bude zaujímavé vedieť.

Zdroj: hab.com