Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes
Ĉi tiu artikolo helpos vin kompreni kiel funkcias ŝarĝoekvilibro en Kubernetes, kio okazas dum skalado de longdaŭraj konektoj, kaj kial vi devus konsideri klientflankan ekvilibron se vi uzas HTTP/2, gRPC, RSockets, AMQP aŭ aliajn longdaŭrajn protokolojn. . 

Iom pri kiel trafiko estas redistribuita en Kubernetes 

Kubernetes provizas du oportunajn abstraktaĵojn por disfaldi aplikaĵojn: Servoj kaj Deplojoj.

Deplojoj priskribas kiel kaj kiom da kopioj de via aplikaĵo devus funkcii samtempe. Ĉiu aplikaĵo estas deplojita kiel Pod kaj ricevas IP-adreson.

Servoj estas similaj en funkcio al ŝarĝbalancilo. Ili estas dizajnitaj por distribui trafikon tra multoblaj podoj.

Ni vidu kiel ĝi aspektas.

  1. En la malsupra diagramo vi povas vidi tri okazojn de la sama aplikaĵo kaj ŝarĝbalancilo:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  2. La ŝarĝbalancilo nomiĝas Servo kaj ricevas IP-adreson. Ĉiu envenanta peto estas redirektita al unu el la podoj:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  3. La deploja scenaro determinas la nombron da okazoj de la aplikaĵo. Vi preskaŭ neniam devos vastiĝi rekte sub:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  4. Ĉiu podo ricevas sian propran IP-adreson:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

Estas utile pensi pri servoj kiel kolekto de IP-adresoj. Ĉiufoje kiam vi aliras la servon, unu el la IP-adresoj estas elektita el la listo kaj uzata kiel la cela adreso.

Ĝi aspektas tiel.

  1. Buklo 10.96.45.152 peto estas ricevita al la servo:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  2. La servo elektas unu el tri pod-adresoj kiel cellokon:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  3. Trafiko estas redirektita al specifa podo:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

Se via aplikaĵo konsistas el fasado kaj backend, tiam vi havos kaj servon kaj deplojon por ĉiu.

Kiam la fasado faras peton al la backend, ĝi ne bezonas scii precize kiom da podoj servas la backend: povus esti unu, dek aŭ cent.

Ankaŭ, la fasado scias nenion pri la adresoj de la podoj servantaj la backend.

Kiam la fasado faras peton al la backend, ĝi uzas la IP-adreson de la backend-servo, kiu ne ŝanĝiĝas.

Jen kiel ĝi aspektas.

  1. Sub 1 petoj la interna backend komponanto. Anstataŭ elekti specifan por la backend, ĝi faras peton al la servo:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  2. La servo elektas unu el la backend pods kiel la cela adreso:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  3. Trafiko iras de Pod 1 al Pod 5, elektita de la servo:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  4. Sub 1 ne scias precize kiom da kapsuloj kiel sub 5 estas kaŝitaj malantaŭ la servo:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

Sed kiel precize la servo distribuas petojn? Ŝajnas, ke cirkla-subskribolista ekvilibro estas uzata? Ni eltrovu ĝin. 

Ekvilibro en Kubernetes-servoj

Kubernetes-servoj ne ekzistas. Ne ekzistas procezo por la servo al kiu estas asignita IP-adreso kaj haveno.

Vi povas kontroli ĉi tion ensalutante en iu ajn nodo en la areto kaj rulante la komandon netstat -ntlp.

Vi eĉ ne povos trovi la IP-adreson asignitan al la servo.

La IP-adreso de la servo situas en la kontroltavolo, en la regilo, kaj registrita en la datumbazo - ktp. La sama adreso estas uzata de alia komponanto - kube-proxy.
Kube-proxy ricevas liston de IP-adresoj por ĉiuj servoj kaj generas aron de iptables-reguloj sur ĉiu nodo en la areto.

Ĉi tiuj reguloj diras: "Se ni vidas la IP-adreson de la servo, ni devas modifi la cel-adreson de la peto kaj sendi ĝin al unu el la podoj."

La servo IP-adreso estas uzata nur kiel enirpunkto kaj ne estas servata de iu ajn procezo aŭskultanta tiun IP-adreson kaj havenon.

