Koormuse tasakaalustamine ja pikaealiste ühenduste skaleerimine Kubernetesis
See artikkel aitab teil mõista, kuidas Kuberneteses koormuse tasakaalustamine töötab, mis juhtub pikaealiste ühenduste skaleerimisel ja miks peaksite kaaluma kliendipoolset tasakaalustamist, kui kasutate HTTP/2, gRPC, RSocketsi, AMQP või muid pikaealisi protokolle. .
Natuke sellest, kuidas Kubernetes liiklust ümber jagatakse
Kubernetes pakub rakenduste juurutamiseks kahte mugavat abstraktsiooni: teenused ja juurutused.
Juurutused kirjeldavad, kuidas ja kui palju teie rakenduse eksemplare peaks igal ajahetkel töötama. Iga rakendus juurutatakse Pod-na ja sellele määratakse IP-aadress.
Teenused on funktsioonilt sarnased koormuse tasakaalustajaga. Need on loodud liikluse jaotamiseks mitme kausta vahel.
Vaatame, kuidas see välja näeb.
Alloleval diagrammil näete sama rakenduse ja koormuse tasakaalustaja kolme eksemplari:
Koormuse tasakaalustajat nimetatakse teenuseks ja sellele määratakse IP-aadress. Kõik sissetulevad taotlused suunatakse ümber ühte kaustadest:
Juurutamise stsenaarium määrab rakenduse eksemplaride arvu. Peaaegu kunagi ei pea te otse laiendama:
Igale podile määratakse oma IP-aadress:
Kasulik on mõelda teenustele kui IP-aadresside kogumile. Iga kord, kui teenust kasutate, valitakse loendist üks IP-aadressidest ja seda kasutatakse sihtkoha aadressina.
See näeb välja selline.
Teenindusele saabus curl 10.96.45.152 päring:
Teenus valib sihtkohaks ühe kolmest taskuaadressist:
Liiklus suunatakse ümber kindlasse kausta:
Kui teie rakendus koosneb esi- ja taustaprogrammist, on teil mõlema jaoks nii teenus kui ka juurutus.
Kui kasutajaliides esitab taustaprogrammile päringu, ei pea ta täpselt teadma, mitut kausta taustaprogramm teenindab: neid võib olla üks, kümme või sada.
Samuti ei tea frontend midagi taustaprogrammi teenindavate kaunade aadressidest.
Kui kasutajaliides esitab taustaprogrammile päringu, kasutab see taustateenuse IP-aadressi, mis ei muutu.
Siin on, kuidas see välja.
Alla 1 taotleb sisemist taustakomponenti. Selle asemel, et valida taustaprogrammi jaoks konkreetne, esitab see teenusele päringu:
Teenus valib sihtkoha aadressiks ühe taustamoodulitest:
Liiklus liigub Pod 1-st Pod 5-sse, mille teenus valib:
Alla 1 ei tea täpselt, kui palju alla 5-ga kauneid on teenuse taga peidus:
Aga kuidas teenus päringuid täpselt levitab? Tundub, et kasutatakse ümberringi tasakaalustamist? Selgitame välja.
Tasakaalustamine Kubernetese teenustes
Kubernetese teenuseid pole olemas. Teenuse jaoks, millele on määratud IP-aadress ja port, pole protsessi.
Saate seda kontrollida, logides sisse klastri mis tahes sõlme ja käivitades käsu netstat -ntlp.
Te ei leia isegi teenusele eraldatud IP-aadressi.
Teenuse IP-aadress asub juhtkihis, kontrolleris ja salvestatakse andmebaasi - jne. Sama aadressi kasutab teine komponent - kube-puhverserver.
Kube-puhverserver võtab vastu kõigi teenuste IP-aadresside loendi ja loob iptablesi reeglite komplekti igas klastri sõlmes.
Need reeglid ütlevad: "Kui näeme teenuse IP-aadressi, peame muutma päringu sihtkoha aadressi ja saatma selle ühte kaustadest."
Teenuse IP-aadressi kasutatakse ainult sisenemispunktina ja seda ei teeninda ükski protsess, mis kuulab seda IP-aadressi ja porti.
Vaatame seda.
Vaatleme kolmest sõlmest koosnevat klastrit. Igal sõlmel on kaustad:
Beežiks värvitud seotud kaunad on osa teenusest. Kuna teenust protsessina ei eksisteeri, kuvatakse see hallina:
Esimene pod taotleb teenust ja peab minema ühte seotud kaustadest:
Kuid teenust pole olemas, protsessi pole olemas. Kuidas see töötab?
Enne kui päring sõlmest lahkub, läbib see iptablesi reeglid:
IPtablesi reeglid teavad, et teenust pole olemas, ja asendavad selle IP-aadressi ühe selle teenusega seotud kaustade IP-aadressidega:
Päring saab sihtkoha aadressina kehtiva IP-aadressi ja seda töödeldakse tavapäraselt:
Sõltuvalt võrgu topoloogiast jõuab päring lõpuks kausta:
Kas iptables saab koormustasakaalu?
Ei, iptablesid kasutatakse filtreerimiseks ja need ei ole mõeldud tasakaalustamiseks.
Kui teil on kolm kausta, kirjutab kube-proxy järgmised reeglid:
Valige esimene alam tõenäosusega 33%, vastasel juhul minge järgmise reegli juurde.
Valige teine 50% tõenäosusega, vastasel juhul minge järgmise reegli juurde.
Valige alt kolmas.
Selle süsteemi tulemusel valitakse iga kaust 33% tõenäosusega.
Ja pole mingit garantiid, et Pod 2 valitakse järgmiseks pärast Pod 1.
Märkus: iptables kasutab juhusliku jaotusega statistilist moodulit. Seega põhineb tasakaalustusalgoritm juhuslikul valikul.
Nüüd, kui saate aru, kuidas teenused töötavad, vaatame huvitavamaid teenusestsenaariume.
Pikaealised ühendused Kubernetesis vaikimisi ei skaleerita
Iga HTTP-päring esiprogrammist taustaprogrammi teenindab eraldi TCP-ühendust, mis avatakse ja suletakse.
Kui kasutajaliides saadab taustaprogrammi 100 päringut sekundis, siis avatakse ja suletakse 100 erinevat TCP ühendust.
Saate vähendada päringu töötlemise aega ja koormust, avades ühe TCP-ühenduse ja kasutades seda kõigi järgnevate HTTP-päringute jaoks.
HTTP-protokollil on funktsioon, mida nimetatakse HTTP elushoidmiseks ehk ühenduse taaskasutamiseks. Sel juhul kasutatakse mitme HTTP-päringu ja vastuse saatmiseks ja vastuvõtmiseks ühte TCP-ühendust:
See funktsioon ei ole vaikimisi lubatud: nii server kui ka klient peavad olema vastavalt konfigureeritud.
Seadistamine ise on lihtne ja juurdepääsetav enamiku programmeerimiskeelte ja keskkondade jaoks.
Siin on mõned lingid näidete juurde erinevates keeltes:
Mis juhtub, kui kasutame Kubernetese teenuses elushoidmist?
Oletame, et nii esi- kui ka taustaprogramm toetavad elushoidmist.
Meil on üks koopia esiosast ja kolm koopiat taustaprogrammist. Esiprogramm teeb esimese päringu ja avab TCP-ühenduse taustaprogrammiga. Päring jõuab teenuseni, sihtaadressiks valitakse üks taustamoodulitest. Taustaprogramm saadab vastuse ja esiprogramm võtab selle vastu.
Erinevalt tavapärasest olukorrast, kus TCP-ühendus suletakse pärast vastuse saamist, hoitakse see nüüd avatuna edasiste HTTP-päringute jaoks.
Mis juhtub, kui kasutajaliides saadab taustaprogrammile rohkem päringuid?
Nende päringute edastamiseks kasutatakse avatud TCP ühendust, kõik päringud suunatakse samasse taustaprogrammi, kuhu esimene päring läks.
Kas iptables ei peaks liiklust ümber jaotama?
Sel juhul mitte.
TCP-ühenduse loomisel läbib see iptablesi reegleid, mis valivad konkreetse taustaprogrammi, kuhu liiklus suunatakse.
Kuna kõik järgnevad päringud on juba avatud TCP-ühenduses, siis iptablesi reegleid enam ei kutsuta.
Vaatame, kuidas see välja näeb.
Esimene pod saadab teenusele päringu:
Sa juba tead, mis edasi saab. Teenust pole olemas, kuid päringu töötlemiseks on olemas iptablesi reeglid:
Sihtkoha aadressiks valitakse üks taustamoodulitest:
Taotlus jõuab kaunasse. Sel hetkel luuakse kahe kausta vahel püsiv TCP-ühendus:
Kõik esimesest kaustast tulevad taotlused läbivad juba loodud ühenduse:
Tulemuseks on kiirem reageerimisaeg ja suurem läbilaskevõime, kuid te kaotate võimaluse taustaprogrammi skaleerida.
Isegi kui teil on taustaprogrammis kaks pideva ühendusega kausta, liigub liiklus alati ühele neist.
Kas seda saab parandada?
Kuna Kubernetes ei tea, kuidas püsivaid ühendusi tasakaalustada, langeb see ülesanne teile.
Teenused on IP-aadresside ja portide kogum, mida nimetatakse lõpp-punktideks.
Teie rakendus saab teenusest hankida lõpp-punktide loendi ja otsustada, kuidas päringuid nende vahel jagada. Saate avada püsiva ühenduse iga taskuga ja tasakaalustada nende ühenduste vahelisi taotlusi, kasutades ümberringi.
Nüüd tekib küsimus: kas see probleem kehtib ainult HTTP elushoidmise kohta?
Kliendipoolne koormuse tasakaalustamine
HTTP ei ole ainus protokoll, mis saab kasutada püsivaid TCP-ühendusi.
Kui teie rakendus kasutab andmebaasi, ei avata TCP-ühendust iga kord, kui peate tegema päringu või hankima andmebaasist dokumendi.
Selle asemel avatakse ja kasutatakse püsivat TCP-ühendust andmebaasiga.
Kui teie andmebaas on Kubernetesis juurutatud ja juurdepääs on pakutud teenusena, ilmnevad samad probleemid, mida kirjeldati eelmises jaotises.
Üks andmebaasi koopia laaditakse rohkem kui teised. Kube-puhverserver ja Kubernetes ei aita ühendusi tasakaalustada. Peate hoolitsema päringute tasakaalustamise eest oma andmebaasiga.
Olenevalt sellest, millist teeki andmebaasiga ühenduse loomiseks kasutate, võib teil olla selle probleemi lahendamiseks erinevaid võimalusi.
Allpool on näide MySQL-i andmebaasiklastrile juurdepääsust saidilt 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
On palju teisi protokolle, mis kasutavad püsivaid TCP-ühendusi:
WebSockets ja turvatud WebSockets
HTTP / 2
gRPC
RSocketid
AMQP
Peaksite enamiku nendest protokollidest juba tuttav olema.
Aga kui need protokollid on nii populaarsed, siis miks pole standardiseeritud tasakaalustamislahendust? Miks on vaja kliendiloogikat muuta? Kas on olemas natiivne Kubernetese lahendus?
Kube-puhverserver ja iptables on loodud katma Kubernetesis juurutamisel kõige levinumad kasutusjuhtumid. See on mugavuse huvides.
Kui kasutate veebiteenust, mis paljastab REST API, on teil õnne – sel juhul püsivaid TCP-ühendusi ei kasutata, võite kasutada mis tahes Kubernetese teenust.
Kuid kui hakkate kasutama püsivaid TCP-ühendusi, peate välja mõtlema, kuidas koormust taustaprogrammide vahel ühtlaselt jaotada. Kubernetes ei sisalda selleks puhuks valmislahendusi.
Siiski on kindlasti võimalusi, mis võivad aidata.
Pikaealiste sidemete tasakaalustamine Kubernetes
Kubernetesis on nelja tüüpi teenuseid:
KlastriIP
Sõlme port
Koormuse tasakaalustaja
Peata
Esimesed kolm teenust põhinevad virtuaalsel IP-aadressil, mida kube-puhverserver kasutab iptablesi reeglite koostamiseks. Kuid kõigi teenuste põhialus on peata teenus.
Peata teenusel ei ole sellega seotud ühtegi IP-aadressi ja see pakub ainult mehhanismi IP-aadresside loendi ja sellega seotud kaustade (otspunktide) portide hankimiseks.
Kõik teenused põhinevad peata teenusel.
ClusterIP teenus on peata teenus, millel on mõned täiendused:
Halduskiht määrab sellele IP-aadressi.
Kube-puhverserver genereerib vajalikud iptablesi reeglid.
Nii saate kube-puhverserverit ignoreerida ja oma rakenduse koormuse tasakaalustamiseks kasutada otse peata teenusest saadud lõpp-punktide loendit.
Kuid kuidas saame lisada sarnase loogika kõigile klastris juurutatud rakendustele?
Kui teie rakendus on juba juurutatud, võib see ülesanne tunduda võimatu. Siiski on alternatiivne võimalus.
Service Mesh aitab teid
Tõenäoliselt olete juba märganud, et kliendipoolne koormuse tasakaalustamise strateegia on üsna tavaline.
Kui rakendus käivitub, siis:
Hangi teenusest IP-aadresside loendi.
Avab ja hooldab ühendusbasseini.
Värskendab perioodiliselt basseini lõpp-punkte lisades või eemaldades.
Kui rakendus soovib taotlust esitada, siis:
Valib saadaoleva ühenduse, kasutades mingit loogikat (nt round-robin).
Täidab taotluse.
Need sammud toimivad nii WebSocketsi, gRPC kui ka AMQP ühenduste puhul.
Saate selle loogika eraldada eraldi teegiks ja kasutada seda oma rakendustes.
Selle asemel saate siiski kasutada teenindusvõrke, nagu Istio või Linkerd.
Service Mesh täiendab teie rakendust protsessiga, mis:
Otsib automaatselt teenuse IP-aadresse.
Testib ühendusi, nagu WebSockets ja gRPC.
Tasakaalustab päringud õige protokolli abil.
Service Mesh aitab hallata liiklust klastri sees, kuid see on üsna ressursimahukas. Muud võimalused on kasutada kolmandate osapoolte teeke, nagu Netflix Ribbon, või programmeeritavaid puhverservereid, nagu Envoy.
Mis juhtub, kui te eirate tasakaalustamise probleeme?
Saate koormuse tasakaalustamist mitte kasutada ja siiski ei märka muudatusi. Vaatame mõnda tööstsenaariumi.
Kui teil on rohkem kliente kui servereid, pole see nii suur probleem.
Oletame, et on viis klienti, mis loovad ühenduse kahe serveriga. Isegi kui tasakaalustamist pole, kasutatakse mõlemat serverit:
Ühendused ei pruugi olla ühtlaselt jaotunud: võib-olla neli klienti on ühendatud sama serveriga, kuid on suur võimalus, et mõlemat serverit kasutatakse.
Probleemsem on vastupidine stsenaarium.
Kui teil on vähem kliente ja rohkem servereid, võivad teie ressursid olla alakasutatud ja ilmneda potentsiaalne kitsaskoht.
Oletame, et seal on kaks klienti ja viis serverit. Parimal juhul tekib kaks püsiühendust kahe serveriga viiest.
Ülejäänud serverid on jõude:
Kui need kaks serverit ei saa hakkama kliendi taotlustega, ei aita horisontaalne skaleerimine.
Järeldus
Kubernetese teenused on loodud töötama enamiku standardsete veebirakenduste stsenaariumide puhul.
Kui aga hakkate töötama püsivaid TCP-ühendusi kasutavate rakendusprotokollidega, nagu andmebaasid, gRPC või WebSockets, ei ole teenused enam sobivad. Kubernetes ei paku püsivate TCP-ühenduste tasakaalustamiseks sisemisi mehhanisme.
See tähendab, et peate rakendusi kirjutama kliendipoolset tasakaalustamist silmas pidades.