Devet Kubernetesovih savjeta za izvedbu

Devet Kubernetesovih savjeta za izvedbu

Bok svima! Moje ime je Oleg Sidorenkov, radim u DomClicku kao voditelj infrastrukturnog tima. Kubik koristimo u proizvodnji više od tri godine i tijekom tog vremena doživjeli smo mnogo različitih zanimljivih trenutaka s njim. Danas ću vam reći kako, s pravim pristupom, možete izvući još više performansi iz vanilla Kubernetesa za svoj klaster. Priprema, pozor, kreni!

Svi jako dobro znate da je Kubernetes skalabilni sustav otvorenog koda za orkestraciju spremnika; pa, ili 5 binarnih datoteka koje djeluju magično upravljajući životnim ciklusom vaših mikroservisa u poslužiteljskom okruženju. Osim toga, to je prilično fleksibilan alat koji se može sastaviti kao Lego za maksimalnu prilagodbu različitim zadacima.

I čini se da je sve u redu: bacite poslužitelje u klaster poput drva za ogrjev u ognjište i nećete znati za tugu. Ali ako ste za okoliš, pomislit ćete: "Kako mogu održavati vatru i poštedjeti šumu?" Drugim riječima, kako pronaći načine za poboljšanje infrastrukture i smanjenje troškova.

1. Pratite resurse tima i aplikacije

Devet Kubernetesovih savjeta za izvedbu

Jedna od najčešćih, ali učinkovitih metoda je uvođenje zahtjeva/ograničenja. Podijelite aplikacije po imenskim prostorima, a imenske prostore po razvojnim timovima. Prije implementacije postavite vrijednosti aplikacije za potrošnju procesorskog vremena, memorije i efemerne pohrane.

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

Kroz iskustvo smo došli do zaključka: ne biste trebali napuhati zahtjeve iz limita više od dva puta. Volumen klastera izračunava se na temelju zahtjeva, a ako aplikacijama date razliku u resursima, na primjer, 5-10 puta, onda zamislite što će se dogoditi s vašim čvorom kada se napuni podovima i odjednom primi opterećenje. Ništa dobro. Na minimumu, prigušivanje, a na maksimumu, reći ćete zbogom radniku i dobit ćete cikličko opterećenje na preostalim čvorovima nakon što se mahune počnu pomicati.

Osim toga, uz pomoć limitranges Na početku možete postaviti vrijednosti resursa za spremnik - minimalne, maksimalne i zadane:

➜  ~ 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 zaboravite ograničiti resurse prostora imena tako da jedan tim ne može preuzeti sve resurse klastera:

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

Kao što se vidi iz opisa resourcequotas, ako operativni tim želi implementirati podove koji će trošiti dodatnih 10 procesora, planer to neće dopustiti i izbacit će pogrešku:

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

Da biste riješili takav problem, možete napisati alat, na primjer, kao ovo, sposoban pohraniti i predati stanje naredbenih resursa.

2. Odaberite optimalnu pohranu datoteka

Devet Kubernetesovih savjeta za izvedbu

Ovdje bih se želio dotaknuti teme trajnih volumena i diskovnog podsustava Kubernetes radnih čvorova. Nadam se da nitko ne koristi "Cube" na HDD-u u proizvodnji, ali ponekad obični SSD više nije dovoljan. Naišli smo na problem gdje su zapisnici uništavali disk zbog I/O operacija, a rješenja nema mnogo:

  • Koristite SSD diskove visokih performansi ili prijeđite na NVMe (ako upravljate vlastitim hardverom).

  • Smanjite razinu zapisivanja.

  • Napravite "pametno" balansiranje mahuna koje siluju disk (podAntiAffinity).

Gornji zaslon pokazuje što se događa pod nginx-ingress-controllerom na disku kada je omogućeno bilježenje access_logs (~12 tisuća zapisa/s). Ovo stanje, naravno, može dovesti do degradacije svih aplikacija na ovom čvoru.

Što se PV tiče, jao, nisam sve probala vrste Trajni volumeni. Koristite najbolju opciju koja vam odgovara. Povijesno se kod nas dogodilo da mali dio servisa zahtijeva RWX volumene, a davno su za tu zadaću počeli koristiti NFS pohranu. Jeftino i... dovoljno. Naravno, on i ja smo jeli govno - bog te, ali naučili smo to štimati i glava me više ne boli. I ako je moguće, premjestite se na S3 pohranu objekata.

3. Prikupite optimizirane slike

Devet Kubernetesovih savjeta za izvedbu

Najbolje je koristiti slike optimizirane za spremnik kako bi ih Kubernetes mogao brže dohvatiti i izvršiti učinkovitije. 

