Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes
Dit artikel sil jo helpe te begripen hoe't load balancing wurket yn Kubernetes, wat bart by it skaaljen fan lange-libbene ferbiningen, en wêrom jo moatte beskôgje client-side balancing as jo brûke HTTP/2, gRPC, RSockets, AMQP, of oare lange-libben protokollen . 

In bytsje oer hoe't ferkear yn Kubernetes opnij ferdield wurdt 

Kubernetes leveret twa handige abstraksjes foar it ynsetten fan applikaasjes: Tsjinsten en ynset.

Ynset beskriuwe hoe en hoefolle eksimplaren fan jo applikaasje op elk momint rinne moatte. Elke applikaasje wurdt ynset as in Pod en wurdt in IP-adres tawiisd.

Tsjinsten binne yn funksje fergelykber mei in load balancer. Se binne ûntworpen om ferkear te fersprieden oer meardere pods.

Litte wy sjen hoe't it derút sjocht.

  1. Yn it diagram hjirûnder kinne jo trije eksimplaren sjen fan deselde applikaasje en in loadbalancer:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  2. De load balancer wurdt in tsjinst neamd en wurdt in IP-adres tawiisd. Elk ynkommende fersyk wurdt omlaat nei ien fan 'e pods:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  3. It ynsetsenario bepaalt it oantal eksimplaren fan 'e applikaasje. Jo sille hast noait direkt moatte útwreidzje ûnder:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  4. Elke pod wurdt in eigen IP-adres tawiisd:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

It is handich om tsjinsten te tinken as in samling IP-adressen. Elke kear as jo tagong krije ta de tsjinst, wurdt ien fan 'e IP-adressen selektearre út 'e list en brûkt as bestimmingsadres.

It liket derop.

  1. In fersyk 10.96.45.152 wurdt ûntfongen oan 'e tsjinst:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  2. De tsjinst selekteart ien fan trije podadressen as bestimming:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  3. Ferkear wurdt omlaat nei in spesifike pod:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

As jo ​​applikaasje bestiet út in frontend en in backend, dan hawwe jo sawol in tsjinst as in ynset foar elk.

As de frontend in fersyk oan 'e efterkant docht, hoecht it net krekt te witten hoefolle pods de efterkant tsjinnet: d'r kinne ien, tsien of hûndert wêze.

Ek wit de frontend neat oer de adressen fan de pods dy't de efterkant betsjinje.

As de frontend in fersyk oan 'e efterkant docht, brûkt it it IP-adres fan' e efterkanttsjinst, dy't net feroaret.

Dit is wat it liket.

  1. Under 1 freget de ynterne backend-komponint. Ynstee fan in spesifyk te selektearjen foar de backend, makket it in fersyk oan 'e tsjinst:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  2. De tsjinst selekteart ien fan 'e backend pods as it bestimmingsadres:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  3. Ferkear giet fan Pod 1 nei Pod 5, selektearre troch de tsjinst:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  4. Under 1 wit net krekt hoefolle pods lykas ûnder 5 binne ferburgen efter de tsjinst:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

Mar hoe krekt ferspraat de tsjinst fersiken? It liket as round-robin balancing wurdt brûkt? Litte wy it útfine. 

Balansearjen yn Kubernetes tsjinsten

Kubernetes-tsjinsten besteane net. D'r is gjin proses foar de tsjinst dy't in IP-adres en poarte wurdt tawiisd.

Jo kinne dit ferifiearje troch yn te loggen op elke knooppunt yn it kluster en it kommando netstat -ntlp út te fieren.

Jo sille it IP-adres dat oan 'e tsjinst is tawiisd net iens kinne fine.

It IP-adres fan 'e tsjinst is te finen yn' e kontrôlelaach, yn 'e controller, en opnommen yn' e databank - ensfh. Itselde adres wurdt brûkt troch in oare komponint - kube-proxy.
Kube-proxy ûntfangt in list mei IP-adressen foar alle tsjinsten en genereart in set fan iptables-regels op elke knooppunt yn it kluster.

Dizze regels sizze: "As wy it IP-adres fan 'e tsjinst sjogge, moatte wy it bestimmingsadres fan it fersyk wizigje en it nei ien fan' e pods stjoere."

It IP-adres fan 'e tsjinst wurdt allinich brûkt as yngongspunt en wurdt net betsjinne troch in proses dat nei dat IP-adres en poarte harket.

