Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes
Kyë kjo artikull që ndihmon për të kuptuar se si funksionon balancimi i ngarkesës në Kubernetes, çfarë ndodh gjatë shkallëzimit të lidhjeve afatgjata dhe pse duhet të shqyrtoni balancimin nga ana e klientit nëse përdorni HTTP/2, gRPC, RSockets, AMQP ose protokolle të tjera afatgjata. 

Pak fjalë mbi mënyrën se si shpërndahet trafiku në Kubernetes 

Kubernetes ofron dy abstraksione të dobishme për publikimin e aplikacioneve: shërbime (Services) dhe implementime (Deployments).

Implementimet përshkruajnë se si dhe sa kopje të aplikacionit tuaj duhet të jenë në funksion në çdo moment. Çdo aplikacion publishohet si pod (Pod) dhe i caktohet një adresë IP.

Shërbimet, për funksionalitetet e tyre, janë të ngjashme me balancuesit e ngarkesës. Ato synojnë të shpërndajnë trafikun midis shumë pod-ësh.

Le të shohim se si duket kjo.

  1. Në diagramin më poshtë, shihni tre instanca të një aplikacioni dhe balancuesin e ngarkesës:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

  2. Balancuesi i ngarkesës quhet shërbim (Service) dhe i është caktuar një adresë IP. Çdo kërkesë hyrëse përshkruhet në një nga pod-et:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

  3. Skenari i implementimit përcakton numrin e instancave të aplikacionit. Ju praktikisht kurrë nuk do të keni nevojë të publikoni direkt një pod:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

  4. Çdo pod ka adresën e tij IP të caktuar:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

Është e dobishme të shihni shërbimet si një grup adresash IP. Çdo herë që i drejtoheni një shërbimi, një nga adresat IP zgjidhet nga lista dhe përdoret si adresë destinacioni.

Kjo duket si më poshtë.

  1. Kërcimi curl 10.96.45.152 në shërbim:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

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

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

  3. Trafiku dërgohet në një pod të caktuar:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

Nëse aplikacioni juaj përbëhet nga një frontend dhe një backend, atëherë do të keni si shërbim ashtu edhe implementim për çdo njësi.

Kur frontend-i bën një kërkesë ndaj backend-it, nuk ka nevojë të dijë se sa pod-e shërbejnë backend-in: mund të jetë një, dhjetë ose njëqind.

Gjithashtu, frontend-i nuk di asgjë për adresat e pod-eve që shërbejnë backend-in.

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

Kjo është si duket.

  1. Pod 1 kërkon një komponent të brendshëm të backend-it. Në vend që të zgjedhë një pod të caktuar të backend-it, ai bën një kërkesë ndaj shërbimit:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

  2. Shërbimi zgjedh një nga pod-at e backend-it si destinacion:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

  3. Trafiku shkon nga podi 1 në podin 5, të zgjedhur nga shërbimi:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

  4. Podi 1 nuk di se sa pod-e si podi 5 janë të fshehur pas shërbimit:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

Por si e shpërndan shërbimi kërkesat? Duket se përdoret balancimi round-robin? Le të e kuptojmë. 

Balancimi në shërbimet Kubernetes

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

Mund ta verifikoni këtë duke shkuar në çdo nodë të klustrit dhe duke ekzekutuar komandën netstat -ntlp.

Nuk do të jeni në gjendje të gjeni as IP-adresën e caktuar shërbimit.

IP-adresa e shërbimit është vendosur në nivelin e menaxhimit, në kontrollues, dhe regjistrohet në bazën e të dhënave — etcd. Ky adresë përdoret edhe nga një komponent tjetër — kube-proxy.
Kube-proxy merr një listë IP-adresash për të gjithë shërbimet dhe formon një set rregullash iptables në çdo nodë të klustrit.

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

IP-adresa e shërbimit përdoret vetëm si një pikë hyrjeje dhe nuk mbikëqyret nga ndonjë proces që e dëgjon këtë IP-adresë dhe port.

Le të shohim këtë. 

  1. Le të shqyrtojmë një kluster me tre nodes. Në çdo nodë ndodhen pod-e:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

  2. Pod-et e lidhura, të vizatuara me ngjyrë bezhë, janë pjesë e shërbimit. Pasi shërbimi nuk ekziston si proces, ai paraqitet me ngjyrë gri:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

  3. Podi i parë kërkon shërbimin dhe duhet të arrijë në një nga pod-et e lidhura:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

  4. Por shërbimi nuk ekziston, nuk ka proces. Si funksionon kjo?

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

  5. Para se kërkesa të largohet nga nodi, ajo kalon përmes rregullave iptables:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

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

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

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

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

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

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

A dinë iptables të balancojnë ngarkesën?

Jo, iptables përdoren për filtrimin dhe nuk janë projektuar për balancim.

Megjithatë, ekziston mundësia për të shkruar një set rregullash që funksionojnë si balancues i rremë.

Dhe kjo është realizuar në Kubernetes.

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

  1. Zgjidhni podin e parë me probabilitet 33%, përndryshe kaloni në rregullin tjetër.
  2. Zgjidhni podin e dytë me një probabilitet prej 50%, përndryshe kaloni në rregullin e ardhshëm.
  3. Zgjidhni podin e tretë.

Një sistem i tillë çon në përzgjedhjen e çdo podi me një probabilitet prej 33%.

Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

Dhe nuk ka asnjë garanci se pod 2 do të zgjidhet pas podit 1.

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

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

Koneksionet me jetëgjatësi në Kubernetes nuk shkallëzohen automatikisht.

Çdo kërkesë HTTP nga frontend në backend shërbehet nga një koneksion të veçantë TCP, i cili hapet dhe mbyllet.

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

Mund të reduktoni kohën e përpunimit të kërkesës dhe të ulni ngarkesën duke hapur një koneksion TCP dhe duke e përdorur atë për të gjitha kërkesat e ardhshme HTTP.

Në protokollin HTTP është e inkorporuar mundësia e quajtur HTTP keep-alive, ose ripërdorimi i koneksionit. Në këtë rast, një koneksion TCP përdoret për dërgimin dhe marrjen e shumë kërkesave dhe përgjigjeve HTTP:

Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

Kjo mundësi nuk është e aktivizuar automatikisht: si serveri, ashtu edhe klienti duhet të konfigurohen siç duhet.

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

Këtu ka disa lidhje për shembuj në gjuhë të ndryshme:

Çfarë do të ndodhë nëse përdorim keep-alive në shërbimin Kubernetes?
Le të supozojmë që si frontend ashtu edhe backend mbështesin keep-alive.

Kemi një kopje të frontend-it dhe tre instanca të backend-it. Frontend bën kërkesën e parë dhe hap një koneksion TCP me backend-in. Kërkesa arrin në shërbim, një nga podet e backend-it zgjidhet si adresë destinacioni. Pod-i i backend-it dërgon përgjigjen dhe frontend e merr atë.

Në dallim nga situata e zakonshme, kur, pas marrjes së përgjigjes, koneksioni TCP mbyllet, tani ai mbahet i hapur për kërkesat e ardhshme HTTP.

Çfarë do të ndodhë nëse frontend dërgon edhe kërkesa të tjera në backend?

Për dërgimin e këtyre kërkesave do të përdoret koneksioni TCP i hapur, të gjitha kërkesat do të shkojnë në të njëjtin pod të backend-it, ku shkoi kërkesa e parë.

A duhet që iptables të ribalancojë trafikun?

Jo në këtë rast.

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

Pasi të gjitha kërkesat pasuese shkojnë përmes një lidhjeje TCP të hapur tashmë, rregullat e iptables nuk thirren më.

Le të shohim se si duket kjo.

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

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata 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 afatgjata në Kubernetes

  3. Një nga pod-et e backend-it do të zgjidhet si adresë e destinacionit:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

  4. Kërkesa arrin pod-in. Në këtë pikë, një lidhje TCP e qëndrueshme midis dy pod-eve do të vendoset:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

  5. Çdo kërkesë tjetër nga pod-i i parë do të kalojë përmes lidhjes tashmë të vendosur:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

Si rezultat, ju keni marrë një përgjigje më të shpejtë dhe një kapacitet më të lartë, por keni humbur mundësinë për të skaluar backend-in.

Edhe nëse keni dy pod-e në backend, me një lidhje të qëndrueshme, trafiku do të shkojë vazhdimisht në një prej tyre.

A mund të rregullohet kjo?

Pasi Kubernetes nuk di si të balancojë lidhjet e qëndrueshme, kjo detyrë e bie juve.

Shërbimet janë një grup IP adresash dhe portesh, të cilat quhen pika fundore.

Aplikacioni juaj mund të marrë një listë pika fundore nga shërbimi dhe të vendosë se si të shpërndajë kërkesat midis tyre. Mund të krijoni një lidhje të qëndrueshme me çdo pod dhe të balansoni kërkesat midis këtyre lidhjeve duke përdorur round-robin.

Ose të përdorni algoritme më kompleks të balancimit.

Kodi në anën e klientit, i cili është përgjegjës për balancimin, duhet të ndiqni këtë logjikë:

  1. Merrni një listë pika fundore nga shërbimi.
  2. Për çdo pikë fundore hapni një lidhje të qëndrueshme.
  3. Kur nevojitet të bëni një kërkesë, përdorni një nga lidhjet e hapura.
  4. Rregullisht përditësoni listën e pika fundore, krijoni lidhje të reja ose mbyllni ato të vjetra në rast të ndryshimit të listës.

Ja si do të duket kjo.

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

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

  2. Duhet të shkruani kodin që pyet se cilat pod-e janë pjesë e shërbimit:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

  3. Sa më shpejt të merrni listën, ruajeni në anën e klientit dhe përdoreni për të lidhur me pod-et:

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

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

    Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

Tani lind pyetje: a përket ky problem vetëm për HTTP keep-alive?

Balancimi i ngarkesës në anën e klientit

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

Nëse aplikacioni juaj përdor një bazë të dhënash, lidhja TCP nuk hapet çdo herë kur 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 të përhershme TCP me bazën e të dhënave.

Nëse baza juaj e të dhënave është e shpërndarë në Kubernetes dhe aksesi ofrohet si një shërbim, atëherë do të përballeni me të njëjtat probleme që janë përmendur në seksionin e mëparshëm.

Një kopje e bllokës së të dhënave do të mbushet më shumë se të tjerat. Kube-proxy dhe Kubernetes nuk ndihmojnë në balancimin e lidhjeve. Ju duhet të kujdeseni për balancimin e kërkesave në bazën tuaj të të dhënave.

Në varësi të asaj se çfarë biblioteke përdorni për t'u lidhur me Bazen e të Dhënave, mund të keni mundësi të ndryshme për zgjidhjen e kësaj problemes.

Më poshtë është një shembull i aksesit në grupin e Baza e të Dhënave MySQL nga Node.js:

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

var endpoints = /* merrni pikët e fundit nga Shërbimi */

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

// Bëni kërkesa në bazën e të dhënave MySQL të grumbulluara

Ekzistojnë shumë protokolle të tjera që përdorin lidhje të përhershme TCP:

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

Ju duhet të jeni tashmë të 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 për balancimin? Pse kërkohet ndryshimi i logjikës së klientit? A ekziston një zgjidhje native në Kubernetes?

Kube-proxy dhe iptables janë krijuar për të mbuluar shumicën e skenarëve standard të përdorimit kur shpaloset në Kubernetes. Kjo është bërë për lehtësi.

Nëse përdorni një shërbim web që ofron REST API, ju keni fat — në këtë rast lidhjet e përhershme TCP nuk përdoren, mund të përdorni çdo shërbim Kubernetes.

Por sapo të filloni të përdorni lidhje të përhershme TCP, do t'ju duhet të kuptoni se si të shpërndani ngarkesën në mënyrë të barabartë në backend-et. Kubernetes nuk ka zgjidhje të gatshme për këtë rast.

Megjithatë, sigurisht që ka mundësi që mund të ndihmojnë.

Balancimi i lidhjeve jetëgjatë në Kubernetes

Në Kubernetes ka katër lloje shërbimesh:

  1. ClusterIP
  2. NodePort
  3. LoadBalancer
  4. Headless

Tre shërbimet e para funksionojnë mbi një IP virtual, e cila përdoret nga kube-proxy për ndërtimin e rregullave iptables. Por baza themelore e të gjitha shërbimeve është një shërbim i tipit headless.

Me shërbimin headless nuk është e lidhur asnjë IP dhe ai ofron vetëm një mekanizëm për të marrë listën e IP-ve dhe porteve të lidhura me pod-ët e tij (pikët e fundit).

Të gjitha shërbimet bazohen në shërbimin headless.

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

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

Kështu, ju mund të injoroni kube-proxy dhe të përdorni drejtpërdrejt listën e pikëve të fundit të marra nga shërbimi headless për balancimin e ngarkesës në aplikacionin tuaj.

Por si të shtoni një logjikë të tillë në të gjitha aplikacionet e drejtuara në klaster?

Nëse aplikacioni juaj është tashmë i drejtuar, ky detyrë mund të duket e pamundur. Megjithatë, ka një alternativë.

Service Mesh do t'ju ndihmojë.

Ka të ngjarë që keni vënë re se strategjia e balancimit të ngarkesës nga ana e klientit është mjaft standarde.

Kur aplikacioni nis, ai:

  1. Merr një listë IP-sh nga shërbimi.
  2. Hap dhe mban një grup lidhjesh.
  3. Rregullisht përditëson grupin, duke shtuar ose hequr pikët e fundit.

Sa herë që aplikacioni dëshiron të bëjë një kërkesë, ai:

  1. Zgjedh një lidhje të disponueshme, duke përdorur një logjikë të caktuar (p.sh., round-robin).
  2. Kryen kërkesën.

Këto hapa funksionojnë si për lidhjet WebSockets, ashtu edhe për gRPC, dhe për AMQP.

Mund të nxirrni këtë logjikë në një bibliotekë të veçantë dhe ta përdorni atë në aplikacionet tuaja.

Megjithatë, mund të përdorni gjithashtu shërbime mesh, si Istio ose Linkerd.

Service Mesh i shton aplikacionit tuaj një proces, i cili:

  1. Automatikisht kërkon IP-të e shërbimeve.
  2. Kontrollon lidhjet si WebSockets dhe gRPC.
  3. Balancoon kërkesat, duke përdorur protokollin e duhur.

Service Mesh ndihmon në menaxhimin e trafikëve brenda klasterit, por është mjaft kërkues në burime. Opsione të tjera janë përdorimi i biblioteka të jashtme, si Netflix Ribbon, ose proxy të programueshëm, si Envoy.

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

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

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

Le të supozojmë se ka 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 afatgjata në Kubernetes

Lidhjet mund të shpërndahen në mënyrë të paekuilibruar: ndoshta katër klientë lidhen me të njëjtin server, por ka një mundësi të mirë që të dy serverët do 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 mjaftueshëm, dhe do të krijohet një ngushticë potenciale.

Le të supozojmë 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 tjerë do të qëndrojnë të papunësuar:

Balancimi i ngarkesës dhe shkallëzimi i lidhjeve afatgjata në Kubernetes

Nëse këto dy serverë nuk mund të përballojnë përpunimin e kërkesave të klientëve, shkallëzimi horizontal nuk do të ndihmojë.

Përfundim

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

Megjithatë, sa herë që filloni të punoni me protokollet e aplikacioneve që përdorin lidhje të përhershme TCP, siç janë 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ë përhershme TCP.

Kështu që, duhet të shkruani aplikacione duke marrë parasysh mundësinë e balancimit nga ana e klientit.

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

Çfarë tjetër të lexoni mbi këtë temë:

  1. Tre nivele auto-skalimi në Kubernetes dhe si t'i përdorni ato në mënyrë efektive. 
  2. Kubernetes në stilin e piraterisë me një model zbatimi.
  3. Kanalin tonë në Telegram për transformimin digjital.

Burimi: habr.com

Blini hosting të besueshëm për faqe interneti me mbrojtje nga DDoS, serverë VPS VDS 🔥 Blini hosting të besueshëm për faqe interneti me mbrojtje nga DDoS, serverë VPS VDS | ProHoster