Optimizirano znači da slike:

  • sadrže samo jednu aplikaciju ili obavljaju samo jednu funkciju;

  • male veličine, jer se velike slike lošije prenose preko mreže;

  • imati krajnje točke zdravlja i spremnosti koje Kubernetesu omogućuju poduzimanje radnji u slučaju prekida;

  • koristite operativne sustave prilagođene spremnicima (poput Alpine ili CoreOS), koji su otporniji na konfiguracijske pogreške;

  • koristite višestupanjske nadogradnje tako da možete implementirati samo kompajlirane aplikacije, a ne prateće izvore.

Postoje mnogi alati i usluge koji vam omogućuju provjeru i optimizaciju slika u hodu. Važno je uvijek ih ažurirati i testirati na sigurnost. Kao rezultat dobivate:

  1. Smanjeno opterećenje mreže na cijelom klasteru.

  2. Smanjenje vremena pokretanja spremnika.

  3. Manja veličina vašeg cijelog Docker registra.

4. Koristite DNS predmemoriju

Devet Kubernetesovih savjeta za izvedbu

Ako govorimo o velikim opterećenjima, onda je život prilično loš bez podešavanja DNS sustava klastera. Jednom davno, programeri Kubernetesa podržavali su svoje kube-dns rješenje. Također je implementiran ovdje, ali ovaj softver nije bio posebno podešen i nije proizveo potrebne performanse, iako se činilo da je to jednostavan zadatak. Onda se pojavio coredns na koji smo se prebacili i nismo imali tugu, kasnije je postao zadana DNS usluga u K8s. U nekom trenutku smo narasli na 40 tisuća rps na DNS sustav, a i to rješenje je postalo nedostatno. Ali, srećom, Nodelocaldns je izašao, aka node local cache, aka NodeLocal DNSCache.

Zašto ovo koristimo? Postoji greška u jezgri Linuxa koja, kada više poziva kroz conntrack NAT preko UDP-a, dovodi do stanja utrke za unose u conntrack tablicama, a dio prometa kroz NAT se gubi (svako putovanje kroz uslugu je NAT). Nodelocaldns rješava ovaj problem rješavanjem NAT-a i nadogradnjom veze na TCP na uzvodni DNS, kao i lokalno predmemoriranje uzvodnih DNS upita (uključujući kratku negativnu predmemoriju od 5 sekundi).

5. Automatski skalirajte mahune vodoravno i okomito

Devet Kubernetesovih savjeta za izvedbu

Možete li sa sigurnošću reći da su svi vaši mikroservisi spremni za dvostruko do trostruko povećanje opterećenja? Kako pravilno dodijeliti resurse svojim aplikacijama? Održavanje nekoliko modula u radu izvan radnog opterećenja može biti suvišno, ali njihovo držanje jedan uz drugog predstavlja opasnost od prekida rada zbog naglog povećanja prometa prema usluzi. Usluge kao što su Horizontalni pod Autoscaler и Vertical Pod Autoscaler.

VPA omogućuje vam da automatski podignete zahtjeve/ograničenja svojih spremnika u modulu ovisno o stvarnoj upotrebi. Kako to može biti korisno? Ako imate podove koji se iz nekog razloga ne mogu vodoravno skalirati (što nije posve pouzdano), možete pokušati povjeriti izmjene njegovih resursa VPA-u. Njegova značajka je sustav preporuka temeljen na povijesnim i trenutnim podacima s metričkog poslužitelja, pa ako ne želite automatski mijenjati zahtjeve/ograničenja, možete jednostavno pratiti preporučene resurse za svoje spremnike i optimizirati postavke kako biste uštedjeli CPU i memorije u klasteru.

Devet Kubernetesovih savjeta za izvedbuSlika preuzeta s https://levelup.gitconnected.com/kubernetes-autoscaling-101-cluster-autoscaler-horizontal-pod-autoscaler-and-vertical-pod-2a441d9ad231

Planer u Kubernetesu uvijek se temelji na zahtjevima. Koju god vrijednost tamo stavili, planer će tražiti odgovarajući čvor na temelju nje. Granične vrijednosti potrebne su kako bi kocka shvatila kada treba prigušiti ili ubiti kapsulu. A budući da je jedini važan parametar vrijednost zahtjeva, VPA će raditi s njim. Kad god okomito skalirate aplikaciju, definirate koji bi zahtjevi trebali biti. Što će onda biti s limitima? Ovaj će se parametar također proporcionalno skalirati.

Na primjer, ovdje su uobičajene postavke mahuna:

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

Mehanizam za preporuke utvrđuje da vaša aplikacija zahtijeva 300m CPU-a i 500Mi za ispravan rad. Dobit ćete sljedeće postavke:

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

Kao što je gore spomenuto, ovo je proporcionalno skaliranje na temelju omjera zahtjeva/ograničenja u manifestu:

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

  • Memorija: 250Mi → 500Mi: omjer 1:2.

