Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes
Šis straipsnis padės suprasti, kaip Kubernetes veikia apkrovos balansavimas, kas nutinka keičiant ilgalaikių ryšių mastelį ir kodėl turėtumėte apsvarstyti kliento pusės balansavimą, jei naudojate HTTP/2, gRPC, RSockets, AMQP ar kitus ilgalaikius protokolus. . 

Šiek tiek apie tai, kaip srautas perskirstomas Kubernetes 

„Kubernetes“ teikia dvi patogias programas diegti: Paslaugas ir Diegimą.

Diegiant aprašoma, kaip ir kiek jūsų programos kopijų turėtų veikti bet kuriuo metu. Kiekviena programa yra įdiegta kaip Pod ir jai priskiriamas IP adresas.

Paslaugos yra panašios į apkrovos balansavimo funkciją. Jie skirti srautui paskirstyti keliose grupėse.

Pažiūrėkime, kaip tai atrodo.

  1. Toliau pateiktoje diagramoje galite pamatyti tris tos pačios programos ir apkrovos balansavimo priemonės atvejus:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  2. Apkrovos balansavimo priemonė vadinama paslauga ir jam priskiriamas IP adresas. Bet kokia gaunama užklausa nukreipiama į vieną iš grupių:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  3. Diegimo scenarijus nustato programos egzempliorių skaičių. Beveik niekada nereikės plėstis tiesiai pagal:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  4. Kiekvienam blokui priskiriamas atskiras IP adresas:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

Naudinga galvoti apie paslaugas kaip apie IP adresų rinkinį. Kiekvieną kartą, kai prisijungiate prie paslaugos, iš sąrašo pasirenkamas vienas iš IP adresų ir naudojamas kaip paskirties adresas.

Tai atrodo taip.

  1. Tarnyboje gautas garbanos 10.96.45.152 užklausa:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  2. Paslauga pasirenka vieną iš trijų pod adresų kaip paskirties vietą:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  3. Eismas nukreipiamas į tam tikrą grupę:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

Jei jūsų programą sudaro priekinė ir užpakalinė dalis, turėsite ir paslaugą, ir diegimą.

Kai priekinė programa pateikia užklausą užpakalinei sistemai, jai nereikia tiksliai žinoti, kiek podų aptarnauja galinė programa: gali būti vienas, dešimt ar šimtas.

Be to, priekinė dalis nieko nežino apie užpakalinę sistemą aptarnaujančių podų adresus.

Kai sąsaja pateikia užklausą užpakalinei sistemai, ji naudoja užpakalinės programos IP adresą, kuris nesikeičia.

Štai kaip ji atrodo.

  1. Pagal 1 užklausa vidinio užpakalinio komponento. Užuot pasirinkusi konkretų užpakalinę programą, ji pateikia užklausą paslaugai:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  2. Paslauga pasirenka vieną iš užpakalinių modulių kaip paskirties adresą:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  3. Eismas vyksta iš Pod 1 į Pod 5, pasirinktą paslaugos:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  4. Jaunesnis nei 1 tiksliai nežino, kiek ankščių, pvz., iki 5, yra paslėpta už paslaugos:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

Bet kaip tiksliai paslauga paskirsto užklausas? Atrodo, kad naudojamas balansavimas ratu? Išsiaiškinkime. 

Balansavimas Kubernetes paslaugose

Kubernetes paslaugos neegzistuoja. Paslaugai, kuriai priskirtas IP adresas ir prievadas, nėra proceso.

Tai galite patikrinti prisijungę prie bet kurio klasterio mazgo ir paleisdami komandą netstat -ntlp.

Jūs net negalėsite rasti paslaugai skirto IP adreso.

Paslaugos IP adresas yra valdymo sluoksnyje, valdiklyje ir įrašomas į duomenų bazę – etcd. Tą patį adresą naudoja kitas komponentas – kube-proxy.
Kube-proxy gauna visų paslaugų IP adresų sąrašą ir kiekviename klasterio mazge sukuria iptables taisyklių rinkinį.

