Devet nasvetov za uspešnost Kubernetes

Devet nasvetov za uspešnost Kubernetes

Pozdravljeni vsi skupaj! Moje ime je Oleg Sidorenkov, delam v DomClicku kot vodja infrastrukturne skupine. Cube prodam uporabljamo že več kot tri leta in v tem času smo z njim doživeli veliko različnih zanimivih trenutkov. Danes vam bom povedal, kako lahko s pravim pristopom iz vanilije Kubernetes iztisnete še več zmogljivosti za vaš grozd. Pripravljeni Pozor zdaj!

Vsi dobro veste, da je Kubernetes razširljiv odprtokodni sistem za orkestracijo vsebnikov; ali pa 5 binarnih datotek, ki delajo čarovnije z upravljanjem življenjskega cikla vaših mikrostoritev v strežniškem okolju. Poleg tega je to dokaj prilagodljivo orodje, ki ga je mogoče sestaviti kot Lego konstruktor za maksimalno prilagajanje različnim nalogam.

In zdi se, da je vse v redu: vrzite strežnike v gručo, kot drva v kurišče, in ne poznajte žalosti. Če pa ste za okolje, potem boste pomislili: "Kako naj vzdržujem ogenj v peči in obžalujem gozd?". Z drugimi besedami, kako najti načine za izboljšanje infrastrukture in zmanjšanje stroškov.

1. Spremljajte ekipe in vire aplikacij

Devet nasvetov za uspešnost Kubernetes

Ena najbolj banalnih, a učinkovitih metod je uvedba zahtev/omejitev. Ločite aplikacije po imenskih prostorih in imenske prostore po razvojnih skupinah. Pred uvedbo aplikacije nastavite vrednosti za porabo procesorskega časa, pomnilnika, efemernega pomnilnika.

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

Po izkušnjah smo prišli do zaključka: ni vredno napihniti zahtev iz omejitev za več kot dvakrat. Velikost gruče se izračuna na podlagi zahtev in če aplikacijo nastavite na razliko v virih, na primer za 5-10-krat, si predstavljajte, kaj se bo zgodilo z vašim vozliščem, ko bo napolnjeno s podi in nenadoma prejme obremenitev. Nič dobrega. Najmanj, dušenje, in kot največ, poslovite se od delavca in dobite ciklično obremenitev preostalih vozlišč, potem ko se sklopi začnejo premikati.

Poleg tega s pomočjo limitranges na začetku lahko nastavite vrednosti virov za vsebnik - najmanj, največ in privzeto:

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

Ne pozabite omejiti virov imenskega prostora, tako da en ukaz ne more prevzeti vseh virov gruče:

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

Kot je razvidno iz opisa resourcequotas, če želi ukaz ops razmestiti pode, ki bodo porabili dodatnih 10 procesorjev, potem razporejevalnik tega ne bo dovolil in bo izdal napako:

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

Za rešitev podobnega problema lahko napišete orodje, na primer kot ta, ki lahko shrani in potrdi stanje ukaznih virov.

2. Izberite najboljšo shrambo datotek

Devet nasvetov za uspešnost Kubernetes

Tukaj bi se rad dotaknil teme trajnih nosilcev in diskovnega podsistema delovnih vozlišč Kubernetes. Upam, da nihče ne uporablja "Cube" na HDD v proizvodnji, vendar včasih tudi navaden SSD že ni dovolj. Soočili smo se s tako težavo, da so dnevniki ubijali disk z V/I operacijami in tukaj ni prav veliko rešitev:

  • Uporabite visoko zmogljive diske SSD ali preklopite na NVMe (če upravljate svojo strojno opremo).

  • Zmanjšajte stopnjo beleženja.

  • Naredite "pametno" uravnoteženje strokov, ki posilijo disk (podAntiAffinity).

