Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes
Ky artikull do t'ju ndihmojë të kuptoni se si funksionon balancimi i ngarkesës në Kubernetes, çfarë ndodh kur shkallëzoni lidhjet jetëgjata dhe pse duhet të merrni parasysh balancimin nga ana e klientit nëse përdorni HTTP/2, gRPC, RSockets, AMQP ose protokolle të tjera jetëgjatë . 

Pak për mënyrën se si trafiku rishpërndahet në Kubernetes 

Kubernetes ofron dy abstraksione të përshtatshme për vendosjen e aplikacioneve: Shërbimet dhe Vendosjet.

Vendosjet përshkruajnë se si dhe sa kopje të aplikacionit tuaj duhet të ekzekutohen në çdo kohë të caktuar. Çdo aplikacion vendoset si një Pod dhe i caktohet një adresë IP.

Shërbimet janë të ngjashme në funksion me një balancues të ngarkesës. Ato janë krijuar për të shpërndarë trafikun nëpër pods të shumta.

Le të shohim se si duket.

  1. Në diagramin më poshtë mund të shihni tre raste të të njëjtit aplikacion dhe një balancues të ngarkesës:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  2. Balancuesi i ngarkesës quhet Shërbimi dhe i është caktuar një adresë IP. Çdo kërkesë hyrëse ridrejtohet në një nga grupet:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  3. Skenari i vendosjes përcakton numrin e rasteve të aplikacionit. Pothuajse kurrë nuk do t'ju duhet të zgjeroheni drejtpërdrejt nën:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  4. Çdo pod i caktohet adresa e vet IP:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

Është e dobishme të mendosh për shërbimet si një koleksion adresash IP. Sa herë që hyni në shërbim, një nga adresat IP zgjidhet nga lista dhe përdoret si adresa e destinacionit.

Duket kështu.

  1. Një kërkesë curl 10.96.45.152 është marrë në shërbim:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  2. Shërbimi zgjedh një nga tre adresat e pod si destinacion:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  3. Trafiku ridrejtohet në një pod specifik:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

Nëse aplikacioni juaj përbëhet nga një frontend dhe një prapavijë, atëherë do të keni një shërbim dhe një vendosje për secilën.

Kur pjesa e përparme i bën një kërkesë backend-it, ai nuk ka nevojë të dijë saktësisht se sa pods shërben backend: mund të jenë një, dhjetë ose njëqind.

Gjithashtu, frontend nuk di asgjë në lidhje me adresat e pods që shërbejnë backend.

Kur frontend i bën një kërkesë backend-it, ai përdor adresën IP të shërbimit backend, i cili nuk ndryshon.

Kështu duket.

  1. Nën 1 kërkon komponentin e brendshëm të mbështetjes. Në vend që të zgjedhë një të veçantë për backend-in, ai i bën një kërkesë shërbimit:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  2. Shërbimi zgjedh një nga pods-et mbështetëse si adresën e destinacionit:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  3. Trafiku shkon nga Pod 1 në Pod 5, i zgjedhur nga shërbimi:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  4. Under 1 nuk e di saktësisht se sa pods si nën 5 janë fshehur pas shërbimit:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

Por si i shpërndan kërkesat saktësisht shërbimi? Duket sikur është përdorur balancimi i rrumbullakët? Le ta kuptojmë. 

Balancimi në shërbimet Kubernetes

Shërbimet Kubernetes nuk ekzistojnë. Nuk ka asnjë proces për shërbimin që i është caktuar një adresë IP dhe port.

Ju mund ta verifikoni këtë duke hyrë në çdo nyje në grup dhe duke ekzekutuar komandën netstat -ntlp.

Ju as nuk do të jeni në gjendje të gjeni adresën IP të caktuar për shërbimin.

Adresa IP e shërbimit ndodhet në shtresën e kontrollit, në kontrollues dhe regjistrohet në bazën e të dhënave - etj. E njëjta adresë përdoret nga një komponent tjetër - kube-proxy.
Kube-proxy merr një listë të adresave IP për të gjitha shërbimet dhe gjeneron një grup rregullash iptables në secilën nyje në grup.

Këto rregulla thonë: "Nëse shohim adresën IP të shërbimit, duhet të modifikojmë adresën e destinacionit të kërkesës dhe ta dërgojmë në një nga pods."

Adresa IP e shërbimit përdoret vetëm si pikë hyrëse dhe nuk shërbehet nga asnjë proces që dëgjon atë adresë IP dhe port.

Le të shohim këtë

  1. Konsideroni një grup prej tre nyjesh. Çdo nyje ka pods:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  2. Bishtaja e lidhur e lyer ngjyrë bezhë janë pjesë e shërbimit. Për shkak se shërbimi nuk ekziston si proces, ai shfaqet me gri:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  3. Pozicioni i parë kërkon një shërbim dhe duhet të shkojë në një nga grupet e lidhura:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  4. Por shërbimi nuk ekziston, procesi nuk ekziston. Si punon?

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  5. Përpara se kërkesa të largohet nga nyja, ajo kalon nëpër rregullat iptables:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  6. Rregullat e iptables e dinë që shërbimi nuk ekziston dhe zëvendësojnë adresën e tij IP me një nga adresat IP të pod-eve të lidhura me atë shërbim:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  7. Kërkesa merr një adresë IP të vlefshme si adresë destinacioni dhe përpunohet normalisht:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  8. Në varësi të topologjisë së rrjetit, kërkesa përfundimisht arrin në pod:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

A mundet iptables të ngarkojë bilancin?

Jo, iptable-t përdoren për filtrim dhe nuk janë krijuar për balancim.

Megjithatë, është e mundur të shkruhet një grup rregullash që funksionojnë si pseudobalancues.

Dhe kjo është pikërisht ajo që zbatohet në Kubernetes.

Nëse keni tre pods, kube-proxy do të shkruajë rregullat e mëposhtme:

  1. Zgjidhni nënën e parë me një probabilitet prej 33%, përndryshe shkoni te rregulli tjetër.
  2. Zgjidhni të dytin me probabilitet 50%, përndryshe shkoni te rregulli tjetër.
  3. Zgjidhni të tretën nën.

Ky sistem rezulton që çdo pod të zgjidhet me një probabilitet prej 33%.

Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

Dhe nuk ka asnjë garanci që Pod 2 do të zgjidhet pas Pod 1.

Shënim: iptables përdor një modul statistikor me shpërndarje të rastësishme. Kështu, algoritmi i balancimit bazohet në përzgjedhjen e rastësishme.

Tani që e kuptoni se si funksionojnë shërbimet, le të shohim skenarë më interesantë të shërbimit.

Lidhjet jetëgjata në Kubernetes nuk shkallëzohen si parazgjedhje

Çdo kërkesë HTTP nga frontend në backend shërbehet nga një lidhje e veçantë TCP, e cila hapet dhe mbyllet.

Nëse frontend dërgon 100 kërkesa në sekondë në backend, atëherë hapen dhe mbyllen 100 lidhje të ndryshme TCP.

Mund të zvogëloni kohën dhe ngarkesën e përpunimit të kërkesës duke hapur një lidhje TCP dhe duke e përdorur atë për të gjitha kërkesat e mëvonshme HTTP.

Protokolli HTTP ka një veçori të quajtur HTTP keep-live, ose ripërdorim i lidhjes. Në këtë rast, një lidhje e vetme TCP përdoret për të dërguar dhe marrë kërkesa dhe përgjigje të shumta HTTP:

Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

Ky funksion nuk është aktivizuar si parazgjedhje: si serveri ashtu edhe klienti duhet të konfigurohen në përputhje me rrethanat.

Vetë konfigurimi është i thjeshtë dhe i arritshëm për shumicën e gjuhëve dhe mjediseve të programimit.

Këtu janë disa lidhje me shembuj në gjuhë të ndryshme:

Çfarë ndodh nëse përdorim mbaj-live në një shërbim Kubernetes?
Le të supozojmë se si pjesa e përparme ashtu edhe pjesa e pasme mbështesin të qëndrojnë gjallë.