Šiose taisyklėse sakoma: „Jei matome paslaugos IP adresą, turime pakeisti užklausos paskirties adresą ir išsiųsti jį į vieną iš podų.

Paslaugos IP adresas naudojamas tik kaip įėjimo taškas ir jo neaptarnauja joks procesas, klausantis to IP adreso ir prievado.

Pažiūrėkime į tai

  1. Apsvarstykite trijų mazgų grupę. Kiekvienas mazgas turi ankštis:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  2. Surištos ankštys, dažytos smėlio spalvos, yra paslaugos dalis. Kadangi paslauga neegzistuoja kaip procesas, ji rodoma pilka spalva:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  3. Pirmoji grupė reikalauja paslaugos ir turi pereiti į vieną iš susijusių grupių:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  4. Bet paslauga neegzistuoja, procesas neegzistuoja. Kaip tai veikia?

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  5. Prieš paliekant užklausą iš mazgo, ji pereina pagal iptables taisykles:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  6. „IPtables“ taisyklės žino, kad paslauga neegzistuoja, ir pakeičia jos IP adresą vienu iš su ta paslauga susijusių blokų IP adresų:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  7. Užklausa kaip paskirties adresas gauna galiojantį IP adresą ir apdorojama įprastai:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  8. Atsižvelgiant į tinklo topologiją, užklausa galiausiai pasiekia bloką:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

Ar gali iptables apkrovos balansas?

Ne, iptables naudojamos filtravimui ir nebuvo skirtos balansavimui.

Tačiau galima parašyti taisyklių rinkinį, kuris veikia kaip pseudobalansas.

Ir būtent tai įgyvendinama „Kubernetes“.

Jei turite tris blokus, kube-proxy parašys šias taisykles:

  1. Pasirinkite pirmąjį antrinį elementą su 33% tikimybe, kitu atveju pereikite prie kitos taisyklės.
  2. Pasirinkite antrąją su 50% tikimybe, kitaip pereikite prie kitos taisyklės.
  3. Toliau pasirinkite trečią.

Dėl šios sistemos kiekvienas ankštis pasirenkamas 33 % tikimybe.

Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

Ir nėra jokios garantijos, kad „Pod 2“ bus pasirinktas kitas po „Pod 1“.

Atkreipti dėmesį: iptables naudoja statistinį modulį su atsitiktiniu pasiskirstymu. Taigi balansavimo algoritmas pagrįstas atsitiktine atranka.

Dabar, kai supratote, kaip veikia paslaugos, pažvelkime į įdomesnius paslaugų scenarijus.

Ilgalaikiai ryšiai Kubernetes nėra keičiami pagal numatytuosius nustatymus

Kiekviena HTTP užklausa iš priekinės dalies į užpakalinę dalį aptarnaujama atskiru TCP ryšiu, kuris atidaromas ir uždaromas.

Jei sąsaja siunčia 100 užklausų per sekundę atgalinei sistemai, tada atidaroma ir uždaroma 100 skirtingų TCP jungčių.

Galite sumažinti užklausų apdorojimo laiką ir apkrovą atidarę vieną TCP ryšį ir naudodami jį visoms paskesnėms HTTP užklausoms.

HTTP protokolas turi funkciją, vadinamą HTTP išlikimas gyvas arba ryšio pakartotinis naudojimas. Šiuo atveju vienas TCP ryšys naudojamas kelioms HTTP užklausoms ir atsakymams siųsti ir gauti:

Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

Ši funkcija neįjungta pagal numatytuosius nustatymus: ir serveris, ir klientas turi būti atitinkamai sukonfigūruoti.

Pati sąranka yra paprasta ir prieinama daugeliui programavimo kalbų ir aplinkų.

Štai keletas nuorodų į pavyzdžius įvairiomis kalbomis:

Kas atsitiks, jei „Kubernetes“ paslaugoje naudosime „Keep-alive“?
Tarkime, kad ir priekinė, ir užpakalinė dalis palaiko gyvavimo išsaugojimą.

Turime vieną priekinės dalies kopiją ir tris užpakalinės dalies kopijas. Frontend pateikia pirmąją užklausą ir atidaro TCP ryšį su užpakaline sistema. Užklausa pasiekia tarnybą, vienas iš užpakalinių modulių pasirenkamas kaip paskirties adresas. Užpakalinė programa siunčia atsakymą, o priekinė programa jį gauna.

Skirtingai nuo įprastos situacijos, kai TCP ryšys uždaromas gavus atsakymą, dabar jis yra atviras tolesnėms HTTP užklausoms.

Kas atsitiks, jei priekinė programa siunčia daugiau užklausų į galinę dalį?

Norint persiųsti šias užklausas, bus naudojamas atviras TCP ryšys, visos užklausos bus nukreiptos į tą pačią užklausą, kur buvo išsiųsta pirmoji užklausa.

Ar iptables neturėtų perskirstyti srauto?

Ne šiuo atveju.

Kai sukuriamas TCP ryšys, jis pereina per iptables taisykles, kurios pasirenka konkrečią vidinę programą, į kurią bus nukreiptas srautas.

Kadangi visos vėlesnės užklausos yra jau atidarytame TCP ryšyje, iptables taisyklės nebekviečiamos.

Pažiūrėkime, kaip tai atrodo.

  1. Pirmasis blokas siunčia užklausą tarnybai:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  2. Jau žinai, kas bus toliau. Paslauga neegzistuoja, tačiau yra iptables taisyklės, kurios apdoros užklausą:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  3. Vienas iš galinių grupių bus pasirinktas kaip paskirties adresas:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  4. Prašymas pasiekia ankštį. Šiuo metu tarp dviejų blokų bus sukurtas nuolatinis TCP ryšys:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  5. Bet kokia paskesnė užklausa iš pirmojo bloko bus vykdoma per jau užmegztą ryšį:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

Rezultatas yra greitesnis atsako laikas ir didesnis pralaidumas, bet jūs prarandate galimybę keisti fono mastelį.

Net jei užpakalinėje programoje yra du blokai, nuolatinis ryšys, srautas visada nukreipiamas į vieną iš jų.

Ar tai galima pataisyti?

Kadangi „Kubernetes“ nežino, kaip subalansuoti nuolatinius ryšius, ši užduotis tenka jums.

Paslaugos yra IP adresų ir prievadų, vadinamų galutiniais taškais, rinkinys.

Jūsų programa gali gauti galinių taškų sąrašą iš paslaugos ir nuspręsti, kaip paskirstyti užklausas tarp jų. Galite atidaryti nuolatinį ryšį su kiekvienu bloku ir subalansuoti užklausas tarp šių jungčių naudodami apvalų ryšį.

Arba taikykite daugiau sudėtingi balansavimo algoritmai.

Kliento kodas, atsakingas už balansavimą, turėtų atitikti šią logiką:

  1. Gaukite galinių taškų sąrašą iš paslaugos.
  2. Atidarykite nuolatinį kiekvieno galutinio taško ryšį.
  3. Kai reikia pateikti užklausą, naudokite vieną iš atvirų jungčių.
  4. Reguliariai atnaujinkite galinių taškų sąrašą, kurkite naujus arba uždarykite senus nuolatinius ryšius, jei sąrašas pasikeičia.

Štai kaip jis atrodys.

  1. Vietoj to, kad pirmoji grupė siųstų užklausą tarnybai, galite subalansuoti užklausas kliento pusėje:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  2. Turite parašyti kodą, kuris klausia, kurios ankštys yra paslaugos dalis:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  3. Kai turėsite sąrašą, išsaugokite jį kliento pusėje ir naudokite jį prisijungdami prie blokų:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

  4. Jūs esate atsakingi už apkrovos balansavimo algoritmą:

    Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

Dabar kyla klausimas: ar ši problema taikoma tik HTTP nuolatiniam gyvavimui?

Kliento pusės apkrovos balansavimas

HTTP nėra vienintelis protokolas, galintis naudoti nuolatinius TCP ryšius.

Jei jūsų programa naudoja duomenų bazę, TCP ryšys neatsidaro kiekvieną kartą, kai reikia pateikti užklausą arba gauti dokumentą iš duomenų bazės. 

Vietoj to atidaromas ir naudojamas nuolatinis TCP ryšys su duomenų baze.

Jei jūsų duomenų bazė yra įdiegta Kubernetes ir prieiga teikiama kaip paslauga, susidursite su tomis pačiomis problemomis, aprašytomis ankstesniame skyriuje.

Viena duomenų bazės kopija bus įkelta labiau nei kitos. „Kube-proxy“ ir „Kubernetes“ nepadės subalansuoti ryšius. Turite pasirūpinti, kad užklausos būtų suderintos su savo duomenų baze.

Priklausomai nuo to, kurią biblioteką naudojate prisijungdami prie duomenų bazės, galite turėti skirtingas šios problemos sprendimo parinktis.

Toliau pateikiamas prieigos prie MySQL duomenų bazės klasterio iš Node.js pavyzdys:

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

Yra daug kitų protokolų, kurie naudoja nuolatinius TCP ryšius:

  • „WebSockets“ ir apsaugotos „WebSockets“.
  • Http / 2
  • grRPC
  • RSockets
  • AMQP

Jūs jau turėtumėte būti susipažinę su daugeliu šių protokolų.

Bet jei šie protokolai tokie populiarūs, kodėl nėra standartizuoto balansavimo sprendimo? Kodėl reikia keisti kliento logiką? Ar yra vietinis „Kubernetes“ sprendimas?

„Kube-proxy“ ir „iptables“ yra sukurti taip, kad apimtų dažniausiai pasitaikančius naudojimo atvejus diegiant „Kubernetes“. Tai patogumui.

Jei naudojate žiniatinklio paslaugą, kuri atskleidžia REST API, jums pasisekė – šiuo atveju nuolatiniai TCP ryšiai nenaudojami, galite naudoti bet kurią „Kubernetes“ paslaugą.

Bet kai pradėsite naudoti nuolatinius TCP ryšius, turėsite sugalvoti, kaip tolygiai paskirstyti apkrovą visose sistemose. Kubernetes nėra paruoštų sprendimų šiam atvejui.

Tačiau tikrai yra galimybių, kurios gali padėti.

Ilgalaikių ryšių subalansavimas Kubernetes mieste

„Kubernetes“ yra keturių tipų paslaugos:

  1. „ClusterIP“
  2. „NodePort“
  3. „LoadBalancer“
  4. Be galvos

Pirmosios trys paslaugos veikia remiantis virtualiu IP adresu, kurį kube-proxy naudoja iptables taisyklėms kurti. Tačiau pagrindinis visų paslaugų pagrindas yra begalvė paslauga.

Paslauga be galvos neturi jokio su ja susijusio IP adreso ir suteikia tik mechanizmą, leidžiantį nuskaityti IP adresų sąrašą ir su ja susietų blokų (galinių taškų) prievadus.

Visos paslaugos yra pagrįstos paslauga be galvos.

„ClusterIP“ paslauga yra be galvos su kai kuriais papildymais: 

  1. Valdymo sluoksnis priskiria jam IP adresą.
  2. Kube-proxy generuoja būtinas iptables taisykles.

Tokiu būdu galite nepaisyti „kube-proxy“ ir tiesiogiai naudoti galinių taškų sąrašą, gautą iš begalinės paslaugos, norėdami subalansuoti programą.

Bet kaip galime pridėti panašią logiką visoms klasteryje įdiegtoms programoms?

Jei jūsų programa jau įdiegta, ši užduotis gali atrodyti neįmanoma. Tačiau yra alternatyvus variantas.

Service Mesh jums padės

Tikriausiai jau pastebėjote, kad kliento pusės apkrovos balansavimo strategija yra gana standartinė.

Kai programa paleidžiama, ji:

  1. Gauna IP adresų sąrašą iš paslaugos.
  2. Atidaro ir prižiūri ryšio baseiną.
  3. Periodiškai atnaujina telkinį pridėdama arba pašalindama galinius taškus.

Kai programa nori pateikti užklausą, ji:

  1. Pasirenka galimą ryšį, naudodamas tam tikrą logiką (pvz., „round-robin“).
  2. Vykdo prašymą.

Šie veiksmai tinka ir WebSockets, ir gRPC, ir AMQP ryšiams.

Galite atskirti šią logiką į atskirą biblioteką ir naudoti ją savo programose.

Tačiau vietoj to galite naudoti paslaugų tinklelius, pvz., Istio arba Linkerd.

„Service Mesh“ papildo jūsų programą tokiu procesu, kuris:

  1. Automatiškai ieško paslaugų IP adresų.
  2. Tikrina ryšius, pvz., WebSockets ir gRPC.
  3. Subalansuoja užklausas naudodamas teisingą protokolą.

„Service Mesh“ padeda valdyti srautą klasterio viduje, tačiau tam reikia daug išteklių. Kitos parinktys yra naudoti trečiųjų šalių bibliotekas, pvz., „Netflix Ribbon“, arba programuojamus tarpinius serverius, tokius kaip „Envoy“.

Kas atsitiks, jei nepaisysite balansavimo problemų?

Galite pasirinkti nenaudoti apkrovos balansavimo ir vis tiek nepastebėti jokių pakeitimų. Pažvelkime į keletą darbo scenarijų.

Jei turite daugiau klientų nei serverių, tai nėra tokia didelė problema.

Tarkime, kad yra penki klientai, kurie prisijungia prie dviejų serverių. Net jei balansavimo nėra, bus naudojami abu serveriai:

Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

Ryšiai gali būti paskirstyti netolygiai: galbūt keturi klientai prisijungę prie to paties serverio, bet yra didelė tikimybė, kad bus naudojami abu serveriai.

Problematiškesnis yra priešingas scenarijus.

Jei turite mažiau klientų ir daugiau serverių, jūsų ištekliai gali būti nepakankamai išnaudoti ir atsiras potenciali kliūtis.

Tarkime, yra du klientai ir penki serveriai. Geriausiu atveju bus du nuolatiniai ryšiai su dviem serveriais iš penkių.

Likę serveriai neveiks:

Apkrovos balansavimas ir ilgalaikių ryšių keitimas Kubernetes

Jei šie du serveriai negali apdoroti klientų užklausų, horizontalus mastelio keitimas nepadės.

išvada

„Kubernetes“ paslaugos yra sukurtos veikti daugelyje standartinių žiniatinklio programų scenarijų.

Tačiau pradėjus dirbti su taikomųjų programų protokolais, kurie naudoja nuolatinius TCP ryšius, pvz., duomenų bazėmis, gRPC ar WebSockets, paslaugos nebetinka. „Kubernetes“ nepateikia vidinių nuolatinių TCP ryšių balansavimo mechanizmų.

Tai reiškia, kad turite rašyti programas atsižvelgdami į kliento pusės balansą.

Vertimą paruošė komanda Kubernetes aaS iš Mail.ru.

Ką dar skaityti šia tema:

  1. Trys automatinio mastelio keitimo lygiai „Kubernetes“ ir kaip juos efektyviai naudoti
  2. Kubernetes piratavimo dvasia su įgyvendinimo šablonu.
  3. Mūsų telegramos kanalas apie skaitmeninę transformaciją.

Šaltinis: www.habr.com

Добавить комментарий