Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine
See artikkel aitab mõista, kuidas toimib koormuse tasakaalustamine Kuberneteses, mis juhtub pikaajaliste ühenduste skaleerimisel ja miks tasub kaaluda kliendi poolel tasakaalustamist, kui kasutate HTTP/2, gRPC, RSockets, AMQP või muid pikaajalisi protokolle. 

Veidi sellest, kuidas liiklus Kuberneteses ümber jaotatakse 

Kubernetes pakub kahte mugavat abstraktsiooni rakenduste välja tootmiseks: teenused (Services) ja juurutamised (Deployments).

Juurutamised määratlevad, kuidas ja kui palju teie rakenduse koopiaid peaks olema käimas igal hetkel. Iga rakendus käivitatakse kui pod (Pod) ja sellele määratakse IP-aadress.

Teenused on funktsioonidelt sarnased koormuse tasakaalustajaga. Need on mõeldud liikluse jaotamiseks mitme podi vahel.

Vaatame, kuidas see välja näeb.

  1. Alloleval joonisel näete kolme sama rakenduse instantsi ja koormuse tasakaalustajat:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  2. Koormuse tasakaalustajat nimetatakse teenuseks (Service), sellele on määratud IP-aadress. Iga sisenev päring suunatakse ühele podile:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  3. Juurutusstsenaarium määrab rakenduse instantside arvu. Peaaegu kunagi ei pea te podi otse juurutama:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  4. Igal podil on oma IP-aadress:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

On kasulik mõista teenuseid kui IP-aadresside kogumit. Iga kord, kui pöördute teenuse poole, valitakse nimekirjast üks IP-aadress ja seda kasutatakse sihtadressina.

See näeb välja järgmine.

  1. Päring curl 10.96.45.152 teenusele tuleb:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  2. Teenuse valib sihtkohaks ühe kolmest podi aadressist:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  3. Liiklus suunatakse konkreetsele podile:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

Kui teie rakendus koosneb esiosas ja tagaküljest, siis on teil igaühe jaoks teenus ja juurutamine.

Kui esiosa teeb päringu tagaküljele, ei pea tal teadma, kui palju podisid tagumine osa teenindab: neid võib olla üks, kümme või sada.

Samuti ei tea esiosa midagi tagumise poole podide aadressidest.

Kui esiosa teeb päringu tagaküljele, kasutab ta tagumise teenuse IP-aadressi, mis ei muutu.

Nii see välja näeb.

  1. Pod 1 palub tagumise poole sisekomponenti. Selle asemel, et valida kindel tagumise poole pod, teeb ta päringu teenusele:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  2. Teenus valib ühe tagapaneeli podi sihtadressiks:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  3. Läbi on liiklus podi 1 ja teenuse poolt valitud podi 5 vahel:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  4. Podi 1 ei tea, kui paljusid podisid, nagu pod 5, teenuse taga on:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

Aga kuidas teenus päringuid jagab? Kas tundub, et kasutatakse round-robin tasakaalustamist? Uurime lähemalt. 

Tasakaalustamine Kubernetes tegevustes

Kubernetes teenused ei eksisteeri. Teenusel ei ole protsessi, millele on määratud IP-aadress ja port.

Selle veendumiseks võite siseneda mistahes klastrinoodi ja käivitada käsu netstat -ntlp.

Te isegi ei suuda leida teenusele määratud IP-aadressi.

Teenuse IP-aadress on haldustasandil, kontrolleris, ja salvestatud andmebaasi — etcd. Seda aadressi kasutab veel üks komponent — kube-proxy.
Kube-proxy saab nimekirja IP-aadressidest kõigile teenustele ja koostab igas klastrinoode iptables reeglite kogumi.

Need reeglid ütlevad: "Kui näeme teenuse IP-aadressi, peame muutma päringu sihtaadressi ja suunama selle ühe seotud podi juurde."

Teenuse IP-aadressi kasutatakse ainult sissepääsupunktina ja seda ei halda ükski protsess, mis kuulab selle IP-aadressi ja porti.

Vaadakem seda

  1. Vaatame kolmest noodist koosnevat klastrit. Igas noodis on podid:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  2. Seotud podid, millel on beež värv, on teenuse osa. Kuna teenust ei eksisteeri protsessina, on see kujutatud hallina:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  3. Esimene pod küsib teenust ja peab jõudma ühe seotud podi juurde:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  4. Kuid teenus ei eksisteeri, protsessi pole. Kuidas see toimib?

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  5. Enne kui päring lahkub noodist, läbib see iptables reeglid:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  6. Iptables reeglid teavad, et teenust ei ole, ja asendavad selle IP-aadressi ühega podide IP-aadressidest, mis on seotud selle teenusega:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  7. Päring saab kehtiva IP-aadressi sihtkohana ja töödeldakse normaalselt:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  8. Sõltuvalt võrgu topoloogiast jõuab päring lõpuks podi juurde:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