Litte wy nei dit sjen

  1. Tink oan in kluster fan trije knopen. Elke knooppunt hat pods:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  2. Tied pods skildere beige binne ûnderdiel fan 'e tsjinst. Om't de tsjinst net as proses bestiet, wurdt it yn griis werjûn:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  3. De earste pod freget in tsjinst oan en moat nei ien fan 'e assosjearre pods gean:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  4. Mar de tsjinst bestiet net, it proses bestiet net. Hoe wurket it?

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  5. Foardat it fersyk it knooppunt ferlit, giet it troch de iptables-regels:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  6. De iptables-regels witte dat de tsjinst net bestiet en ferfange it IP-adres troch ien fan 'e IP-adressen fan' e pods dy't ferbûn binne mei dy tsjinst:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  7. It fersyk krijt in jildich IP-adres as bestimmingsadres en wurdt normaal ferwurke:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  8. Ofhinklik fan 'e netwurktopology berikt it fersyk úteinlik de pod:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

Kin iptables balâns laden?

Nee, iptables wurde brûkt foar filterjen en binne net ûntworpen foar balansearjen.

It is lykwols mooglik om in set regels te skriuwen dy't wurkje lykas pseudo-balancer.

En dit is krekt wat wurdt ymplementearre yn Kubernetes.

As jo ​​​​trije pods hawwe, sil kube-proxy de folgjende regels skriuwe:

  1. Selektearje de earste sub mei in kâns fan 33%, oars gean nei de folgjende regel.
  2. Kies de twadde mei in kâns fan 50%, oars gean nei de folgjende regel.
  3. Selektearje de tredde ûnder.

Dit systeem resultearret yn elke pod wurdt selektearre mei in kâns fan 33%.

Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

En d'r is gjin garânsje dat Pod 2 neist Pod 1 sil wurde keazen.

remark: iptables brûkt in statistyske module mei willekeurige ferdieling. Sa is it balânsalgoritme basearre op willekeurige seleksje.

No't jo begripe hoe't tsjinsten wurkje, litte wy nei mear ynteressante tsjinstsenario's sjen.

Langlibbene ferbiningen yn Kubernetes skaalje net standert

Elk HTTP-fersyk fan 'e frontend nei de efterkant wurdt betsjinne troch in aparte TCP-ferbining, dy't iepene en sluten wurdt.

As de frontend 100 fersiken per sekonde nei de efterkant stjoert, dan wurde 100 ferskillende TCP-ferbiningen iepene en sluten.

Jo kinne de ferwurkingstiid en laden fan fersyk ferminderje troch ien TCP-ferbining te iepenjen en it te brûken foar alle folgjende HTTP-oanfragen.

It HTTP-protokol hat in funksje neamd HTTP keep-alive, of ferbining opnij brûke. Yn dit gefal wurdt in inkele TCP-ferbining brûkt om meardere HTTP-oanfragen en antwurden te ferstjoeren en te ûntfangen:

Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

Dizze funksje is standert net ynskeakele: sawol de tsjinner as de client moatte dêroer konfigurearre wurde.

De opset sels is ienfâldich en tagonklik foar de measte programmeartalen en omjouwings.

Hjir binne wat keppelings nei foarbylden yn ferskate talen:

Wat bart der as wy keep-alive brûke yn in Kubernetes-tsjinst?
Litte wy oannimme dat sawol de frontend as backend keep-alive stypje.

Wy hawwe ien kopy fan 'e frontend en trije kopyen fan' e efterkant. De frontend makket it earste fersyk en iepenet in TCP-ferbining mei de efterkant. It fersyk berikt de tsjinst, ien fan 'e backend pods wurdt selektearre as it bestimmingsadres. De backend stjoert in antwurd, en de frontend ûntfangt it.

Oars as de gewoane situaasje dêr't de TCP-ferbining is sletten nei it ûntfangen fan in antwurd, wurdt it no iepen hâlden foar fierdere HTTP-oanfragen.

Wat bart der as de frontend mear oanfragen nei de efterkant stjoert?

Om dizze oanfragen troch te stjoeren, sil in iepen TCP-ferbining brûkt wurde, alle oanfragen sille nei deselde backend gean wêr't it earste fersyk gie.

Moatte iptables it ferkear net opnij fersprieden?

Net yn dit gefal.

As in TCP-ferbining wurdt makke, giet it troch iptables-regels, dy't in spesifike efterkant selektearje wêr't it ferkear hinne sil.

Sûnt alle folgjende oanfragen binne op in al iepen TCP-ferbining, wurde de iptables-regels net mear neamd.

Litte wy sjen hoe't it derút sjocht.

  1. De earste pod stjoert in fersyk nei de tsjinst:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  2. Jo witte al wat der barre sil. De tsjinst bestiet net, mar d'r binne iptables-regels dy't it fersyk sille ferwurkje:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  3. Ien fan 'e backend pods sil wurde selektearre as it bestimmingsadres:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  4. It fersyk berikt de pod. Op dit punt sil in oanhâldende TCP-ferbining tusken de twa pods wurde oprjochte:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  5. Elk folgjende fersyk fan 'e earste pod sil troch de al fêststelde ferbining gean:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

It resultaat is flugger reaksjetiid en hegere trochslach, mar jo ferlieze de mooglikheid om de efterkant te skaaljen.

Sels as jo twa pods yn 'e efterkant hawwe, mei in konstante ferbining, sil ferkear altyd nei ien fan har gean.

Kin dit wurde repareare?

Om't Kubernetes net wit hoe't se oanhâldende ferbiningen balansearje kinne, falt dizze taak op jo.

Tsjinsten binne in samling IP-adressen en poarten neamd einpunten.

Jo applikaasje kin in list mei einpunten krije fan 'e tsjinst en beslute hoe't jo fersiken tusken har fersprieden. Jo kinne in oanhâldende ferbining iepenje foar elke pod en balânsfersiken tusken dizze ferbiningen mei round-robin.

Of mear oanfreegje komplekse balancing algoritmen.

De koade oan 'e kant fan' e kliïnt dy't ferantwurdlik is foar balansearjen moat dizze logika folgje:

  1. Krij in list mei einpunten fan 'e tsjinst.
  2. Iepenje in oanhâldende ferbining foar elk einpunt.
  3. As in fersyk dien wurde moat, brûk dan ien fan 'e iepen ferbiningen.
  4. Update de list mei einpunten geregeldwei, meitsje nije oan of slute âlde oanhâldende ferbiningen as de list feroaret.

Dit is hoe't it der útsjen sil.

  1. Ynstee fan 'e earste pod dy't it fersyk nei de tsjinst stjoert, kinne jo oanfragen balansearje oan' e kliïntside:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  2. Jo moatte koade skriuwe dy't freget hokker pods diel útmeitsje fan 'e tsjinst:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  3. Sadree't jo de list hawwe, bewarje it op 'e kliïntside en brûk it om te ferbinen mei de pods:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

  4. Jo binne ferantwurdlik foar it load balancing algoritme:

    Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

No komt de fraach op: jildt dit probleem allinich foar HTTP keep-alive?

Klant-side load balancing

HTTP is net it ienige protokol dat persistente TCP-ferbiningen kin brûke.

As jo ​​applikaasje in databank brûkt, dan wurdt in TCP-ferbining net iepene elke kear as jo in fersyk meitsje moatte of in dokumint út 'e databank ophelje moatte. 

Ynstee dêrfan wurdt in oanhâldende TCP-ferbining mei de databank iepene en brûkt.

As jo ​​databank wurdt ynset op Kubernetes en tagong wurdt levere as in tsjinst, dan sille jo tsjinkomme deselde problemen beskreaun yn de foarige seksje.

Ien database replika sil mear laden wurde as de oaren. Kube-proxy en Kubernetes sille de ferbiningen net helpe. Jo moatte soargje om de queries yn jo database te balansearjen.

Ofhinklik fan hokker bibleteek jo brûke om te ferbinen mei de databank, kinne jo ferskate opsjes hawwe foar it oplossen fan dit probleem.

Hjirûnder is in foarbyld fan tagong ta in MySQL-databasekluster fan 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

D'r binne in protte oare protokollen dy't persistente TCP-ferbiningen brûke:

  • WebSockets en befeilige WebSockets
  • HTTP / 2
  • gRPC
  • RSockets
  • AMQP

Jo moatte al bekend wêze mei de measte fan dizze protokollen.

Mar as dizze protokollen sa populêr binne, wêrom is d'r dan gjin standerdisearre balânsoplossing? Wêrom moat de klantlogika feroarje? Is d'r in native Kubernetes-oplossing?

Kube-proxy en iptables binne ûntworpen om meast foarkommende gebrûksgefallen te dekken by ynset nei Kubernetes. Dit is foar it gemak.

As jo ​​​​in webtsjinst brûke dy't in REST API bleatstelt, hawwe jo gelok - yn dit gefal wurde persistente TCP-ferbiningen net brûkt, jo kinne elke Kubernetes-tsjinst brûke.

Mar as jo ienris begjinne mei it brûken fan persistente TCP-ferbiningen, moatte jo útfine hoe't jo de lading evenredich oer de efterkanten kinne ferdielen. Kubernetes befettet gjin klearmakke oplossingen foar dit gefal.

D'r binne lykwols wis opsjes dy't kinne helpe.

Balansearjen fan lange libbene ferbiningen yn Kubernetes

D'r binne fjouwer soarten tsjinsten yn Kubernetes:

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

De earste trije tsjinsten operearje basearre op in firtuele IP-adres, dat wurdt brûkt troch kube-proxy om iptables-regels te bouwen. Mar de fûnemintele basis fan alle tsjinsten is in kopleaze tsjinst.