Ne kemi një kopje të pjesës së përparme dhe tre kopje të pjesës së përparme. Frontend bën kërkesën e parë dhe hap një lidhje TCP me backend. Kërkesa arrin shërbimin, si adresa e destinacionit zgjidhet një nga grupet e mbështetjes. Backend dërgon një përgjigje, dhe frontend e merr atë.

Ndryshe nga situata e zakonshme ku lidhja TCP mbyllet pas marrjes së një përgjigjeje, ajo tani mbahet e hapur për kërkesa të mëtejshme HTTP.

Çfarë ndodh nëse frontend dërgon më shumë kërkesa në backend?

Për të përcjellë këto kërkesa, do të përdoret një lidhje e hapur TCP, të gjitha kërkesat do të shkojnë në të njëjtin backend ku shkoi kërkesa e parë.

A nuk duhet iptables të rishpërndajë trafikun?

Jo në këtë rast.

Kur krijohet një lidhje TCP, ajo kalon përmes rregullave iptables, të cilat zgjedhin një backend specifik ku do të shkojë trafiku.

Meqenëse të gjitha kërkesat e mëvonshme janë në një lidhje tashmë të hapur TCP, rregullat iptables nuk thirren më.

Le të shohim se si duket.

  1. Pod-i i parë dërgon një kërkesë në shërbim:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  2. Ju tashmë e dini se çfarë do të ndodhë më pas. Shërbimi nuk ekziston, por ka rregulla iptables që do të përpunojnë kërkesën:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  3. Një nga grupet mbështetëse do të zgjidhet si adresa e destinacionit:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  4. Kërkesa arrin në pod. Në këtë pikë, do të krijohet një lidhje e vazhdueshme TCP midis dy podeve:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  5. Çdo kërkesë e mëvonshme nga podi i parë do të kalojë përmes lidhjes së krijuar tashmë:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

Rezultati është koha më e shpejtë e përgjigjes dhe xhiroja më e lartë, por ju humbni aftësinë për të shkallëzuar prapavijën.

Edhe nëse keni dy pods në pjesën e pasme, me një lidhje të vazhdueshme, trafiku do të shkojë gjithmonë në njërën prej tyre.

A mund të rregullohet kjo?

Meqenëse Kubernetes nuk di të balancojë lidhjet e vazhdueshme, kjo detyrë bie mbi ju.

Shërbimet janë një koleksion i adresave IP dhe porteve të quajtura pika fundore.

Aplikacioni juaj mund të marrë një listë të pikave përfundimtare nga shërbimi dhe të vendosë se si të shpërndajë kërkesat ndërmjet tyre. Mund të hapësh një lidhje të vazhdueshme me çdo pod dhe të balancosh kërkesat midis këtyre lidhjeve duke përdorur "Round-robin".

Ose aplikoni më shumë algoritme komplekse të balancimit.

Kodi i klientit që është përgjegjës për balancimin duhet të ndjekë këtë logjikë:

  1. Merrni një listë të pikave përfundimtare nga shërbimi.
  2. Hapni një lidhje të vazhdueshme për çdo pikë fundore.
  3. Kur duhet të bëhet një kërkesë, përdorni një nga lidhjet e hapura.
  4. Përditësoni rregullisht listën e pikave fundore, krijoni të reja ose mbyllni lidhjet e vjetra të vazhdueshme nëse lista ndryshon.

Kështu do të duket.

  1. Në vend që podi i parë të dërgojë kërkesën në shërbim, ju mund të balanconi kërkesat në anën e klientit:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  2. Ju duhet të shkruani kodin që pyet se cilat pods janë pjesë e shërbimit:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  3. Pasi të keni listën, ruajeni në anën e klientit dhe përdorni atë për t'u lidhur me pods:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

  4. Ju jeni përgjegjës për algoritmin e balancimit të ngarkesës:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

Tani lind pyetja: a zbatohet ky problem vetëm për HTTP-në e mbajtur gjallë?

Balancimi i ngarkesës nga ana e klientit

