Arsjitektuer fan in netwurk load balancer yn Yandex.Cloud

Arsjitektuer fan in netwurk load balancer yn Yandex.Cloud
Hallo, ik bin Sergey Elantsev, ik ûntwikkelje netwurk load balancer yn Yandex.Cloud. Earder lei ik de ûntwikkeling fan 'e L7-balancer foar it Yandex-portaal - kollega's grapke dat wat ik ek doch, it blykt in balancer te wêzen. Ik sil Habr-lêzers fertelle hoe't jo de lading yn in wolkplatfoarm kinne beheare, wat wy sjogge as it ideale ark foar it berikken fan dit doel, en hoe't wy nei it bouwen fan dit ark geane.

Litte wy earst wat termen yntrodusearje:

  • VIP (firtuele IP) - balancer IP-adres
  • Server, backend, bygelyks - in firtuele masine dy't in applikaasje draait
  • RIP (Real IP) - tsjinner IP-adres
  • Healthcheck - kontrolearjen fan tsjinner reeheid
  • Beskikberenssône, AZ - isolearre ynfrastruktuer yn in datasintrum
  • Regio - in uny fan ferskate AZ's

Load balancers losse trije haadtaken op: se fiere de balâns sels út, ferbetterje de fouttolerânsje fan 'e tsjinst en ferienfâldigje har skaalfergrutting. Fouttolerânsje wurdt garandearre troch automatysk ferkearsbehear: de balancer kontrolearret de tastân fan 'e applikaasje en slút eksimplaren út fan balâns dy't de livenesskontrôle net passe. Skaalfergrutting wurdt garandearre troch de lading lykwichtich te ferdielen oer eksimplaren, en ek it bywurkjen fan de list fan eksimplaren op 'e flecht. As de balânsjen net unifoarm genôch is, sille guon fan 'e eksimplaren in lading krije dy't har kapasiteitslimyt grutter is, en de tsjinst sil minder betrouber wurde.

In load balancer wurdt faak klassifisearre troch de protokol laach fan it OSI model dêr't it rint. De Cloud Balancer wurket op it TCP-nivo, wat oerienkomt mei de fjirde laach, L4.

Litte wy trochgean nei in oersjoch fan 'e Cloud balancer-arsjitektuer. Wy sille stadichoan fergrutsje it nivo fan detail. Wy diele de balancer komponinten yn trije klassen. De konfiguraasjeplaneklasse is ferantwurdlik foar brûkersynteraksje en bewarret de doelstatus fan it systeem. It kontrôlefleantúch bewarret de aktuele steat fan it systeem en beheart systemen fan 'e gegevensflakklasse, dy't direkt ferantwurdlik binne foar it leverjen fan ferkear fan kliïnten nei jo eksimplaren.

Data fleantúch

It ferkear komt telâne op djoere apparaten neamd grinsrouters. Om fouttolerânsje te fergrutsjen, wurkje ferskate sokke apparaten tagelyk yn ien datasintrum. Folgjende giet it ferkear nei balancers, dy't elk cast IP-adressen oankundigje oan alle AZ's fia BGP foar kliïnten. 

Arsjitektuer fan in netwurk load balancer yn Yandex.Cloud

Ferkear wurdt oerbrocht fia ECMP - dit is in routingstrategy neffens dêr't d'r ferskate like goede rûtes nei it doel kinne wêze (yn ús gefal sil it doel it bestimmings-IP-adres wêze) en pakketten kinne by elk fan har stjoerd wurde. Wy stypje ek wurk yn ferskate beskikberenssônes neffens it folgjende skema: wy advertearje in adres yn elke sône, ferkear giet nei de tichtstbye en giet net oer syn grinzen. Letter yn 'e post sille wy yn mear detail sjen wat der bart mei ferkear.

Config fleantúch

 
De kaaikomponint fan it konfiguraasjefleantúch is de API, wêrmei't basisoperaasjes mei balancers wurde útfierd: oanmeitsje, wiskje, feroarjen fan 'e gearstalling fan eksimplaren, resultaten fan sûnenskontrôles, ensfh. Oan 'e iene kant is dit in REST API, en oan 'e oare, wy yn 'e Wolk hiel faak brûke it ramt gRPC, dus wy "oersette" REST nei gRPC en dan brûke allinne gRPC. Elk fersyk liedt ta it meitsjen fan in searje asynchrone idempotinte taken dy't wurde útfierd op in mienskiplike pool fan Yandex.Cloud-arbeiders. Taken binne sa skreaun dat se op elk momint ophâlde kinne en dan wer opstart wurde. Dit soarget foar skaalberens, werhelling en logging fan operaasjes.

Arsjitektuer fan in netwurk load balancer yn Yandex.Cloud

As gefolch sil de taak fan 'e API in fersyk meitsje oan' e balancer-tsjinstcontroller, dy't skreaun is yn Go. It kin balancers tafoegje en fuortsmite, de gearstalling fan backends en ynstellingen feroarje. 

Arsjitektuer fan in netwurk load balancer yn Yandex.Cloud

De tsjinst bewarret syn steat yn Yandex Database, in ferspraat behearde databank dy't jo ynkoarten kinne brûke. Yn Yandex.Cloud, lykas wy al fertelde, jildt it konsept foar hûnemat: as wy sels ús tsjinsten brûke, dan sille ús kliïnten se ek graach brûke. Yandex Database is in foarbyld fan de ymplemintaasje fan sa'n konsept. Wy bewarje al ús gegevens yn YDB, en wy hoege net te tinken oer it ûnderhâld en skaalfergrutting fan de databank: dizze problemen binne foar ús oplost, wy brûke de databank as tsjinst.

Litte wy weromgean nei de balancer controller. Syn taak is om ynformaasje oer de balancer te bewarjen en in taak te stjoeren om de reewilligens fan 'e firtuele masine te kontrolearjen nei de sûnenscheckcontroller.

Healthcheck controller

It ûntfangt fersiken om kontrôleregels te feroarjen, bewarret se yn YDB, distribearret taken ûnder healtcheck-knooppunten en aggregearret de resultaten, dy't dan wurde bewarre yn 'e databank en stjoerd nei de loadbalancer-controller. It stjoert op syn beurt in fersyk om de gearstalling fan it kluster yn it gegevensfleantúch te feroarjen nei de loadbalancer-knooppunt, dy't ik hjirûnder sil beprate.

Arsjitektuer fan in netwurk load balancer yn Yandex.Cloud

Litte wy mear prate oer sûnenskontrôles. Se kinne wurde ferdield yn ferskate klassen. Audits hawwe ferskillende súkses kritearia. TCP-kontrôles moatte mei súkses in ferbining meitsje binnen in fêste tiid. HTTP-kontrôles fereaskje sawol in suksesfolle ferbining as in antwurd mei in 200-statuskoade.

Ek, kontrôles ferskille yn 'e klasse fan aksje - se binne aktyf en passyf. Passive kontrôles kontrolearje gewoan wat der bart mei ferkear sûnder spesjale aksje te nimmen. Dit wurket net sa goed op L4, om't it hinget fan 'e logika fan 'e protokollen op heger nivo: op L4 is der gjin ynformaasje oer hoe lang de operaasje duorre of oft de ferbining foltôging goed of min wie. Aktive kontrôles fereaskje de balancer om fersiken te stjoeren nei elke servereksimplaar.

De measte load balancers fiere liveness kontrôles sels. By Cloud hawwe wy besletten om dizze dielen fan it systeem te skieden om skaalberens te fergrutsjen. Dizze oanpak sil ús tastean om it oantal balancers te ferheegjen, wylst it oantal oanfragen foar sûnenscheck nei de tsjinst behâlde. Kontrôles wurde útfierd troch aparte knooppunten foar sûnenskontrôle, wêrby't kontrôledoelen ferdield en replikeare wurde. Jo kinne gjin kontrôles fan ien host útfiere, om't it kin mislearje. Dan krije wy de steat fan 'e gefallen dy't hy kontrolearre net. Wy fiere kontrôles út op ien fan 'e gefallen fan op syn minst trije sûnenscheckknooppunten. Wy snijje de doelen fan kontrôles tusken knopen mei konsekwinte hashing-algoritmen.

Arsjitektuer fan in netwurk load balancer yn Yandex.Cloud

Skiedende balâns en sûnenskontrôle kin liede ta problemen. As de healthcheck-knooppunt oanfragen docht oan it eksimplaar, troch de balancer te omgean (dy't op it stuit gjin ferkear betsjinnet), dan ûntstiet in frjemde situaasje: de boarne liket te libjen, mar it ferkear sil it net berikke. Wy losse dit probleem op dizze manier op: wy wurde garandearre om sûnenscheckferkear te begjinnen fia balancers. Mei oare wurden, it skema foar it ferpleatsen fan pakketten mei ferkear fan kliïnten en fan sûnenskontrôles ferskilt minimaal: yn beide gefallen sille de pakketten de balancers berikke, dy't se leverje oan 'e doelboarnen.

It ferskil is dat kliïnten oanfragen meitsje oan VIP, wylst sûnenskontrôles oanfragen meitsje foar elke yndividuele RIP. In nijsgjirrich probleem ûntstiet hjir: wy jouwe ús brûkers de kâns om middels te meitsjen yn grize IP-netwurken. Litte wy ús foarstelle dat d'r twa ferskillende wolkeeigners binne dy't har tsjinsten ferburgen hawwe efter balancers. Elk fan harren hat boarnen yn it 10.0.0.1/24 subnet, mei deselde adressen. Jo moatte se op ien of oare manier kinne ûnderskiede, en hjir moatte jo dûke yn 'e struktuer fan it firtuele netwurk Yandex.Cloud. It is better om mear details te finen yn fideo fan about: cloud-evenemint, is it wichtich foar ús no dat it netwurk is multi-layered en hat tunnels dy't kin wurde ûnderskieden troch subnet id.

Healthcheck knopen kontakt balancers mei help fan saneamde quasi-IPv6 adressen. In kwasi-adres is in IPv6-adres mei in IPv4-adres en brûker subnet id ynbêde. It ferkear berikt de balancer, dy't it IPv4-boarneadres derút ekstrakt, IPv6 ferfangt mei IPv4 en stjoert it pakket nei it netwurk fan 'e brûker.

It omkearde ferkear giet deselde manier: de balancer sjocht dat de bestimming in griis netwurk is fan sûnenscheckers, en konvertearret IPv4 nei IPv6.

VPP - it hert fan it gegevensfleantúch

De balancer wurdt ymplementearre mei Vector Packet Processing (VPP) technology, in ramt fan Cisco foar batchferwurking fan netwurkferkear. Yn ús gefal wurket it ramt boppe op 'e bibleteek foar behear fan brûkersromte netwurkapparaten - Data Plane Development Kit (DPDK). Dit soarget foar hege prestaasjes fan pakketferwurking: folle minder ûnderbrekkingen komme foar yn 'e kernel, en d'r binne gjin kontekstwikselingen tusken kernelromte en brûkersromte. 

VPP giet noch fierder en squeeze noch mear prestaasjes út it systeem troch it kombinearjen fan pakketten yn batches. De prestaasjeswinsten komme út it agressyf gebrûk fan caches op moderne processors. Beide gegevenscaches wurde brûkt (pakketten wurde ferwurke yn "vectors", de gegevens binne tichtby elkoar) en ynstruksjecaches: yn VPP folget pakketferwurking in grafyk, wêrfan de knopen funksjes befetsje dy't deselde taak útfiere.

Bygelyks, de ferwurking fan IP-pakketten yn VPP bart yn 'e folgjende folchoarder: earst wurde de pakketkoppen yn' e parsearknooppunt parseard, en dan wurde se nei it knooppunt stjoerd, dy't de pakketten fierder trochstjoert neffens routingtabellen.

In bytsje hardcore. De auteurs fan VPP tolerearje gjin kompromissen yn it brûken fan prosessor-caches, dus typyske koade foar it ferwurkjen fan in fektor fan pakketten befettet hânfektorisaasje: d'r is in ferwurkingslus wêryn in situaasje lykas "wy hawwe fjouwer pakketten yn 'e wachtrige" wurdt ferwurke, dan itselde foar twa, dan - foar ien. Prefetch-ynstruksjes wurde faak brûkt om gegevens yn caches te laden om de tagong ta har te rapperjen yn folgjende iteraasjes.

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);
}

Dat, Healthchecks prate oer IPv6 nei de VPP, dy't se feroaret yn IPv4. Dit wurdt dien troch in knooppunt yn 'e grafyk, dy't wy algoritmyske NAT neame. Foar reverse ferkear (en konverzje fan IPv6 nei IPv4) is d'r deselde algoritmyske NAT-knooppunt.

Arsjitektuer fan in netwurk load balancer yn Yandex.Cloud

Direkt ferkear fan 'e balancer-kliïnten giet troch de grafknooppunten, dy't de balâns sels útfiere. 

Arsjitektuer fan in netwurk load balancer yn Yandex.Cloud

De earste knooppunt is kleverige sesjes. It bewarret de hash fan 5-tup foar fêststelde sesjes. 5-tuple omfettet it adres en de haven fan 'e kliïnt wêrfan ynformaasje wurdt oerdroegen, it adres en havens fan boarnen beskikber foar it ûntfangen fan ferkear, lykas it netwurkprotokol. 

De 5-tuple hash helpt ús om minder berekkeningen út te fieren yn 'e folgjende konsekwinte hashing knooppunt, en ek better omgean mei boarnelistwizigingen efter de balancer. As in pakket dêr't gjin sesje foar komt by de balancer, wurdt it stjoerd nei it konsekwinte hashingknooppunt. Dit is wêr't balânsjen foarkomt mei konsekwint hashing: wy selektearje in boarne út 'e list mei beskikbere "live" boarnen. Dêrnei wurde de pakketten stjoerd nei de NAT-knooppunt, dy't it bestimmingsadres eins ferfangt en de kontrôlesummen opnij berekkent. Sa't jo sjen kinne, folgje wy de regels fan VPP - like to like, groepearje ferlykbere berekkeningen om de effisjinsje fan prosessor-caches te ferheegjen.

Konsekwint hashing

Wêrom hawwe wy it keazen en wat is it sels? Litte wy earst de foarige taak beskôgje - in boarne selektearje út 'e list. 

Arsjitektuer fan in netwurk load balancer yn Yandex.Cloud

Mei inkonsistinte hashing wurdt de hash fan it ynkommende pakket berekkene, en in boarne wurdt selektearre út 'e list troch de rest fan dizze hash te dielen troch it oantal boarnen. Salang't de list net feroaret, wurket dit skema goed: wy stjoere altyd pakketten mei deselde 5-tuple nei deselde eksimplaar. As, bygelyks, guon boarne stoppe te reagearjen op sûnenskontrôles, dan sil foar in signifikant diel fan 'e hashes de kar feroarje. De TCP-ferbiningen fan 'e kliïnt sille ferbrutsen wurde: in pakket dat earder eksimplaar A berikte kin eksimplaar B begjinne te berikken, dat net bekend is mei de sesje foar dit pakket.

Konsekwint hashing lost it beskreaune probleem op. De maklikste manier om dit konsept te ferklearjen is dit: stel jo foar dat jo in ring hawwe wêr't jo boarnen troch hash (bygelyks troch IP: haven) fersprieden. Selektearje in boarne is it draaien fan it tsjil troch in hoeke, dat wurdt bepaald troch de hash fan it pakket.

Arsjitektuer fan in netwurk load balancer yn Yandex.Cloud

Dit minimalisearret ferkearsferdieling as de gearstalling fan boarnen feroaret. It wiskjen fan in boarne sil allinnich beynfloedzje it diel fan 'e konsekwint hashing ring dêr't de boarne wie leit. It tafoegjen fan in boarne feroaret ek de distribúsje, mar wy hawwe in kleverige sesjeknooppunt, wêrtroch't wy al fêststelde sesjes net kinne wikselje nei nije boarnen.

Wy seagen wat der bart mei direkt ferkear tusken de balancer en middels. Litte wy no sjen nei weromferkear. It folget itselde patroan as kontrôleferkear - fia algoritmyske NAT, dat is, troch reverse NAT 44 foar kliïntferkear en fia NAT 46 foar sûnenscheckferkear. Wy hâlde ús oan ús eigen skema: wy ferienigje sûnenskontrôlesferkear en echt brûkersferkear.

Loadbalancer-knooppunt en gearstalde komponinten

De gearstalling fan balancers en boarnen yn VPP wurdt rapportearre troch de lokale tsjinst - loadbalancer-node. It abonnearret op de stream fan eveneminten fan 'e loadbalancer-controller en is yn steat om it ferskil te plotjen tusken de hjoeddeistige VPP-tastân en de doelstatus ûntfongen fan 'e controller. Wy krije in sletten systeem: eveneminten fan 'e API komme nei de balancer-controller, dy't taken oan' e healthcheck-controller tawize om de "libbenens" fan boarnen te kontrolearjen. Dat jout op syn beurt taken ta oan 'e sûnenscheck-knooppunt en aggregearret de resultaten, wêrnei't it se werom stjoert nei de balancer-controller. Loadbalancer-node abonnearret op eveneminten fan 'e controller en feroaret de steat fan' e VPP. Yn sa'n systeem wit elke tsjinst allinich wat nedich is oer oanbuorjende tsjinsten. It oantal ferbinings is beheind en wy hawwe de mooglikheid om ferskate segminten ûnôfhinklik te operearjen en te skaaljen.

Arsjitektuer fan in netwurk load balancer yn Yandex.Cloud

Hokker problemen waarden foarkommen?

Al ús tsjinsten yn it kontrôlefleantúch binne skreaun yn Go en hawwe goede skaalfergrutting en betrouberens. Go hat in protte iepen boarne bibleteken foar it bouwen fan ferspraat systemen. Wy brûke aktyf GRPC, alle komponinten befetsje in iepen boarne ymplemintaasje fan tsjinstûntdekking - ús tsjinsten kontrolearje inoars prestaasjes, kinne har komposysje dynamysk feroarje, en wy hawwe dit keppele oan GRPC-balancing. Foar metriken brûke wy ek in iepen boarne-oplossing. Yn it gegevensfleantúch krigen wy fatsoenlike prestaasjes en in grutte boarnereserve: it die bliken dat it heul lestich wie om in stand te sammeljen wêrop wy kinne fertrouwe op 'e prestaasjes fan in VPP, ynstee fan in izeren netwurkkaart.

Problemen en oplossings

Wat wurke net sa goed? Go hat automatysk ûnthâld behear, mar ûnthâld lekken noch barre. De maklikste manier om har te behanneljen is om goroutines te rinnen en te ûnthâlden om se te beëinigjen. Takeaway: Besjoch it ûnthâldferbrûk fan jo Go-programma's. Faak is in goede yndikator it oantal goroutines. D'r is in plus yn dit ferhaal: yn Go is it maklik om runtimegegevens te krijen - ûnthâldferbrûk, it oantal rinnende goroutines en in protte oare parameters.

Ek is Go miskien net de bêste kar foar funksjonele tests. Se binne frij verbose, en de standert oanpak fan "it útfiere alles yn CI yn in batch" is net hiel geskikt foar harren. It feit is dat funksjonele tests mear boarne-easkende binne en echte time-outs feroarsaakje. Hjirtroch kinne testen mislearje om't de CPU dwaande is mei ienheidstests. Konklúzje: As it mooglik is, útfiere "swiere" tests apart fan ienheidstests. 

Microservice evenemint arsjitektuer is komplekser as in monolith: it sammeljen fan logs op tsientallen ferskillende masines is net hiel handich. Konklúzje: as jo mikrotsjinsten meitsje, tink dan daliks oer tracing.

Us plannen

Wy sille in ynterne balancer lansearje, in IPv6 balancer, stipe taheakje foar Kubernetes-skripts, trochgean mei it sjitten fan ús tsjinsten (op it stuit wurde allinich healthcheck-node en healthcheck-ctrl ferdield), nije sûnenskontrôles tafoegje, en ek tûke aggregation fan kontrôles ymplementearje. Wy beskôgje de mooglikheid om ús tsjinsten noch selsstanniger te meitsjen - sadat se net direkt mei elkoar kommunisearje, mar mei in berjochtwachtrige. In SQS-kompatibele tsjinst is koartlyn ferskynd yn 'e wolk Yandex Berjochtwachtrige.

Koartlyn fûn de iepenbiere frijlitting fan Yandex Load Balancer plak. Ferkenne dokumintaasje oan 'e tsjinst, beheare balancers op in manier dy't jo handich is en fergrutsje de skuldtolerânsje fan jo projekten!

Boarne: www.habr.com

Add a comment