De kopleaze tsjinst hat gjin IP-adres ferbûn en leveret allinich in meganisme foar it opheljen fan in list mei IP-adressen en havens fan 'e pods (einpunten) dy't dermei ferbûn binne.

Alle tsjinsten binne basearre op de headless tsjinst.

De ClusterIP-tsjinst is in kopleaze tsjinst mei wat tafoegings: 

  1. De behearslaach jout it in IP-adres ta.
  2. Kube-proxy genereart de nedige iptables-regels.

Op dizze manier kinne jo kube-proxy negearje en de list mei einpunten direkt brûke fan 'e kopleaze tsjinst om jo applikaasje lykwicht te laden.

Mar hoe kinne wy ​​​​fergelykbere logika tafoegje oan alle applikaasjes ynset yn it kluster?

As jo ​​applikaasje al is ynset, kin dizze taak ûnmooglik lykje. D'r is lykwols in alternative opsje.

Service Mesh sil jo helpe

Jo hawwe wierskynlik al opfallen dat de loadbalancingstrategy oan 'e kant fan'e kliïnt frij standert is.

As de applikaasje begjint, is it:

  1. Kriget in list mei IP-adressen fan 'e tsjinst.
  2. Iepenet en ûnderhâldt in ferbining pool.
  3. Periodyk updates it swimbad troch tafoegjen of fuortsmite einpunten.

Ienris de applikaasje wol in fersyk meitsje, dan:

  1. Selektearret in beskikbere ferbining mei wat logika (bgl. round-robin).
  2. Fiert it fersyk út.

Dizze stappen wurkje foar sawol WebSockets, gRPC, en AMQP-ferbiningen.

Jo kinne dizze logika skiede yn in aparte bibleteek en brûke it yn jo applikaasjes.

Jo kinne lykwols tsjinstmeshes brûke lykas Istio of Linkerd ynstee.

Service Mesh fergruttet jo applikaasje mei in proses dat:

  1. Sykje automatysk nei tsjinst IP-adressen.
  2. Testet ferbinings lykas WebSockets en gRPC.
  3. Balansearret oanfragen mei it juste protokol.

Service Mesh helpt ferkear binnen it kluster te behearjen, mar it is frij boarne-yntinsyf. Oare opsjes brûke bibleteken fan tredden lykas Netflix Ribbon of programmabele proxy's lykas Envoy.

Wat bart der as jo balânsproblemen negearje?

Jo kinne kieze om load balancing net te brûken en noch gjin feroarings op te merken. Litte wy nei in pear wurkscenario's sjen.

As jo ​​​​mear kliïnten hawwe as servers, is dit net sa'n grut probleem.

Litte wy sizze dat d'r fiif kliïnten binne dy't ferbine mei twa servers. Sels as d'r gjin balâns is, sille beide servers brûkt wurde:

Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

Ferbinings meie net lykwichtich ferdield: miskien fjouwer kliïnten ferbûn oan deselde tsjinner, mar der is in goede kâns dat beide tsjinners wurde brûkt.

Wat mear problematysk is, is it tsjinoerstelde senario.

As jo ​​minder kliïnten en mear servers hawwe, kinne jo boarnen ûnderbenut wurde en sil in potinsjele knelpunt ferskine.

Litte wy sizze dat d'r twa kliïnten en fiif servers binne. Yn it bêste gefal sille d'r twa permaninte ferbiningen wêze mei twa fan de fiif tsjinners.

De oerbleaune tsjinners sille idle wêze:

Loadbalancing en skaalfergrutting fan lange libbensferbiningen yn Kubernetes

As dizze twa tsjinners gjin klantfersiken kinne behannelje, sil horizontale skaalfergrutting net helpe.

konklúzje

Kubernetes-tsjinsten binne ûntworpen om te wurkjen yn de measte standert webapplikaasje-senario's.

As jo ​​lykwols begjinne te wurkjen mei applikaasjeprotokollen dy't persistente TCP-ferbiningen brûke, lykas databases, gRPC of WebSockets, binne tsjinsten net langer geskikt. Kubernetes leveret gjin ynterne meganismen foar it balansearjen fan persistente TCP-ferbiningen.

Dit betsjut dat jo applikaasjes moatte skriuwe mei klantside-balâns yn gedachten.

Oersetting taret troch it team Kubernetes aaS fan Mail.ru.

Wat oars te lêzen oer it ûnderwerp:

  1. Trije nivo's fan autoscaling yn Kubernetes en hoe't se se effektyf kinne brûke
  2. Kubernetes yn 'e geast fan piraterij mei in sjabloan foar ymplemintaasje.
  3. Us Telegram-kanaal oer digitale transformaasje.

Boarne: www.habr.com

Add a comment