Ni rigardu ĉi tion

  1. Konsideru areton de tri nodoj. Ĉiu nodo havas podojn:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  2. Ligitaj guŝoj pentritaj flavgrizaj estas parto de la servo. Ĉar la servo ne ekzistas kiel procezo, ĝi estas montrita en griza:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  3. La unua podo petas servon kaj devas iri al unu el la rilataj podoj:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  4. Sed la servo ne ekzistas, la procezo ne ekzistas. Kiel ĝi funkcias?

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  5. Antaŭ ol la peto forlasas la nodon, ĝi ekzamenas la regulojn de iptables:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  6. La reguloj de iptables scias, ke la servo ne ekzistas kaj anstataŭigas ĝian IP-adreson per unu el la IP-adresoj de la podoj asociitaj kun tiu servo:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  7. La peto ricevas validan IP-adreson kiel la cel-adreson kaj estas procesita normale:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  8. Depende de la retotopologio, la peto finfine atingas la pod:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

Ĉu iptables povas ŝarĝi ekvilibron?

Ne, iptables estas uzataj por filtri kaj ne estis desegnitaj por ekvilibrigi.

Tamen, eblas skribi aron da reguloj, kiuj funkcias kiel pseŭdo-balancilo.

Kaj ĉi tio estas ĝuste kio estas efektivigita en Kubernetes.

Se vi havas tri podojn, kube-proxy skribos la jenajn regulojn:

  1. Elektu la unuan suban kun probablo de 33%, alie iru al la sekva regulo.
  2. Elektu la duan kun probableco de 50%, alie iru al la sekva regulo.
  3. Elektu la trian sub.

Ĉi tiu sistemo rezultigas, ke ĉiu balgo estas elektita kun probableco de 33%.

Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

Kaj ne estas garantio, ke Pod 2 estos elektita poste post Pod 1.

Примечание: iptables uzas statistikan modulon kun hazarda distribuo. Tiel, la ekvilibra algoritmo estas bazita sur hazarda elekto.

Nun kiam vi komprenas kiel funkcias servoj, ni rigardu pli interesajn servajn scenarojn.

Longvivaj konektoj en Kubernetes ne skalas defaŭlte

Ĉiu HTTP-peto de la fasado al la backend estas servata de aparta TCP-konekto, kiu estas malfermita kaj fermita.

Se la fasado sendas 100 petojn sekundo al la backend, tiam 100 malsamaj TCP-konektoj estas malfermitaj kaj fermitaj.

Vi povas redukti peton prilaborado kaj ŝarĝo malfermante unu TCP-konekton kaj uzante ĝin por ĉiuj postaj HTTP-petoj.

La HTTP-protokolo havas funkcion nomitan HTTP-teni-viva aŭ konektoreuzo. En ĉi tiu kazo, ununura TCP-konekto estas uzata por sendi kaj ricevi plurajn HTTP-petojn kaj respondojn:

Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

Ĉi tiu funkcio ne estas ebligita defaŭlte: kaj la servilo kaj la kliento devas esti agorditaj laŭe.

La aranĝo mem estas simpla kaj alirebla por plej multaj programlingvoj kaj medioj.

Jen kelkaj ligiloj al ekzemploj en malsamaj lingvoj:

Kio okazas se ni uzas keep-alive en Kubernetes-servo?
Ni supozu, ke ambaŭ la fasado kaj la backend subtenas vivaj.

Ni havas unu kopion de la fasado kaj tri kopiojn de la backend. La fasado faras la unuan peton kaj malfermas TCP-konekton al la backend. La peto atingas la servon, unu el la backend pods estas elektita kiel la cela adreso. La backend sendas respondon, kaj la fasado ricevas ĝin.

Male al la kutima situacio kie la TCP-konekto estas fermita post ricevado de respondo, ĝi nun estas konservita malfermita por pliaj HTTP-petoj.

Kio okazas se la fasado sendas pli da petoj al la backend?

Por plusendi ĉi tiujn petojn, malferma TCP-konekto estos uzata, ĉiuj petoj iros al la sama backend kie iris la unua peto.

Ĉu iptables ne devus redistribui la trafikon?

Ne en ĉi tiu kazo.

Kiam TCP-konekto estas kreita, ĝi trapasas iptables-regulojn, kiuj elektas specifan backend kie la trafiko iros.

Ĉar ĉiuj postaj petoj estas sur jam malfermita TCP-konekto, la reguloj de iptables ne plu estas nomitaj.

Ni vidu kiel ĝi aspektas.

  1. La unua pod sendas peton al la servo:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  2. Vi jam scias, kio okazos poste. La servo ne ekzistas, sed ekzistas reguloj de iptables, kiuj prilaboros la peton:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  3. Unu el la malantaŭaj kapsuloj estos elektita kiel la cela adreso:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  4. La peto atingas la balgon. Je ĉi tiu punkto, konstanta TCP-konekto inter la du balgoj estos establita:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  5. Ajna posta peto de la unua pod trairos la jam establitan konekton:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

La rezulto estas pli rapida responda tempo kaj pli alta trairo, sed vi perdas la kapablon grimpi la backend.