Kas iptables suudavad tasakaalu hoida?

Ei, iptables kasutatakse filtrimiseks ja ei ole loodud tasakaalustamiseks.

Kuid on võimalus kirjutada reeglite kogum, mis toimib nagu vale tasakaalustaja.

Ja just seda on Kubernetesis rakendatud.

Kui teil on kolm podi, kirjutab kube-proxy järgmised reeglid:

  1. Valige esimene pod 33% tõenäosusega, muidu liikuda järgmise reegli juurde.
  2. Vali teine pod 50% tõenäosusega, vastasel juhul mine järgmise reegli juurde.
  3. Vali kolmas pod.

Selline süsteem toob kaasa selle, et iga pod valitakse 33% tõenäosusega.

Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

Ja ei ole garantiid, et pod 2 valitakse järgmiseks pärast podi 1.

Märkus: iptables kasutab statistilist moodulit juhusliku jaotuse jaoks. Seega põhineb tasakaalustamise algoritm juhuslikul valikul.

Nüüd, kui sa mõistad, kuidas teenused töötavad, vaatame huvitavamaid tööstsenaariume.

Pikad ühendused Kuberneteses ei skaala vaikimisi.

Iga HTTP-päring esiosast tagasiside poole teenindatud eraldi TCP-ühenduse kaudu, mis avatakse ja suletakse.

Kui esiosa saadab tagasiside poolele 100 päringut sekundis, avatakse ja suletakse 100 erinevat TCP-ühendust.

Päringu töötlemise aega on võimalik vähendada ja koormust alandada, kui avada üks TCP-ühendus ja kasutada seda kõigi järgneva HTTP-päringu jaoks.

HTTP-protokollis on võimalus, mida nimetatakse HTTP keep-alive'iks või ühenduse taaskasutamiseks. Sel juhul kasutatakse ühte TCP-ühendust paljude HTTP-päringute ja vastuste saatmiseks ja vastuvõtmiseks:

Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

See võimalus ei ole vaikimisi sisse lülitatud: nii server kui ka klient peavad olema vastavalt seadistatud.

Seadistamine iseenesest on lihtne ja kergesti kergesti kättesaadav enamikule programmeerimiskeeltele ja keskkondadele.

Siin on mõned lingid erinevate keelte näidetele:

Mis juhtub, kui kasutame keep-alive'i Kuberneteses?
Oletame, et nii esi- kui tagasiside toetavad keep-alive'i.

Meil on üks eesmine koopia ja kolm tagapoolset eksemplari. Eesmine teeb esimese päringu ja avab TCP-ühenduse tagasiside poolega. Päring jõuab teenuseni, üks tagapool valitakse sihtmärgiks. Tagapool saadab vastuse ja eesmine saab selle kätte.

Erinevalt tavalisest olukorrast, kus pärast vastuse saamist TCP-ühendus suletakse, hoitakse nüüd see avatud järgmiste HTTP-päringute jaoks.

Mis juhtub, kui eesmine saadab veel päringud tagasiside poolele?

Nende päringute edastamiseks kasutatakse avatud TCP-ühendust, kõik päringud jõuavad samasse tagapooli, kuhu esimene päring jõudis.

Kas iptables ei peaks juurduks ära jaotama liiklust?

Mitteametlikul juhul.

Kui TCP-ühendus luuakse, läbib see iptables reegleid, mis valivad, millisesse tagabäkkidesse liiklus suunatakse.

Kuna kõik järgmised päringud lähevad juba avatud TCP-ühenduse kaudu, ei kutsuta iptables reegleid enam välja.

Vaatame, kuidas see välja näeb.

  1. Esimene pod saadab päringu teenusele:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  2. Te juba teate, mis edasi juhtub. Teenust ei eksisteeri, kuid on olemas iptables reeglid, mis töötlevad päringu:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  3. Üks tagabäkkide podidest valitakse sihtkohaks:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  4. Päring jõuab podi. Sel hetkel luuakse kahe poda vahel püsiv TCP-ühendus:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  5. Iga järgmine päring esimesest podist läheb juba loodud ühenduse kaudu:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

Seega saate kiirema vastuse ja kõrgema läbilaskevõime, kuid peate loobuma tagabäkkide skaleeritavusest.

Ieven kui tagabäkkides on kaks poda, liigub pidev ühendus alati ühe neist.