HTTP nuk është protokolli i vetëm që mund të përdorë lidhje të vazhdueshme TCP.

Nëse aplikacioni juaj përdor një bazë të dhënash, atëherë një lidhje TCP nuk hapet sa herë që ju duhet të bëni një kërkesë ose të merrni një dokument nga baza e të dhënave. 

Në vend të kësaj, hapet dhe përdoret një lidhje e vazhdueshme TCP me bazën e të dhënave.

Nëse baza juaj e të dhënave është vendosur në Kubernetes dhe aksesi ofrohet si shërbim, atëherë do të hasni të njëjtat probleme të përshkruara në seksionin e mëparshëm.

Një kopje e bazës së të dhënave do të jetë më e ngarkuar se të tjerat. Kube-proxy dhe Kubernetes nuk do të ndihmojnë në balancimin e lidhjeve. Duhet të kujdeseni që të balanconi pyetjet në bazën e të dhënave tuaja.

Në varësi të bibliotekës që përdorni për t'u lidhur me bazën e të dhënave, mund të keni mundësi të ndryshme për zgjidhjen e këtij problemi.

Më poshtë është një shembull i hyrjes në një grup bazë të dhënash MySQL nga Node.js:

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

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

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

// Make queries to the clustered MySQL database

Ka shumë protokolle të tjera që përdorin lidhje të vazhdueshme TCP:

  • WebSockets dhe WebSockets të sigurta
  • HTTP / 2
  • gRPC
  • RSockets
  • AMQP

Ju tashmë duhet të jeni njohur me shumicën e këtyre protokolleve.

Por nëse këto protokolle janë kaq të njohura, pse nuk ka një zgjidhje të standardizuar balancuese? Pse duhet të ndryshojë logjika e klientit? A ka një zgjidhje vendase Kubernetes?

Kube-proxy dhe iptables janë krijuar për të mbuluar rastet më të zakonshme të përdorimit kur vendosen në Kubernetes. Kjo është për lehtësi.

Nëse jeni duke përdorur një shërbim ueb që ekspozon një API REST, ju jeni me fat - në këtë rast, lidhjet e vazhdueshme TCP nuk përdoren, ju mund të përdorni çdo shërbim Kubernetes.

Por sapo të filloni të përdorni lidhjet e vazhdueshme TCP, do t'ju duhet të kuptoni se si të shpërndani në mënyrë të barabartë ngarkesën në të gjithë prapavijët. Kubernetes nuk përmban zgjidhje të gatshme për këtë rast.

Sidoqoftë, sigurisht që ka opsione që mund të ndihmojnë.

Balancimi i lidhjeve jetëgjatë në Kubernetes

Ekzistojnë katër lloje shërbimesh në Kubernetes:

  1. ClusterIP
  2. Porta e nyjeve
  3. LoadBalancer
  4. Pa kokë

Tre shërbimet e para funksionojnë bazuar në një adresë IP virtuale, e cila përdoret nga kube-proxy për të ndërtuar rregullat iptables. Por baza themelore e të gjitha shërbimeve është një shërbim pa kokë.

Shërbimi pa kokë nuk ka ndonjë adresë IP të lidhur me të dhe ofron vetëm një mekanizëm për marrjen e një liste të adresave IP dhe porteve të pods (pikave fundore) të lidhura me të.

Të gjitha shërbimet bazohen në shërbimin pa kokë.

Shërbimi ClusterIP është një shërbim pa kokë me disa shtesa: 

  1. Shtresa e menaxhimit i cakton asaj një adresë IP.
  2. Kube-proxy gjeneron rregullat e nevojshme iptables.

Në këtë mënyrë ju mund të injoroni kube-proxy dhe të përdorni drejtpërdrejt listën e pikave fundore të marra nga shërbimi pa kokë për të ngarkuar balancën e aplikacionit tuaj.

Por si mund të shtojmë logjikë të ngjashme për të gjitha aplikacionet e vendosura në grup?

Nëse aplikacioni juaj është vendosur tashmë, kjo detyrë mund të duket e pamundur. Megjithatë, ekziston një opsion alternativ.