Eĉ se vi havas du podojn en la backend, kun konstanta konekto, trafiko ĉiam iros al unu el ili.

Ĉu tio povas esti riparita?

Ĉar Kubernetes ne scias kiel ekvilibrigi konstantajn ligojn, ĉi tiu tasko apartenas al vi.

Servoj estas kolekto de IP-adresoj kaj havenoj nomataj finpunktoj.

Via aplikaĵo povas ricevi liston de finpunktoj de la servo kaj decidi kiel distribui petojn inter ili. Vi povas malfermi konstantan konekton al ĉiu pod kaj ekvilibrigi petojn inter ĉi tiuj konektoj per cirkla-subskribolista.

Aŭ apliki pli kompleksaj ekvilibraj algoritmoj.

La klientflanka kodo, kiu respondecas pri ekvilibro, devus sekvi ĉi tiun logikon:

  1. Akiru liston de finpunktoj de la servo.
  2. Malfermu konstantan konekton por ĉiu finpunkto.
  3. Kiam peto devas esti farita, uzu unu el la malfermitaj konektoj.
  4. Regule ĝisdatigu la liston de finpunktoj, kreu novajn aŭ fermu malnovajn konstantajn konektojn se la listo ŝanĝiĝas.

Jen kiel ĝi aspektos.

  1. Anstataŭ ke la unua pod sendas la peton al la servo, vi povas ekvilibrigi petojn ĉe la klienta flanko:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  2. Vi devas skribi kodon, kiu demandas, kiuj balgoj estas parto de la servo:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  3. Post kiam vi havas la liston, konservu ĝin ĉe la klienta flanko kaj uzu ĝin por konekti al la podoj:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

  4. Vi respondecas pri la ŝarĝbalanca algoritmo:

    Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

Nun la demando ekestas: ĉu ĉi tiu problemo validas nur por HTTP-tenado?

Kliento-flanka ŝarĝoekvilibro

HTTP ne estas la sola protokolo, kiu povas uzi konstantajn TCP-konektojn.

Se via aplikaĵo uzas datumbazon, tiam TCP-konekto ne estas malfermita ĉiufoje kiam vi bezonas fari peton aŭ preni dokumenton el la datumbazo. 

Anstataŭe, konstanta TCP-konekto al la datumbazo estas malfermita kaj uzata.

Se via datumbazo estas deplojita sur Kubernetes kaj aliro estas provizita kiel servo, tiam vi renkontos la samajn problemojn priskribitajn en la antaŭa sekcio.

Unu datumbaza kopio estos pli ŝarĝita ol la aliaj. Kube-proxy kaj Kubernetes ne helpos ekvilibrigi ligojn. Vi devas zorgi ekvilibrigi la demandojn al via datumbazo.

Depende de kiu biblioteko vi uzas por konekti al la datumbazo, vi eble havas malsamajn eblojn por solvi ĉi tiun problemon.

Malsupre estas ekzemplo de aliro al MySQL-datumbaza areto de 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

Estas multaj aliaj protokoloj, kiuj uzas konstantajn TCP-ligojn:

  • WebSockets kaj sekurigitaj WebSockets
  • HTTP / 2
  • gRPC
  • Ringoj
  • AMQP

Vi jam devus koni la plej multajn el ĉi tiuj protokoloj.

Sed se ĉi tiuj protokoloj estas tiel popularaj, kial ne ekzistas normigita ekvilibra solvo? Kial la klienta logiko bezonas ŝanĝiĝi? Ĉu ekzistas denaska solvo de Kubernetes?

Kube-proxy kaj iptables estas dizajnitaj por kovri plej oftajn uzkazojn dum deplojiĝo al Kubernetes. Ĉi tio estas por komforto.

Se vi uzas retservon, kiu elmontras REST-API, vi bonŝancas - ĉi-kaze, konstantaj TCP-konektoj ne estas uzataj, vi povas uzi ajnan Kubernetes-servon.

Sed post kiam vi komencos uzi konstantajn TCP-konektojn, vi devos eltrovi kiel egale distribui la ŝarĝon tra la backends. Kubernetes ne enhavas pretajn solvojn por ĉi tiu kazo.

Tamen, estas certe ebloj kiuj povas helpi.

Ekvilibro de longedaŭraj rilatoj en Kubernetes

Estas kvar specoj de servoj en Kubernetes:

  1. ClusterIP
  2. NodePort
  3. LoadBalancer
  4. Sen kapo

La unuaj tri servoj funkcias surbaze de virtuala IP-adreso, kiu estas uzata de kube-proxy por konstrui iptables-regulojn. Sed la fundamenta bazo de ĉiuj servoj estas senkapa servo.