Kas seda on võimalik parandada?

Kuna Kubernetes ei tea, kuidas tasakaalustada püsivaid ühendusi, on see ülesanne antud teile.

Teenused on komplekt IP-aadresse ja porte, mida nimetatakse lõpp-punktideks.

Teie rakendus saab teenusest lõpp-punktide nimekirja ja otsustab, kuidas päringud nende vahel jagada. Võimalik on avada püsiv ühendus iga podiga ja tasakaalustada päringud nende ühenduste vahel round-robin meetodiga.

Või rakendada keerukamaid tasakaalustamisalgoritme..

Kliendi poolel olev kood, mis vastutab tasakaalustamise eest, peaks järgima järgmist loogikat:

  1. Saada lõpp-punktide nimekiri teenusest.
  2. Iga lõpp-punkti jaoks luua püsiv ühendus.
  3. Kui on vaja teha päring, kasutada ühte avatud ühendust.
  4. Regulaarselt värskendada lõpp-punktide nimekirja, luua uusi või sulgeda vanu püsivaid ühendusi nimekirja muutumisel.

Nii see välja näeb:.

  1. Kohaliku podi päringu saatmise asemel võite tasakaalustada päringud kliendi poolel:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  2. Tuleb kirjutada kood, mis küsib, millised podid kuuluvad teenusesse:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  3. Kui olete nimekirja saanud, salvestage see kliendi poolel ja kasutage podidega ühenduse loomiseks:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

  4. Te olete ise vastutav koormuse tasakaalustamise algoritmi eest:

    Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

Nüüd kerkib küsimus: kas see probleem puudutab ainult HTTP keep-alive'i?

Klient-poolne koormuse tasakaalustamine

HTTP ei ole ainus protokoll, mis võib kasutada püsinud TCP-ühendusi.

Kui teie rakendus kasutab andmebaasi, ei avata TCP-ühendust iga kord, kui peate päringu esitama või dokumendi andmebaasist saama. 

Selle asemel avatakse ja kasutatakse püsiv TCP-ühendus andmebaasiga.

Kui teie andmebaas on eraldatud Kuberneteses ja juurdepääs antakse teenuse kaudu, siis puutute kokku samu probleemidega, nagu eelnevas osas kirjeldatud.

Üks andmebaasi koopia on rohkem koormatud kui teised. Kube-proxy ja Kubernetes ei aita ühendusi tasakaalustada. Te peate hoolitsema oma andmebaasile esitatud päringute tasakaalustamise eest.

Tuginedes sellele, millist raamatukogu te andmebaasi ühendamiseks kasutate, võivad teil olla erinevad lahenduse variandid.

Allpool on näide MySQL andmebaasi klastrisse pääsemiseks Node.js'ist:

var mysql = require('mysql');
var poolCluster = mysql.createPoolCluster();

var endpoints = /* get endpoints from the Service */

for (var [index, endpoint] of endpoints) {
  poolCluster.add(`mysql-replica-${index}`, endpoint);
}

// Esitage päringud klastrisse kuuluvale MySQL andmebaasile

On palju teisi protokolle, mis kasutavad püsinud TCP-ühendusi:

  • WebSocket ja turvatud WebSocketid
  • HTTP/2
  • gRPC
  • RSocketid
  • AMQP

Te peaksite olema tutvunud enamikuga neist protokollidest.

Aga kui need protokollid on nii populaarsed, siis miks ei ole standardiseeritud lahendust tasakaalustamiseks? Miks peab klienti loogikat muutma? Kas Kubernetesel on natiivne lahendus?

Kube-proxy ja iptables on loodud sulgema enamik standardseid kasutusstsenaariume Kuberneteses rakendamisel. See on tehtud mugavuse lahendamiseks.

Kui kasutate veebiteenust, mis pakub REST API-d, siis olete õnnelik — sel juhul püsinud TCP-ühendusi ei kasutata, saate kasutada mis tahes Kubernetes teenust.

Kuid kui hakkate kasutama püsinud TCP-ühendusi, peate välja selgitama, kuidas koormust tasakaalustada backendide vahel. Kubernetes ei sisalda selle jaoks valmis lahendusi.

Küll aga on olemas variandid, mis võivad aidata.

Pikaajaliste ühenduste tasakaalustamine Kuberneteses

Kuberneteses on neli tüüpi teenuseid:

  1. ClusterIP
  2. NodePort
  3. LoadBalancer
  4. Pea-ühendus

Kolme esimest teenust töötavad virtuaalse IP-aadressi baasil, mida kube-proxy kasutab iptables'i reeglite koostamiseks. Kuid kõigi teenuste põhiidee on headless teenus.