Što se tiče HPA, onda je mehanizam rada transparentniji. Mjerni podaci kao što su CPU i memorija imaju prag, a ako prosjek svih replika premaši prag, aplikacija se skalira za +1 sub dok vrijednost ne padne ispod praga ili dok se ne dosegne najveći broj replika.

Devet Kubernetesovih savjeta za izvedbuSlika preuzeta s https://levelup.gitconnected.com/kubernetes-autoscaling-101-cluster-autoscaler-horizontal-pod-autoscaler-and-vertical-pod-2a441d9ad231

Uz uobičajene metrike kao što su CPU i memorija, možete postaviti pragove za svoje prilagođene metrike iz Prometheusa i raditi s njima ako mislite da je to najprecizniji pokazatelj kada treba skalirati svoju aplikaciju. Nakon što se aplikacija stabilizira ispod navedenog metričkog praga, HPA će početi smanjivati ​​podove na minimalni broj replika ili dok opterećenje ne dosegne navedeni prag.

6. Ne zaboravite na afinitet čvora i afinitet pod

Devet Kubernetesovih savjeta za izvedbu

Ne rade svi čvorovi na istom hardveru i ne moraju svi podovi pokretati računalno intenzivne aplikacije. Kubernetes vam omogućuje postavljanje specijalizacije čvorova i podova pomoću Afinitet čvora и Pod Affinity.

Ako imate čvorove koji su prikladni za računalno intenzivne operacije, tada je za maksimalnu učinkovitost bolje povezati aplikacije s odgovarajućim čvorovima. Da biste to učinili koristite nodeSelector s oznakom čvora.

Recimo da imate dva čvora: jedan s CPUType=HIGHFREQ i veliki broj brzih jezgri, druga sa MemoryType=HIGHMEMORY više memorije i brže performanse. Najlakši način je dodijeliti raspoređivanje čvoru HIGHFREQdodavanjem u odjeljak spec ovaj selektor:

…
nodeSelector:
	CPUType: HIGHFREQ

Skuplji i specifičniji način za to je korištenje nodeAffinity na terenu affinity razdela spec. Postoje dvije mogućnosti:

  • requiredDuringSchedulingIgnoredDuringExecution: teška postavka (planer će implementirati mahune samo na određenim čvorovima (i nigdje drugdje));

  • preferredDuringSchedulingIgnoredDuringExecution: meka postavka (planer će se pokušati implementirati na određene čvorove, a ako to ne uspije, pokušat će se implementirati na sljedeći dostupni čvor).

Možete navesti određenu sintaksu za upravljanje oznakama čvorova, kao što je In, NotIn, Exists, DoesNotExist, Gt ili Lt. Međutim, zapamtite da će složene metode u dugim popisima oznaka usporiti donošenje odluka u kritičnim situacijama. Drugim riječima, neka bude jednostavno.

Kao što je gore spomenuto, Kubernetes vam omogućuje da postavite afinitet trenutnih mahuna. Odnosno, možete osigurati da određene jedinice rade zajedno s drugim grupama u istoj zoni dostupnosti (relevantno za oblake) ili čvorovima.

В podAffinity polja affinity razdela spec dostupna su ista polja kao u slučaju nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution и preferredDuringSchedulingIgnoredDuringExecution. Jedina razlika je u tome matchExpressions će podove povezati s čvorom koji već pokreće pod s tom oznakom.

Kubernetes također nudi polje podAntiAffinity, koji, naprotiv, ne veže mahunu za čvor s određenim mahunama.

O izrazima nodeAffinity Može se dati isti savjet: pokušajte držati pravila jednostavnima i logičnima, nemojte pokušavati preopteretiti specifikaciju modula složenim skupom pravila. Vrlo je lako stvoriti pravilo koje neće odgovarati uvjetima klastera, stvarajući nepotrebno opterećenje na planeru i smanjujući ukupnu izvedbu.

7. Mrlje i tolerancije

Postoji još jedan način upravljanja planerom. Ako imate veliki klaster sa stotinama čvorova i tisućama mikroservisa, tada je vrlo teško ne dopustiti da određeni podovi budu hostirani na određenim čvorovima.

Mehanizam mrlja - pravila zabrane - pomaže u tome. Na primjer, u određenim scenarijima možete zabraniti određenim čvorovima pokretanje podova. Da biste primijenili mrlju na određeni čvor morate upotrijebiti opciju taint u kubectl. Navedite ključ i vrijednost, a zatim pokvarite like NoSchedule ili NoExecute:

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

Također je vrijedno napomenuti da mehanizam mrlja podržava tri glavna učinka: NoSchedule, NoExecute и PreferNoSchedule.

  • NoSchedule znači da za sada neće biti odgovarajućeg unosa u specifikaciji modula tolerations, neće se moći postaviti na čvor (u ovom primjeru node10).

  • PreferNoSchedule - pojednostavljena verzija NoSchedule. U ovom slučaju, planer će pokušati ne dodijeliti podove koji nemaju odgovarajući unos tolerations po čvoru, ali to nije teško ograničenje. Ako u klasteru nema resursa, mahune će se početi postavljati na ovom čvoru.

  • NoExecute - ovaj učinak pokreće trenutačnu evakuaciju mahuna koje nemaju odgovarajući ulaz tolerations.

Zanimljivo je da se ovo ponašanje može poništiti pomoću mehanizma tolerancija. Ovo je zgodno kada postoji "zabranjeni" čvor i na njega trebate postaviti samo infrastrukturne usluge. Kako to učiniti? Dopustite samo one mahune za koje postoji odgovarajuća tolerancija.

Evo kako bi izgledala specifikacija kapsule:

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

To ne znači da će sljedeća preraspodjela pasti na ovaj određeni čvor, ovo nije mehanizam afiniteta čvora i nodeSelector. Ali kombiniranjem nekoliko značajki možete postići vrlo fleksibilne postavke planera.

8. Postavite prioritet postavljanja modula

Samo zato što imate podove dodijeljene čvorovima ne znači da se svi podovi moraju tretirati s istim prioritetom. Na primjer, možda ćete htjeti implementirati neke blokove prije drugih.

Kubernetes nudi različite načine za konfiguriranje Pod Priority i Preemption. Postavka se sastoji od nekoliko dijelova: objekt PriorityClass i opise polja priorityClassName u specifikaciji mahune. Pogledajmo primjer:

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"

Mi stvaramo PriorityClass, dajte mu naziv, opis i vrijednost. Što je viši value, veći je prioritet. Vrijednost može biti bilo koji 32-bitni cijeli broj manji od ili jednak 1 000 000 000. Više vrijednosti rezervirane su za kritične sistemske sklopove koji se općenito ne mogu preuzeti unaprijed. Premještanje će se dogoditi samo ako se grupa s visokim prioritetom nema gdje okrenuti, tada će neke od grupa iz određenog čvora biti evakuirane. Ako vam je ovaj mehanizam previše krut, možete dodati opciju preemptionPolicy: Never, i tada neće biti preemptiona, pod će stajati prvi u redu i čekati da planer pronađe slobodne resurse za njega.

Zatim kreiramo pod u kojem označavamo 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
          

Možete kreirati onoliko klasa prioriteta koliko želite, iako je preporučljivo ne zanositi se time (recimo, ograničite se na nizak, srednji i visoki prioritet).

Stoga, ako je potrebno, možete povećati učinkovitost postavljanja kritičnih servisa kao što su nginx-ingress-controller, coredns itd.

9. Optimizirajte ETCD klaster

Devet Kubernetesovih savjeta za izvedbu

ETCD se može nazvati mozgom cijelog klastera. Vrlo je važno održavati rad ove baze podataka na visokoj razini jer o tome ovisi brzina rada u Cubeu. Prilično standardno, au isto vrijeme i dobro rješenje bilo bi zadržati ETCD klaster na glavnim čvorovima kako bi imali minimalno kašnjenje do kube-apiservera. Ako to ne možete učiniti, postavite ETCD što bliže, s dobrom propusnošću između sudionika. Također obratite pozornost na to koliko čvorova iz ETCD-a može ispasti bez štete za klaster

Devet Kubernetesovih savjeta za izvedbu

Imajte na umu da pretjerano povećanje broja članova u klasteru može povećati toleranciju na pogreške nauštrb performansi, sve bi trebalo biti umjereno.

Ako govorimo o postavljanju usluge, postoji nekoliko preporuka:

  1. Imajte dobar hardver, na temelju veličine klastera (možete pročitati ovdje).

  2. Podesite nekoliko parametara ako ste raširili klaster između para DC-ova ili vaša mreža i diskovi ostavljaju mnogo toga za poželjeti (možete pročitati ovdje).

Zaključak

Ovaj članak opisuje točke kojih se naš tim nastoji pridržavati. Ovo nije opis radnji korak po korak, već opcije koje mogu biti korisne za optimizaciju opterećenja klastera. Jasno je da je svaki klaster jedinstven na svoj način, a konfiguracijska rješenja mogu uvelike varirati, stoga bi bilo zanimljivo dobiti vaše povratne informacije o tome kako nadzirete svoj Kubernetes klaster i kako poboljšavate njegovu izvedbu. Podijelite svoje iskustvo u komentarima, bit će zanimljivo znati.

Izvor: www.habr.com