La senkapa servo ne havas ajnan IP-adreson asociitan kun ĝi kaj nur provizas mekanismon por retrovi liston de IP-adresoj kaj havenoj de la balgoj (finpunktoj) asociitaj kun ĝi.

Ĉiuj servoj baziĝas sur la senkapa servo.

La ClusterIP-servo estas senkapa servo kun kelkaj aldonoj: 

  1. La administra tavolo asignas al ĝi IP-adreson.
  2. Kube-proxy generas la necesajn regulojn de iptables.

Tiel vi povas ignori kube-proxy kaj rekte uzi la liston de finpunktoj akiritaj de la senkapa servo por ŝarĝi ekvilibron de via aplikaĵo.

Sed kiel ni povas aldoni similan logikon al ĉiuj aplikaĵoj deplojitaj en la areto?

Se via aplikaĵo jam estas deplojita, ĉi tiu tasko povas ŝajni neebla. Tamen, ekzistas alternativa opcio.

Servo Mesh helpos vin

Vi verŝajne jam rimarkis, ke la strategio pri ekvilibra ŝarĝo de la kliento estas sufiĉe norma.

Kiam la aplikaĵo komenciĝas, ĝi:

  1. Akiras liston de IP-adresoj de la servo.
  2. Malfermas kaj konservas konektan naĝejon.
  3. Periode ĝisdatigas la naĝejon aldonante aŭ forigante finpunktojn.

Post kiam la aplikaĵo volas fari peton, ĝi:

  1. Elektas disponeblan konekton uzante iun logikon (ekz. round-robin).
  2. Plenumas la peton.

Ĉi tiuj paŝoj funkcias por ambaŭ konektoj WebSockets, gRPC kaj AMQP.

Vi povas apartigi ĉi tiun logikon en apartan bibliotekon kaj uzi ĝin en viaj aplikaĵoj.

Tamen vi povas uzi servajn retojn kiel Istio aŭ Linkerd anstataŭe.

Service Mesh pliigas vian aplikaĵon per procezo, kiu:

  1. Aŭtomate serĉas servon IP-adresojn.
  2. Testas konektojn kiel WebSockets kaj gRPC.
  3. Ekvilibras petojn uzante la ĝustan protokolon.

Service Mesh helpas administri trafikon ene de la areto, sed ĝi estas sufiĉe rimeda. Aliaj opcioj uzas triajn bibliotekojn kiel Netflix Ribbon aŭ programeblajn prokurojn kiel Envoy.

Kio okazas se vi ignoras ekvilibrajn problemojn?

Vi povas elekti ne uzi ŝarĝan ekvilibron kaj ankoraŭ ne rimarki ŝanĝojn. Ni rigardu kelkajn laborscenarojn.

Se vi havas pli da klientoj ol serviloj, ĉi tio ne estas tiom granda problemo.

Ni diru, ke estas kvin klientoj, kiuj konektas al du serviloj. Eĉ se ne ekzistas ekvilibro, ambaŭ serviloj estos uzataj:

Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

Konektoj eble ne estas egale distribuitaj: eble kvar klientoj konektitaj al la sama servilo, sed estas bona ŝanco ke ambaŭ serviloj estos uzataj.

Kio estas pli problema estas la kontraŭa scenaro.

Se vi havas malpli da klientoj kaj pli da serviloj, viaj rimedoj povas esti subutiligitaj kaj ebla proplemkolo aperos.

Ni diru, ke estas du klientoj kaj kvin serviloj. En la plej bona kazo, estos du konstantaj konektoj al du serviloj el kvin.

La ceteraj serviloj estos neaktivaj:

Ŝarĝbalancado kaj skalado longdaŭraj konektoj en Kubernetes

Se ĉi tiuj du serviloj ne povas trakti klientajn petojn, horizontala skalo ne helpos.

konkludo

Kubernetes-servoj estas dezajnitaj por funkcii en la plej multaj normaj retprogramoj.

Tamen, kiam vi komencas labori kun aplikaj protokoloj, kiuj uzas konstantajn TCP-konektojn, kiel datumbazoj, gRPC aŭ WebSockets, servoj ne plu taŭgas. Kubernetes ne disponigas internajn mekanismojn por ekvilibrigi persistajn TCP-ligojn.

Ĉi tio signifas, ke vi devas skribi aplikojn kun klientflanka ekvilibro en menso.

Traduko preparita de la teamo Kubernetes aaS de Mail.ru.

Kion alian legi pri la temo:

  1. Tri niveloj de aŭtoskalo en Kubernetes kaj kiel uzi ilin efike
  2. Kubernetes en la spirito de piratado kun ŝablono por efektivigo.
  3. Nia Telegram-kanalo pri cifereca transformo.

fonto: www.habr.com

Aldoni komenton