Headless teenusega ei ole seotud ühtegi IP-aadressi ja see pakub ainult mehhanismi, et saada loend seotud podide IP-aadressidest ja sadamatest (lõpp-punktidest).

Kõik teenused põhinevad headless teenusel.

ClusterIP teenus on headless teenus teatud lisanditega: 

  1. Halduse kiht määrab sellele IP-aadressi.
  2. Kube-proxy koostab vajalikud iptables'i reeglid.

Seega võite ignoreerida kube-proxy't ja kasutada otse headless teenusest saadud lõpp-punktide loendit koormuse jagamiseks oma rakenduses.

Kuidas lisada sellist loogikat kõigisse klastrisse paigaldatud rakendustesse?

Kui teie rakendus on juba paigaldatud, võib see ülesanne tunduda ületamatuna. Kuid on olemas alternatiivne lahendus.

Service Mesh aitab teid.

Olete võib-olla juba märganud, et kliendipoolne koormuse jagamise strateegia on üsna standardne.

Kui rakendus käivitub, siis:

  1. Saab teenusest IP-aadresside loendi.
  2. Avab ja hoiab ühenduste tanti.
  3. Aeg-ajalt värskendab tanti, lisades või eemaldades lõpp-punkte.

Kui rakendus soovib teha päringu, siis:

  1. Valib saadaval oleva ühenduse, kasutades mingit loogikat (näiteks round-robin).
  2. Teeb päringu.

Need sammud töötavad nii WebSocketi kui ka gRPC ja AMQP ühenduste jaoks.

Saate selle loogika eraldi teeki välja tõsta ja kasutada oma rakendustes.

Siiski on võimalik kasutada teenuse võrke, näiteks Istio või Linkerd.

Service Mesh täiendab teie rakendust protsessiga, mis:

  1. Otsib automaatselt teenuste IP-aadresse.
  2. Kontrollib ühendusi, nagu WebSocketid ja gRPC.
  3. Jagab päringud, kasutades õiget protokolli.

Service Mesh aitab hallata liiklust klastris, kuid see on üsna ressursimahukas. Teised variandid on kolmandate osapoolte raamatukogude kasutamine, nagu Netflix Ribbon, või programmeeritavad pöördproksid, nagu Envoy.

Mida juhtub, kui ignoreerida koormuse jagamise küsimusi?

Te võite mitte kasutada koormuse jagamist ja siiski mingeid muutusi mitte märgata. Vaadakem mõningaid tööstsenaariume.

Kui teil on rohkem kliente kui servereid, ei ole see nii suur probleem.

Oletame, et on viis klienti, kes ühenduvad kahe serveriga. Isegi kui tasakaalustust ei ole, kasutatakse mõlemat serverit:

Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

Ühendused võivad olla ebaühtlaselt jaotatud: võib juhtuda, et neli klienti on ühinenud samasse serverisse, kuid on hea võimalus, et mõlemat serverit kasutatakse.

Küll aga on probleemsem vastupidine stsenaarium.

Kui teil on vähem kliente ja rohkem servereid, võivad teie ressursid jääda piisavalt kasutamata ning see toob endaga kaasa võimaliku kitsaskoha.

Oletame, et on kaks klienti ja viis serverit. Parimal juhul on kaks pidevat ühendust kahe serveriga viiest.

Ülejäänud serverid jäävad seisma:

Kubernetes's koormuse tasakaalustamine ja pikaajaliste ühenduste skaleerimine

Kui need kaks serverit ei suuda klientide päringute töötlemisega hakkama saada, ei aita horisontaalne skaleerimine.

Kokkuvõte

Kubernetes teenused on loodud töötama enamikus veebirakenduste standardsetes stsenaariumides.

Siiski, niipea kui hakkate töötama rakendusprotokollidega, mis kasutavad pidevaid TCP ühendusi, nagu andmebaasid, gRPC või WebSocketid, ei sobi teenused enam. Kubernetes ei paku seadmevahelist mehhanismi pidevate TCP-ühenduste tasakaalustamiseks.

See tähendab, et peate kirjutama rakendusi, arvestades kliendipoolse tasakaalustamise võimalust.

Tõlge on koostatud meeskonna poolt Kubernetes aaS Mail.ru-lt.

Mida veel selle kohta lugeda:

  1. Kubernetes'is on kolm automaatskaalumise taset ja kuidas neid tõhusalt kasutada
  2. 🥇Kuidas rahulikult magada, kui teil on pilveteenus: peamised arhitektuuri nõuanded | ProHoster.
  3. Meie kanal Telegramis digitaalse transformatsiooni teemal.

Allikas: habr.com

Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster