Netwerk load balancer argitektuur in Yandex.Cloud

Netwerk load balancer argitektuur in Yandex.Cloud
Hallo, ek is Sergey Elantsev, ek ontwikkel netwerk lasbalanseerder in Yandex.Cloud. Voorheen het ek die ontwikkeling van die L7-balanseerder vir die Yandex-portaal gelei - my kollegas grap dat dit nie saak maak wat ek doen nie, dit blyk 'n balanseerder te wees. Ek sal vir lesers van Habr vertel hoe om die vrag in 'n wolkplatform te bestuur, hoe ons die ideale hulpmiddel sien om hierdie doel te bereik, en hoe ons beweeg na die bou van hierdie hulpmiddel.

Kom ons stel eers 'n paar terme voor:

  • VIP (Virtuele IP) - IP-adres van die balanseerder
  • Bediener, backend, instansie - 'n virtuele masjien met 'n lopende toepassing
  • RIP (Real IP) - bediener IP-adres
  • Healthcheck - bedienergereedheidskontrole
  • Beskikbaarheidsone, AZ - geïsoleerde infrastruktuur in die datasentrum
  • Streek - 'n samesmelting van verskillende AZ'e

Lasbalanseerders los drie hooftake op: hulle voer die balansering self uit, verbeter die fouttoleransie van die diens en vereenvoudig die skaal daarvan. Foutverdraagsaamheid word verseker deur outomatiese verkeersbestuur: die balanseerder monitor die toestand van die toepassing en sluit gevalle van balansering uit wat nie die lewendheidstoets geslaag het nie. Skaal word verskaf deur eenvormige vragverspreiding oor gevalle, sowel as die opdatering van die lys van gevalle op die vlieg. As die balansering nie eens genoeg is nie, sal sommige van die gevalle bo hul gesondheidsperk gelaai word en die diens sal minder betroubaar word.

'n Lasbalanseerder word dikwels geklassifiseer deur die protokollaag van die OSI-model waarop dit loop. Die Cloud Balancer werk by die TCP-laag, wat ooreenstem met die vierde laag, L4.

Kom ons gaan aan na 'n oorsig van die argitektuur van die Wolkbalanseerder. Ons sal die vlak van detail geleidelik verhoog. Ons verdeel die balanseerderkomponente in drie klasse. Die konfigurasievlakklas is verantwoordelik vir gebruikersinteraksie en stoor die teikentoestand van die stelsel. Die beheervlak stoor die huidige toestand van die stelsel en bestuur stelsels vanaf die datavlakklas, wat direk verantwoordelik is vir die lewering van verkeer van kliënte na jou gevalle.

datavlak

Verkeer gaan na duur toestelle wat grensrouters genoem word. Om fouttoleransie in een datasentrum te verhoog, werk verskeie sulke toestelle gelyktydig. Dan kom die verkeer na balanseerders, wat enige uitsaai-IP-adres aan alle AZ'e aankondig via BGP vir kliënte. 

Netwerk load balancer argitektuur in Yandex.Cloud

Verkeer word oor ECMP versend - dit is 'n roetestrategie, waarvolgens daar verskeie ewe goeie roetes na die teiken kan wees (in ons geval sal die bestemmings-IP-adres die teiken wees) en pakkies kan deur enige van hulle gestuur word. Ons ondersteun ook werk in verskeie beskikbaarheidsones volgens die volgende skema: ons kondig die adres in elk van die sones aan, die verkeer gaan die naaste een binne en gaan nie verder as dit nie. Verder in die pos gaan ons van nader kyk na wat met verkeer gebeur.

konfigurasie-vliegtuig

 
Die sleutelkomponent van die konfigurasievlak is die API, waardeur die hoofbewerkings met balanseerders uitgevoer word: skep, verwydering, verandering van die samestelling van gevalle, verkryging van die resultate van gesondheidsondersoeke, ens. Aan die een kant is dit 'n REST API, en aan die ander kant gebruik ons ​​baie dikwels die raamwerk in die Wolk gRPC, so ons "vertaal" REST na gRPC en gaan voort om net gRPC te gebruik. Enige versoek lei tot die skepping van 'n reeks asynchrone idempotente take wat op die gemeenskaplike poel van Yandex.Cloud-werkers loop. Take is so geskryf dat dit enige tyd opgeskort en dan weer begin kan word. Dit verseker skaalbaarheid, herhaalbaarheid en aantekening van bedrywighede.

Netwerk load balancer argitektuur in Yandex.Cloud

As gevolg hiervan sal die taak van die API 'n versoek aan die diensbeheerder van die balanseerders rig, wat in Go geskryf is. Hy kan balanseerders byvoeg en verwyder, die samestelling van backends en instellings verander. 

Netwerk load balancer argitektuur in Yandex.Cloud

Die diens stoor sy toestand in Yandex-databasis, 'n verspreide bestuurde databasis wat u binnekort sal kan gebruik. In Yandex.Cloud, soos ons reeds vertel, die hondekos-konsep werk: as ons self van ons dienste gebruik maak, dan sal ons kliënte dit ook graag gebruik. Yandex-databasis is 'n voorbeeld van so 'n konsep. Ons stoor al ons data in YDB, en ons hoef nie daaraan te dink om die databasis in stand te hou en te skaal nie: hierdie probleme is vir ons opgelos, ons gebruik die databasis as 'n diens.

Ons keer terug na die balanseerder kontroleerder. Die taak daarvan is om inligting oor die balanseerder te stoor, die taak om die gereedheid van die virtuele masjien na te gaan, na die gesondheidskontroleerder te stuur.

Gesondheidskontroleerder

Dit ontvang versoeke om die kontrolereëls te verander, stoor dit na YDB, versprei take onder genesingstoets-nodusse en versamel die resultate, wat dan na die databasis gestoor en na die loadbalancer-beheerder gestuur word. Hy stuur op sy beurt 'n versoek om die samestelling van die groepering in die datavlak te verander na die loadbalancer-node, wat ek hieronder sal bespreek.

Netwerk load balancer argitektuur in Yandex.Cloud

Kom ons praat meer oor gesondheidsondersoeke. Hulle kan in verskeie klasse verdeel word. Toetse het verskillende sukseskriteria. TCP-tjeks moet binne 'n vasgestelde tyd 'n verbinding suksesvol tot stand bring. HTTP-kontroles vereis beide 'n suksesvolle verbinding en 'n antwoord met 'n 200-statuskode.

Tjeks verskil ook in die klas van aksie - hulle is aktief en passief. Passiewe kontrole kyk eenvoudig wat met die verkeer gebeur sonder om enige spesiale stappe te doen. Dit werk nie baie goed op L4 nie, want dit hang af van die logika van die hoërlaagprotokolle: op L4 is daar geen inligting oor hoe lank die operasie geneem het en of die beëindiging van die verbinding goed of sleg was nie. Aktiewe tjeks vereis dat die balanseerder versoeke na elke bedienergeval stuur.

Die meeste lasbalanseerders doen self lewendheidskontroles. Ons by die Wolk het besluit om hierdie dele van die stelsel te skei om skaalbaarheid te verbeter. Hierdie benadering sal ons in staat stel om die aantal balanseerders te vermeerder, terwyl die aantal gesondheidskontrole-versoeke aan die diens gehandhaaf word. Kontroles word uitgevoer deur afsonderlike gesondheidsondersoeknodusse, waaroor kontrole-teikens verdeel en herhaal word. U kan nie kontroles vanaf een gasheer doen nie, aangesien dit kan misluk. Dan kry ons nie die toestand van die gevalle wat hy nagegaan het nie. Ons doen kontrole op enige van die gevalle vanaf ten minste drie gesondheidsondersoek-nodusse. Ons verdeel teikens tussen nodusse deur konsekwente hashing-algoritmes te gebruik.

Netwerk load balancer argitektuur in Yandex.Cloud

Skei balansering en gesondheidsondersoek kan tot probleme lei. As die gesondheidstoets-nodus versoeke aan die instansie rig en die balanseerder (wat tans nie verkeer bedien nie) omseil, dan ontstaan ​​'n vreemde situasie: dit lyk of die hulpbron lewendig is, maar die verkeer sal dit nie bereik nie. Ons los hierdie probleem op die volgende manier op: ons is gewaarborg om gesondheidskontrole-verkeer deur balanseerders te begin. Met ander woorde, die skema vir die verskuiwing van pakkies met verkeer van kliënte en van gesondheidsondersoeke verskil minimaal: in beide gevalle sal die pakkies by die balanseerders uitkom, wat hulle aan die teikenhulpbronne sal lewer.

Die verskil is dat kliënte versoeke vir BBP's rig, terwyl gesondheidsondersoeke na elke individuele RIP gaan. Hier ontstaan ​​'n interessante probleem: ons gee ons gebruikers die vermoë om hulpbronne in grys IP-netwerke te skep. Stel jou voor dat daar twee verskillende wolkeienaars is wat hul dienste agter balanseerders versteek het. Elkeen van hulle het hulpbronne op die 10.0.0.1/24 subnet, en met dieselfde adresse. Jy moet hulle op een of ander manier kan onderskei, en hier moet jy in die Yandex.Cloud virtuele netwerktoestel duik. Meer besonderhede kan gevind word in video van die about:cloud-geleentheid, Dit is nou vir ons belangrik dat die netwerk multilaag is en tonnels daarin het, wat onderskei kan word deur subnet id.

Healthcheck nodusse het toegang tot balanseerders met behulp van sogenaamde kwasi-IPv6-adresse. 'n Kwasi-adres is 'n IPv6-adres wat die gebruiker se IPv4-adres en subnet-ID binne-in het. Die verkeer kom na die balanseerder, wat die hulpbron se IPv4-adres daaruit onttrek, IPv6 met IPv4 vervang en die pakkie na die gebruiker se netwerk stuur.

Omgekeerde verkeer is dieselfde: die balanseerder sien dat die bestemming 'n grys netwerk van gesondheidkontroleurs is, en skakel IPv4 om na IPv6.

VPP is die hart van die datavlak

Die lasbalanseerder word geïmplementeer op die Vector Packet Processing (VPP) tegnologie, 'n Cisco-raamwerk vir pakketverwerking van netwerkverkeer. In ons geval werk die raamwerk bo-op die gebruiker-ruimte netwerk toestel bestuur biblioteek - Data Plane Development Kit (DPDK). Dit bied hoë pakketverwerkingsprestasie: daar is baie minder onderbrekings in die kern, daar is geen kontekswisselaars tussen kernspasie en gebruikersruimte nie. 

VPP gaan selfs verder en druk nog meer werkverrigting uit die stelsel deur pakkies in bondels te kombineer. Prestasiewinste kom uit die aggressiewe gebruik van moderne verwerkerkas. Beide datakas word gebruik (pakkies word deur "vektore" verwerk, die data is naby aan mekaar), en instruksiekas: in VPP volg pakkieverwerking 'n grafiek, in die nodusse waarvan daar funksies is wat een taak verrig.

Die verwerking van IP-pakkies in VPP vind byvoorbeeld in die volgende volgorde plaas: eerstens word die pakkieopskrifte in die ontledingsnodus ontleed, en dan word dit na die nodus gestuur, wat die pakkies verder aanstuur volgens die roeteringstabelle.

Bietjie hardcore. VPP-outeurs kompromitteer nie die gebruik van verwerkerkas, so tipiese pakketvektorverwerkingskode bevat handvektorisering: daar is 'n verwerkingslus wat die situasie verwerk soos "ons het vier pakkies in die tou", dan - dieselfde vir twee, dan - vir een. Voorafhaal-instruksies word dikwels gebruik om data in kas te laai om toegang daartoe in die volgende herhalings te bespoedig.

n_left_from = frame->n_vectors;
while (n_left_from > 0)
{
    vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
    // ...
    while (n_left_from >= 4 && n_left_to_next >= 2)
    {
        // processing multiple packets at once
        u32 next0 = SAMPLE_NEXT_INTERFACE_OUTPUT;
        u32 next1 = SAMPLE_NEXT_INTERFACE_OUTPUT;
        // ...
        /* Prefetch next iteration. */
        {
            vlib_buffer_t *p2, *p3;

            p2 = vlib_get_buffer (vm, from[2]);
            p3 = vlib_get_buffer (vm, from[3]);

            vlib_prefetch_buffer_header (p2, LOAD);
            vlib_prefetch_buffer_header (p3, LOAD);

            CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
            CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
        }
        // actually process data
        /* verify speculative enqueues, maybe switch current next frame */
        vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
                to_next, n_left_to_next,
                bi0, bi1, next0, next1);
    }

    while (n_left_from > 0 && n_left_to_next > 0)
    {
        // processing packets by one
    }

    // processed batch
    vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}

Dus, Healthchecks kry toegang tot VPP oor IPv6, wat hulle in IPv4 verander. Dit word gedoen deur die knooppunt van die grafiek, wat ons algoritmiese NAT noem. Vir omgekeerde verkeer (en vertaling van IPv6 na IPv4) is daar dieselfde algoritmiese NAT-nodus.

Netwerk load balancer argitektuur in Yandex.Cloud

Direkte verkeer van die balanseerder se kliënte gaan deur die nodusse van die grafiek, wat self die balansering uitvoer. 

Netwerk load balancer argitektuur in Yandex.Cloud

Die eerste nodus is taai sessies. Dit bevat 'n hash van 5-tupel vir gevestigde sessies. 5-tuple sluit in die adres en poort van die kliënt vanwaar inligting versend word, die adres en poorte van die hulpbronne wat beskikbaar is om verkeer te ontvang, sowel as die netwerkprotokol. 

Die 5-tuple hash help ons om minder berekeninge te doen in die daaropvolgende konsekwente hash node, en ook beter te hanteer hulpbronlys veranderinge agter die balancer. Wanneer 'n pakkie by die balanseerder aankom waarvoor daar geen sessie is nie, word dit na die konsekwente hashing-nodus gestuur. Dit is waar balansering plaasvind deur konsekwente hashing te gebruik: ons kies 'n hulpbron uit die lys van beskikbare "lewendige" hulpbronne. Vervolgens word die pakkies na die NAT-nodus gestuur, wat eintlik die bestemmingsadres vervang en die kontrolesomme herbereken. Soos u kan sien, volg ons die reëls van VPP - hou daarvan, groepeer soortgelyke berekeninge om die doeltreffendheid van verwerkerkas te verhoog.

Konsekwente hashing

Hoekom het ons dit gekies en waaroor gaan dit? Om mee te begin, oorweeg die vorige taak - kies 'n hulpbron uit die lys. 

Netwerk load balancer argitektuur in Yandex.Cloud

Met inkonsekwente hash word 'n hash uit die inkomende pakkie bereken, en die hulpbron word uit die lys gekies deur die res van hierdie hash te deel deur die aantal hulpbronne. Solank die lys onveranderd bly, werk hierdie skema goed: ons stuur altyd pakkies met dieselfde 5-tuple na dieselfde instansie. As een of ander hulpbron byvoorbeeld opgehou het om op gesondheidsondersoeke te reageer, sal die keuse vir 'n beduidende deel van die hashes verander. Die kliënt sal TCP-verbindings verloor: 'n pakkie wat voorheen instansie A getref het, kan instansie B begin tref, wat nie vertroud is met die sessie vir hierdie pakkie nie.

Konsekwente hashing los die beskryf probleem op. Die maklikste manier om hierdie konsep te verduidelik, is soos volg: stel jou voor dat jy 'n ring het waarheen jy hulpbronne deur hash versprei (byvoorbeeld deur IP:poort). Die keuse van hulpbron is die rotasie van die wiel met 'n hoek, wat bepaal word deur die hash uit die pakket.

Netwerk load balancer argitektuur in Yandex.Cloud

Dit verminder die herverdeling van verkeer wanneer die samestelling van hulpbronne verander word. Die verwydering van 'n hulpbron sal slegs die deel van die konsekwente hash-ring beïnvloed waarop die hulpbron was. Die byvoeging van 'n hulpbron verander ook die verspreiding, maar ons het 'n taai sessienodus wat ons toelaat om nie reeds gevestigde sessies na nuwe hulpbronne oor te skakel nie.

Ons het gekyk na wat gebeur met direkte verkeer tussen die balanseerder en hulpbronne. Kom ons gaan nou met retoerverkeer. Dit volg dieselfde patroon as kontroleverkeer - deur algoritmiese NAT, dit wil sê deur omgekeerde NAT 44 vir kliëntverkeer en deur NAT 46 vir gesondheidskontrole-verkeer. Ons hou by ons eie skema: ons verenig gesondheidskontrole-verkeer en werklike gebruikersverkeer.

Loadbalancer-node en saamgestelde komponente

Die samestelling van balanseerders en hulpbronne in VPP word gerapporteer deur die plaaslike diens - loadbalancer-node. Dit teken in op die gebeurtenisstroom vanaf die loadbalancer-beheerder, kan die verskil bou tussen die huidige VPP-toestand en die teikentoestand wat van die kontroleerder ontvang word. Ons kry 'n geslote stelsel: gebeure van die API kom na die balanseerderbeheerder, wat die take vir die gesondheidkontrole-kontroleerder stel om die "lewendheid" van hulpbronne na te gaan. Dit plaas op sy beurt take in die gesondheidkontrole-node en versamel die resultate, waarna dit aan die balanseerder-beheerder teruggee. Loadbalancer-node teken in op gebeure van die kontroleerder en verander die toestand van die VPP. In so 'n stelsel weet elke diens net wat hy van naburige dienste moet weet. Die aantal verbindings is beperk en ons het die vermoë om verskillende segmente onafhanklik te bedryf en te skaal.

Netwerk load balancer argitektuur in Yandex.Cloud

Watter probleme is vermy?

Al ons beheervliegtuigdienste is in Go geskryf en het goeie skaalbaarheid en betroubaarheid. Go het baie oopbronbiblioteke vir die bou van verspreide stelsels. Ons gebruik GRPC aktief, alle komponente bevat 'n oopbron-implementering van diensontdekking - ons dienste monitor mekaar se prestasie, kan hul samestelling dinamies verander, en ons het dit met GRPC-balansering verbind. Vir metrieke gebruik ons ​​ook 'n oopbron-oplossing. In die datavlak het ons ordentlike werkverrigting en 'n groot marge hulpbronne gekry: dit blyk baie moeilik te wees om 'n staander saam te stel waarop ons kan rus teen die prestasie van VPP, en nie 'n ysternetwerkkaart nie.

Probleme en oplossings

Wat het nie goed gewerk nie? Go het outomatiese geheuebestuur, maar geheuelekkasies vind wel plaas. Die maklikste manier om dit te hanteer, is om goroutines te hardloop en te onthou om hulle te beëindig. Gevolgtrekking: Kyk na die geheueverbruik van Go-programme. Dikwels is 'n goeie aanwyser die aantal goroutines. Daar is 'n pluspunt in hierdie storie: in Go is dit maklik om data oor looptyd te kry - oor geheueverbruik, oor die aantal lopende goroutines en oor baie ander parameters.

Go is ook dalk nie die beste keuse vir funksionele toetse nie. Hulle is nogal verbose, en die standaard "hardloop alles in CI in bondel" benadering is nie baie geskik vir hulle nie. Die feit is dat funksionele toetse meer veeleisend is op hulpbronne, en werklike time-outs kom daarmee voor. As gevolg hiervan kan toetse misluk omdat die SVE besig is met eenheidstoetse. Gevolgtrekking: voer "swaar" toetse afsonderlik van eenheidstoetse uit, waar moontlik. 

'n Mikrodiensgebeurtenisargitektuur is meer ingewikkeld as 'n monoliet: dit is nie baie gerieflik om logs op dosyne verskillende masjiene te gryp nie. Gevolgtrekking: as jy mikrodienste doen, dink dadelik aan opsporing.

Ons planne

Ons sal 'n interne balanseerder, 'n IPv6-balanseerder bekendstel, ondersteuning vir Kubernetes-scenario's byvoeg, voortgaan om ons dienste te versnipper (tans word slegs healthcheck-node en healthcheck-ctrl versplinter), nuwe gesondheidskontroles byvoeg en slimkontrole-aggregasie implementeer. Ons oorweeg die moontlikheid om ons dienste nog meer onafhanklik te maak – sodat hulle nie direk met mekaar kommunikeer nie, maar deur 'n boodskap-tou te gebruik. The Cloud het onlangs 'n SQS-versoenbare diens bekendgestel Yandex-boodskapwaglys.

Onlangs het die publieke vrystelling van Yandex Load Balancer plaasgevind. Leer dokumentasie na die diens, bestuur balanseerders op 'n gerieflike manier vir jou en verhoog die fouttoleransie van jou projekte!

Bron: will.com

Voeg 'n opmerking