Zgornji posnetek zaslona prikazuje, kaj se zgodi pod nginx-ingress-controller z diskom, ko je omogočen access_logs (~12k dnevnikov/s). Tako stanje seveda lahko privede do degradacije vseh aplikacij na tem vozlišču.

Glede PV pa žal, vsega še nisem preizkusil. vrste Trajne količine. Uporabite najboljšo možnost, ki vam ustreza. Pri nas se je v zgodovini že zgodilo, da majhen del storitev potrebuje RWX nosilce, že dolgo nazaj pa so za to nalogo začeli uporabljati NFS shrambo. Poceni in ... dovolj. Seveda smo jedli sranje z njim - bodite zdravi, vendar smo se naučili, kako ga uglasiti, in glava ga ne boli več. In če je mogoče, preklopite na shranjevanje objektov S3.

3. Zgradite optimizirane slike

Devet nasvetov za uspešnost Kubernetes

Najbolje je, da uporabite slike, optimizirane za vsebnik, da jih lahko Kubernetes hitreje pridobi in izvede učinkoviteje. 

Optimizacija pomeni, da slike:

  • vsebujejo samo eno aplikacijo ali opravljajo samo eno funkcijo;

  • majhna velikost, ker se velike slike slabše prenašajo po omrežju;

  • imajo končne točke zdravja in pripravljenosti, ki jih Kubernetes lahko uporabi za ukrepanje v primeru izpadov;

  • uporabljajte vsebniku prijazne operacijske sisteme (kot sta Alpine ali CoreOS), ki so bolj odporni na konfiguracijske napake;

  • uporabite večstopenjske gradnje, tako da lahko namestite samo prevedene aplikacije in ne spremljajočih virov.

Obstaja veliko orodij in storitev, ki vam omogočajo sprotno preverjanje in optimizacijo slik. Pomembno je, da so vedno posodobljeni in varni. Kot rezultat dobite:

  1. Zmanjšana obremenitev omrežja na celotnem grozdu.

  2. Zmanjšan čas zagona vsebnika.

  3. Manjša velikost vašega celotnega registra Docker.

4. Uporabite predpomnilnik DNS

Devet nasvetov za uspešnost Kubernetes

Če govorimo o visokih obremenitvah, potem je življenje brez nastavitve DNS sistema grozda precej zanič. Nekoč so razvijalci Kubernetes podpirali svojo rešitev kube-dns. Izvedena je bila tudi v naši državi, vendar se ta programska oprema ni posebej prilagodila in ni dala zahtevane zmogljivosti, čeprav se zdi, da je naloga preprosta. Potem se je pojavil coredns, na katerega smo prešli in nismo poznali žalosti, kasneje je postal privzeta storitev DNS v K8s. V nekem trenutku smo zrasli do 40 tisoč rps na sistem DNS in tudi ta rešitev ni bila dovolj. Toda po srečnem naključju se je pojavil Nodelocaldns, alias lokalni predpomnilnik vozlišč, alias NodeLocal DNSCache.

Zakaj ga uporabljamo? V jedru Linuxa je napaka, ki pri večkratnem dostopu prek conntrack NAT preko UDP povzroči stanje tekmovanja za pisanje v tabele conntrack in del prometa prek NAT se izgubi (vsako potovanje prek storitve je NAT). Nodelocaldns rešuje to težavo tako, da se znebi NAT in nadgradi na povezljivost TCP na vzhodni DNS ter lokalno predpomni poizvedbe DNS navzgor (vključno s kratkim 5-sekundnim negativnim predpomnilnikom).

5. Samodejno skalirajte stroke vodoravno in navpično

Devet nasvetov za uspešnost Kubernetes

Ali lahko z gotovostjo trdite, da so vse vaše mikrostoritve pripravljene na dvakratno do trikratno povečanje obremenitve? Kako pravilno dodeliti vire svojim aplikacijam? Ohranjanje delovanja nekaj enot, ki presegajo delovno obremenitev, je lahko odveč, če jih držite drug za drugim, pa tvegate izpade zaradi nenadnega povečanja prometa do storitve. Zlata sredina pomaga doseči urok množenja, kot so storitve Horizontalni pod Autoscaler и Vertical Pod Autoscaler.