Shërbimi Mesh do t'ju ndihmojë

Ndoshta e keni vënë re tashmë se strategjia e balancimit të ngarkesës nga ana e klientit është mjaft standarde.

Kur fillon aplikacioni, ai:

  1. Merr një listë të adresave IP nga shërbimi.
  2. Hap dhe mirëmban një pishinë lidhjeje.
  3. Përditëson periodikisht grupin duke shtuar ose hequr pikat përfundimtare.

Pasi aplikacioni dëshiron të bëjë një kërkesë, ai:

  1. Zgjedh një lidhje të disponueshme duke përdorur disa logjikë (p.sh. me rrotullim).
  2. Ekzekuton kërkesën.

Këta hapa funksionojnë si për lidhjet WebSockets, gRPC dhe AMQP.

Ju mund ta ndani këtë logjikë në një bibliotekë të veçantë dhe ta përdorni në aplikacionet tuaja.

Sidoqoftë, në vend të tyre mund të përdorni rrjeta shërbimi si Istio ose Linkerd.

Service Mesh rrit aplikacionin tuaj me një proces që:

  1. Kërkon automatikisht për adresat IP të shërbimit.
  2. Teston lidhje të tilla si WebSockets dhe gRPC.
  3. Balancon kërkesat duke përdorur protokollin e duhur.

Service Mesh ndihmon në menaxhimin e trafikut brenda grupit, por është mjaft intensiv me burime. Opsione të tjera janë duke përdorur biblioteka të palëve të treta si Netflix Ribbon ose përfaqësues të programueshëm si Envoy.

Çfarë ndodh nëse injoroni çështjet e balancimit?

Mund të zgjidhni të mos përdorni balancimin e ngarkesës dhe të mos vini re ndonjë ndryshim. Le të shohim disa skenarë pune.

Nëse keni më shumë klientë sesa serverë, ky nuk është një problem aq i madh.

Le të themi se janë pesë klientë që lidhen me dy serverë. Edhe nëse nuk ka balancim, të dy serverët do të përdoren:

Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

Lidhjet mund të mos shpërndahen në mënyrë të barabartë: ndoshta katër klientë të lidhur me të njëjtin server, por ka një shans të mirë që të dy serverët të përdoren.

Ajo që është më problematike është skenari i kundërt.

Nëse keni më pak klientë dhe më shumë serverë, burimet tuaja mund të mos përdoren më pak dhe do të shfaqet një pengesë e mundshme.

Le të themi se ka dy klientë dhe pesë serverë. Në rastin më të mirë, do të ketë dy lidhje të përhershme me dy serverë nga pesë.

Serverët e mbetur do të jenë të papunë:

Balancimi i ngarkesës dhe shkallëzimi i lidhjeve jetëgjatë në Kubernetes

Nëse këta dy serverë nuk mund të trajtojnë kërkesat e klientit, shkallëzimi horizontal nuk do të ndihmojë.

Përfundim

Shërbimet Kubernetes janë krijuar për të funksionuar në shumicën e skenarëve standardë të aplikacioneve në internet.

Megjithatë, sapo të filloni të punoni me protokollet e aplikacioneve që përdorin lidhje të vazhdueshme TCP, të tilla si bazat e të dhënave, gRPC ose WebSockets, shërbimet nuk janë më të përshtatshme. Kubernetes nuk ofron mekanizma të brendshëm për balancimin e lidhjeve të vazhdueshme TCP.

Kjo do të thotë që ju duhet të shkruani aplikacione duke pasur parasysh balancimin nga ana e klientit.

Përkthimi i përgatitur nga ekipi Kubernetes aaS nga Mail.ru.

Çfarë tjetër për të lexuar në këtë temë:

  1. Tre nivele të shkallëzimit automatik në Kubernetes dhe si t'i përdorni ato në mënyrë efektive
  2. Kubernetes në frymën e piraterisë me një shabllon për zbatim.
  3. Kanali ynë Telegram për transformimin dixhital.

Burimi: www.habr.com

Shto një koment