VPA omogoča samodejno zvišanje zahtev/omejitev vaših vsebnikov v podu na podlagi dejanske uporabe. Kako je lahko koristno? Če imate Pods, ki jih iz nekega razloga ni mogoče povečati vodoravno (kar ni povsem zanesljivo), potem lahko poskusite zaupati VPA, da spremeni svoje vire. Njegova značilnost je sistem priporočil, ki temelji na preteklih in trenutnih podatkih iz metričnega strežnika, tako da če ne želite samodejno spreminjati zahtev/omejitev, lahko preprosto spremljate priporočene vire za vsebnike in optimizirate nastavitve, da prihranite CPE in pomnilnik v gruči.

Devet nasvetov za uspešnost KubernetesSlika povzeta iz https://levelup.gitconnected.com/kubernetes-autoscaling-101-cluster-autoscaler-horizontal-pod-autoscaler-and-vertical-pod-2a441d9ad231

Razporejevalnik v Kubernetesu vedno temelji na zahtevah. Ne glede na vrednost, ki jo vnesete, bo planer na podlagi nje poiskal ustrezno vozlišče. Mejno vrednost potrebuje kublet, da ve, kdaj mora dušiti ali ubiti strok. In ker je edini pomemben parameter vrednost zahteve, bo VPA deloval z njo. Kadarkoli svojo aplikacijo prilagodite navpično, določite, kakšne naj bodo zahteve. In kaj bo potem z limiti? Tudi ta parameter bo sorazmerno prilagojen.

Tukaj so na primer tipične nastavitve sklopa:

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

Mehanizem za priporočila ugotovi, da vaša aplikacija za pravilno delovanje potrebuje 300 m CPE in 500Mi. Dobili boste te nastavitve:

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

Kot je navedeno zgoraj, je to sorazmerno skaliranje na podlagi razmerja med zahtevami in omejitvami v manifestu:

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

  • Pomnilnik: 250Mi → 500Mi: razmerje 1:2.

glede HPA, potem je mehanizem delovanja bolj pregleden. Mejne vrednosti so nastavljene za meritve, kot sta procesor in pomnilnik, in če povprečje vseh replik preseže prag, se aplikacija skalira za +1 pod, dokler vrednost ne pade pod prag ali dokler ni doseženo največje število replik.

Devet nasvetov za uspešnost KubernetesSlika povzeta iz https://levelup.gitconnected.com/kubernetes-autoscaling-101-cluster-autoscaler-horizontal-pod-autoscaler-and-vertical-pod-2a441d9ad231

Poleg običajnih metrik, kot sta CPU in pomnilnik, lahko nastavite pragove za meritve Prometheus po meri in delate z njimi, če menite, da je to najnatančnejši način za določanje, kdaj prilagoditi svojo aplikacijo. Ko se aplikacija stabilizira pod določenim pragom meritev, bo HPA začel zniževati sklope na najmanjše število replik ali dokler obremenitev ne doseže podanega praga.

6. Ne pozabite na afiniteto vozlišča in afiniteto pod

Devet nasvetov za uspešnost Kubernetes

Vsa vozlišča ne delujejo na isti strojni opremi in ni treba, da vsi podi izvajajo računalniško intenzivne aplikacije. Kubernetes vam omogoča, da določite specializacijo vozlišč in podov z uporabo Afiniteta vozlišča и Pod Affinity.

Če imate vozlišča, ki so primerna za računalniško intenzivne operacije, je za največjo učinkovitost bolje, da aplikacije povežete z ustreznimi vozlišči. Če želite to narediti, uporabite nodeSelector z oznako vozlišča.

Recimo, da imate dve vozlišči: eno z CPUType=HIGHFREQ ter velikim številom hitrih jeder, drugo z MemoryType=HIGHMEMORY več pomnilnika in hitrejše delovanje. Najlažji način je, da vozlišču dodelite razmestitev poda HIGHFREQz dodajanjem v razdelek spec tak selektor:

…
nodeSelector:
	CPUType: HIGHFREQ

Dražji in specifični način za to je uporaba nodeAffinity na terenu affinity razdelek spec. Obstajata dve možnosti:

  • requiredDuringSchedulingIgnoredDuringExecution: trda nastavitev (razporejevalnik bo namestil pode samo na določenih vozliščih (in nikjer drugje));

  • preferredDuringSchedulingIgnoredDuringExecution: mehka nastavitev (razporejevalnik se bo poskušal razmestiti v določena vozlišča in če ne uspe, se bo poskusil razmestiti v naslednje razpoložljivo vozlišče).

Določite lahko posebno sintakso za upravljanje oznak vozlišč, na primer In, NotIn, Exists, DoesNotExist, Gt ali Lt. Vendar ne pozabite, da bodo kompleksne metode na dolgih seznamih oznak upočasnile sprejemanje odločitev v kritičnih situacijah. Z drugimi besedami, ne komplicirajte preveč.

Kot že omenjeno, vam Kubernetes omogoča nastavitev vezave trenutnih sklopov. To pomeni, da lahko določene pode delujejo skupaj z drugimi podi v istem območju razpoložljivosti (pomembno za oblake) ali vozliščih.

В podAffinity marže affinity razdelek spec na voljo so enaka polja kot v primeru nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution и preferredDuringSchedulingIgnoredDuringExecution. Edina razlika je v tem matchExpressions bo pode povezal z vozliščem, ki že izvaja pod s to oznako.

Več Kubernetes ponuja polje podAntiAffinity, ki v nasprotju s tem ne veže poda na vozlišče z določenimi podi.

O izrazih nodeAffinity Lahko damo enak nasvet: poskusite ohraniti pravila preprosta in logična, ne poskušajte preobremeniti specifikacije sklopa s kompleksnim nizom pravil. Zelo enostavno je ustvariti pravilo, ki se ne ujema s pogoji gruče, kar dodatno obremeni razporejevalnik in zmanjša splošno zmogljivost.

7. Umazanosti in tolerance

Obstaja še en način za upravljanje razporejevalnika. Če imate veliko gručo s stotinami vozlišč in tisoči mikrostoritev, je zelo težko preprečiti, da bi določena vozlišča gostila določene sklope.

Pri tem pomaga mehanizem taintov – prepovedujočih pravil. Določenim vozliščem lahko na primer preprečite izvajanje podov v določenih scenarijih. Če želite nanesti madež na določeno vozlišče, uporabite možnost taint v kubectl. Določite ključ in vrednost ter nato pokvarite podobno NoSchedule ali NoExecute:

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

Prav tako je treba omeniti, da mehanizem madeža podpira tri glavne učinke: NoSchedule, NoExecute и PreferNoSchedule.

  • NoSchedule pomeni, da dokler v specifikaciji sklopa ni ustreznega vnosa tolerations, ga ni mogoče namestiti v vozlišče (v tem primeru node10).

  • PreferNoSchedule - poenostavljena različica NoSchedule. V tem primeru bo razporejevalnik poskušal ne dodeliti podov, ki nimajo ujemajočega se vnosa. tolerations na vozlišče, vendar to ni stroga omejitev. Če v gruči ni virov, se bodo podi začeli nameščati na tem vozlišču.

  • NoExecute - ta učinek sproži takojšnjo evakuacijo strokov, ki nimajo ustreznega vnosa tolerations.

Zanimivo je, da je to vedenje mogoče razveljaviti z mehanizmom toleranc. To je priročno, ko obstaja "prepovedano" vozlišče in morate nanj postaviti samo infrastrukturne storitve. Kako narediti? Dovolite samo tiste stroke, za katere obstaja ustrezna toleranca.

Tako bi izgledala specifikacija sklopa:

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

To ne pomeni, da bo med naslednjo prerazporeditvijo pod zadel točno to vozlišče, to ni mehanizem afinitete vozlišča in nodeSelector. Toda s kombiniranjem več funkcij lahko dosežete zelo prilagodljivo nastavitev razporejevalnika.

8. Nastavite prioriteto razmestitve pod

Samo zato, ker ste konfigurirali vezave sklopa na vozlišče, ne pomeni, da je treba vse sklope obravnavati z enako prioriteto. Na primer, morda boste želeli nekatere Pode namestiti pred drugimi.

Kubernetes ponuja različne načine za nastavitev prioritete Pod Priority in Preemption. Postavitev je sestavljena iz več delov: objekt PriorityClass in opise polj priorityClassName v specifikaciji stroka. Razmislite o primeru:

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"

Ustvarjamo PriorityClass, mu dajte ime, opis in vrednost. Višji valuevišja je prioriteta. Vrednost je lahko katero koli 32-bitno celo število, ki je manjše ali enako 1 000 000 000. Višje vrednosti so rezervirane za kritične sistemske sklope, ki jih običajno ni mogoče prevzeti. Do izločitve bo prišlo samo, če se skupina z visoko prioriteto nima kam obrniti, potem bodo nekatere enote iz določenega vozlišča evakuirane. Če je ta mehanizem preveč tog za vas, potem lahko dodate možnost preemptionPolicy: Never, in potem ne bo nobene prednosti, pod bo prvi v čakalni vrsti in bo čakal, da razporejevalnik najde prosta sredstva zanj.

Nato ustvarimo pod, v katerem določimo ime 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
          

Ustvarite lahko poljubno število prednostnih razredov, čeprav je priporočljivo, da se s tem ne zanesete (recimo, omejite se na nizko, srednjo in visoko prioriteto).

Tako lahko po potrebi povečate učinkovitost uvajanja kritičnih storitev, kot so nginx-ingress-controller, coredns itd.

9. Optimizirajte svojo gručo ETCD

Devet nasvetov za uspešnost Kubernetes

ETCD lahko imenujemo možgani celotnega grozda. Zelo pomembno je vzdrževati delovanje te podatkovne baze na visoki ravni, saj je od tega odvisna hitrost delovanja v "Cube". Precej standardna in hkrati dobra rešitev bi bila ohraniti gručo ETCD na glavnih vozliščih, da bi imeli minimalno zamudo pri kube-apiserverju. Če to ni mogoče, postavite ETCD čim bližje, z dobro pasovno širino med udeleženci. Bodite pozorni tudi na to, koliko vozlišč iz ETCD lahko izpade brez škode za gručo.

Devet nasvetov za uspešnost Kubernetes

Ne pozabite, da lahko pretirano povečanje števila udeležencev v gruči poveča toleranco na napake na račun zmogljivosti, vsega naj bo zmerno.

Če govorimo o nastavitvi storitve, je nekaj priporočil:

  1. Imejte dobro strojno opremo glede na velikost gruče (lahko preberete tukaj).

  2. Prilagodite nekaj parametrov, če ste razširili gručo med parom DC-jev ali če vaše omrežje in diski puščajo veliko želenega (lahko preberete tukaj).

Zaključek

Ta članek opisuje točke, ki jih naša ekipa poskuša upoštevati. To ni opis dejanj po korakih, temveč možnosti, ki so lahko koristne za optimizacijo režijskih stroškov gruče. Jasno je, da je vsaka gruča edinstvena na svoj način in rešitve za nastavitev so lahko zelo različne, zato bi bilo zanimivo dobiti povratne informacije od vas: kako spremljate svojo gručo Kubernetes, kako izboljšate njeno delovanje. Delite svoje izkušnje v komentarjih, zanimivo bo izvedeti.

Vir: www.habr.com