Yandex.Cloudi vÔrgu koormuse tasakaalustaja arhitektuur

Yandex.Cloudi vÔrgu koormuse tasakaalustaja arhitektuur
Tere, mina olen Sergei Jelantsev, arendan vĂ”rgutasakaalu jaoturit Yandex.Cloudis. Varem juhin ma Yandexi portaali L7-balansseerija arendust — kolleegid naljatavad, et mida iganes ma teen, tuleb tasakaalustaja vĂ€lja. RÀÀgin Habr'i lugejatele, kuidas hallata koormust pilveplatvormil, milline on meie ideaalne vahend selle saavutamiseks ja kuidas liigume selle tööriista loomise suunas.

KÀime esmalt lÀbi mÔned terminid:

  • VIP (Virtuaalne IP) — tasakaalustaja IP-aadress
  • Server, taust, instants — virtuaalne masin, kus töötab rakendus
  • RIP (Reaalne IP) — serveri IP-aadress
  • Healthcheck — serveri valmisoleku kontroll
  • Saadavaloleku tsoon, Availability Zone, AZ — isoleeritud infrastruktuur andmekeskuses
  • Regioon — erinevate AZ-de kogum

Koormustasakaalustajad lahendavad kolm pĂ”hitegevust: nad teostavad tasakaalu ning parandavad teenuse tĂ”rkekindlust ja lihtsustavad selle skaleerimist. TĂ”rkekindlus saavutatakse automaatse liikluse juhtimise kaudu: tasakaalustaja jĂ€lgib rakenduse olekut ja vĂ€listab tasakaalus hoidmisest instantsid, mis ei lĂ€binud elujĂ”udluse kontrolli. Skaleerimine saavutatakse koormuse ĂŒhtlasy jaotamise kaudu instantside vahel ning instantside nimekirja vĂ€rskendamisega reaalajas. Kui tasakaalustus ei ole piisavalt ĂŒhtlane, saavad mĂ”ned instantsid koormuse, mis ĂŒletab nende taluvuspiirid, ja teenus muutub vĂ€hem usaldusvÀÀrseks.

Koormustasakaalustajat klassifitseeritakse sageli OSI mudeli protokolli taseme jÀrgi, millega ta töötab. Pilve tasakaalustaja töötab TCP tasemel, mis vastab neljandale tasemele, L4.

Liigume ĂŒlevaate juurde pilve tasakaalustaja arhitektuurist. TĂ”stame jĂ€rk-jĂ€rgult detailide taset. Jagame tasakaalustaja komponente kolme klassi. Klass config plane vastutab kasutajaga suhtlemise ning sĂŒsteemi sihtoleku salvestamise eest. Control plane salvestab sĂŒsteemi tegeliku oleku ja haldab data plane klassi sĂŒsteeme, mis vastutavad liikluse edastamise eest klientidelt teie instantsidele.

Data plane

Liiklus jĂ”uab kallitele seadmetele, mida nimetatakse piirrouteriteks. TĂ”hususe suurendamiseks töötab ĂŒhes andmekeskuses samaaegselt mitu sellist seadet. Edasi jĂ”uab liiklus koormuse tasakaalustajatesse, mis reklaamivad klientidele anycast IP-aadressi kĂ”igis AZ-des BGP kaudu. 

Yandex.Cloudi vÔrgu koormuse tasakaalustaja arhitektuur

Liiklus edastatakse ECMP kaudu — see on marsruutimisstrateegia, mille kohaselt vĂ”ivad sihtpunkti (meie puhul siht-IP-aadress) suunata mitmed vĂ”rdselt head marsruuti ning pakette saab edastada mistahes neist. Samuti toetame mitme kĂ€ttesaadavuse tsooni tööd jĂ€rgmisel skeemil: reklaamime aadressi igas tsoonis, liiklus jĂ”uab lĂ€himasse ja ei vĂ€lju sealt enam. Hiljem postituses vaatame lĂ€hemalt, mis juhtub liiklusega.

Config plane

 
Config plane'i peamine komponent on API, mille kaudu teostatakse pĂ”hitegevused koormuse tasakaalustajatega: loomine, kustutamine, instantside koostisosade muutmine, tervisekontrollide tulemuste saamine jne. Ühest kĂŒljest on see REST API, aga teisest kĂŒljest kasutame Mees Cloudis sageli gRPC raamistikku, seega "tĂ”lgime" REST-i gRPC-ks ning edaspidi kasutame ainult gRPC-d. Iga pĂ€ring toob kaasa seeria asĂŒnkroonseid idempotente ĂŒlesandeid, mis tĂ€idetakse Yandex Cloudi ĂŒhises töötajate basseinis. Ülesanded on kirjutatud nii, et need vĂ”ivad igal ajal peatuda ja hiljem uuesti kĂ€ivituda. See tagab operatsioonide skaleeritavuse, korduvuse ja logimise.

Yandex.Cloudi vÔrgu koormuse tasakaalustaja arhitektuur

LĂ”puks teeb API ĂŒlesanne pĂ€ringu koormuse tasakaalustajate teenuse kontrollijale, mis on kirjutatud Go-s. See vĂ”ib lisada ja kustutada koormuse tasakaalustajaid, muuta tagaplaanide koosseisu ja seadeid. 

Yandex.Cloudi vÔrgu koormuse tasakaalustaja arhitektuur

Teenuse olek salvestatakse Yandex Database'i — jaotatud hallatav andmebaas, millega saate varsti ise tutvuda. Yandex Cloudis, nagu juba ĂŒtlesime, rÀÀkinud, kehtib dog foodi kontseptsioon: kui me ise kasutame oma teenuseid, siis kasutavad ka meie kliendid neid hea meelega. Yandex Database on selle kontseptsiooni elluviimise nĂ€ide. Salvestame YDB-s kĂ”ik oma andmed ja meil ei pea olema muret andmebaasi hooldamise ja skaleerimise ĂŒle: need probleemid on meie eest lahendatud, kasutame andmebaasi kui teenust.

Naasume tasakaalu kontrolleri juurde. Tema ĂŒlesanne on sĂ€ilitada tasakaalu teavet, edastada kontrolliĂŒlesande virtuaalmasina valmiduse kohta tervisekontrolli kontrollerile.

Tervisekontrolli kontroller

See saab pĂ€ringuid kontrollimisreeglite muutmiseks, salvestab need YDB-sse, jagab ĂŒlesanded tervisekontrolli sĂ”lmedele ning kogub tulemused, mis seejĂ€rel salvestatakse andmebaasi ja edastatakse tasakaalu kontrollerile. Viimane saadab omakorda pĂ€ringu klastrikoosseisu muutmiseks andmeplaadi tasakaalu sĂ”lmele, millest rÀÀgin allpool.

Yandex.Cloudi vÔrgu koormuse tasakaalustaja arhitektuur

RÀÀgime lĂ€hemalt tervisekontrollidest. Need saab jagada mitmeks klassiks. Kontrollide edukuse kriteeriumid on erinevad. TCP-kontrollid peavad edukalt ĂŒhendust looma kindla aja jooksul. HTTP-kontrollid nĂ”uavad nii edukat ĂŒhendust kui ka vastust staatuskoodiga 200.

Kontrollid erinevad ka tegevusklasside poolest — need vĂ”ivad olla aktiivsed ja passiivsed. Passiivsed kontrollid jĂ€lgivad lihtsalt, mis toimub liikluses, ega tee erilisi toiminguid. See ei tööta hĂ€sti L4 tasemel, kuna sĂ”ltub kĂ”rgema taseme protokollide loogikast: L4-l ei ole teavet selle kohta, kui kaua operatsioon kestis ja kas ĂŒhenduse lĂ”petamine oli hea vĂ”i halb. Aktiivsed kontrollid nĂ”uavad, et tasakaalustaja saadaks pĂ€ringud iga serveri instantsi kohta.

Enamik koormuse tasakaalustajaid teostab "elu" kontrollid ise. Meie Clouds oleme otsustanud jagada need sĂŒsteemi osad skaleeritavuse suurendamiseks. See lĂ€henemine vĂ”imaldab meil suurendada tasakaalustajate arvu, sĂ€ilitades samal ajal tervisekontrolli pĂ€ringute arvu teenusele. Kontrollid teostatakse eraldi tervisekontrolli sĂ”lmedel, kuhu on jaotatud ja replitseeritud kontrollimise sihid. Ühel hostil ei saa kontrolle teha, kuna see vĂ”ib ebaĂ”nnestuda. Siis ei saa me infot selle kohta, millised instantsid on kontrollitud. Teeme kontrollid igast instantsist vĂ€hemalt kolmest tervisekontrolli sĂ”lmest. Kontrollimise sihid jagame sĂ”lmede vahel, kasutades konsistentsse hashimise algoritme.

Yandex.Cloudi vÔrgu koormuse tasakaalustaja arhitektuur

Tasakaalu ja tervisekontrolli eraldamine vÔib pÔhjustada probleeme. Kui tervisekontrolli sÔlm teeb pÀringuid instantsile, mööda tasakaalustajat (mis hetkel ei töötle liiklust), siis tekib kummaline olukord: ressurss nÀib olevat elus, kuid liiklus sinna ei pÀÀse. Me lahendame selle probleemi jÀrgmiselt: suuname tervisekontrolli liikluse kindlalt lÀbi tasakaalustajate. TeisisÔnu, klientide ja tervisekontrollide liikluse pakettide edastamise skeem erineb minimaalselt: mÔlemal juhul jÔuavad paketid tasakaalustajatesse, mis toimetavad need sihtressursside juurde.

Erinevus on selles, et kliendid teevad pĂ€ringud VIP-ile, samas kui tervisekontrollid pöörduvad iga eraldi RIP-i poole. Siin tekib huvitav probleem: meie kasutajatele anname vĂ”imaluse luua ressursse hallides IP-vĂ”rkudes. Kujutame ette, et on kaks erinevat pilveomanikku, kes on varjanud oma teenuseid tasakaalustajate taha. IgaĂŒhel neist on ressursid alamvĂ”rgus 10.0.0.1/24, millel on samad aadressid. Tuleb osata neid kuidagi eristada, ja siin tuleb sĂŒveneda Yandex.Cloudi virtuaalvĂ”rgu struktuuri. TĂ€iendavaid ĂŒksikasju on parem teada saada ĂŒrituse video kaudu about:cloud, meile on praegu oluline, et vĂ”rk on mitmekihiline ning sisaldab tunnelite eristamiseks alamsubneti id-sid.

Tervisekontrolli sÔlmed pöörduvad tasakaalustajate poole nn pool-IPv6-aadresside kaudu. Poolaadress on IPv6-aadress, mille sees on peidetud IPv4-aadress ja kasutaja alamsubneti id. Liiklus jÔuab tasakaalustajani, kes vÀljavÔtab sellest ressursi IPv4-aadressi, asendab IPv6 IPv4-ga ja saadab paketi kasutaja vÔrgusse.

Tagasi liiklus kulgeb samamoodi: tasakaalustaja nÀeb, et sihtkoht on tervisekontrollijate hall vÔrk, ja muudab IPv4 IPv6-ks.

VPP — andmeplaadi sĂŒda

Tasakaalustaja on rakendatud Vector Packet Processing (VPP) tehnoloogia abil — Cisco raamistik, mis on mĂ”eldud vĂ”rgu liikluse pakettide töötlemiseks. Meie juhul töötab raamistik ĂŒle kasutaja ruumi vĂ”rgu seadmete haldamise raamatukogu — Data Plane Development Kit (DPDK). See tagab pakettide töötlemise kĂ”rge jĂ”udluse: tuumas toimub palju vĂ€hem katkestusi, puuduvad konteksti vahetused tuuma ja kasutaja ruumi vahel. 

VPP lĂ€heb veel kaugemale ja pigistab sĂŒsteemist veel rohkem jĂ”udlust, ĂŒhendades pakette partiitideks. JĂ”udluse tĂ”us toimub agressiivse kasutamise tĂ”ttu kaasaegsete protsessorite vahemĂ€lus. Kasutatavad on nii andmevahemĂ€lu (pakette töödeldakse "vektoritega", andmed on ĂŒksteisele lĂ€hedal) kui ka kĂ€skude vahemĂ€lu: VPP-s pakettide töötlemine jĂ€rgneb graafile, mille sĂ”lmedes asuvad funktsioonid, mis tĂ€idavad ĂŒhte ĂŒlesannet.

NĂ€iteks IP-pakettide töötlemine VPP-s toimub sellises jĂ€rjekorras: esmalt toimub sĂ”lmes analĂŒĂŒs pakettide pealkirjadest, seejĂ€rel saadetakse need sĂ”lme, mis edastab paketid edasi marsruudi tabelite kohaselt.

Veidi hardcore. VPP autorid ei luba protsessori vahemĂ€lu kasutuses kompromisse, seega tĂŒĂŒpiline kood pakettide vektorite töötlemiseks sisaldab kĂ€sitsi vektoreerimist: on töötlemise tsĂŒkkel, milles kĂ€sitletakse olukorda "meil on neli paketti jĂ€rjekorras", seejĂ€rel sama ka kahe jaoks, ja seejĂ€rel ĂŒhele. Kasutatakse sageli prefetch-kĂ€ske, mis laadivad andmed vahemĂ€ludesse, et kiirendada neile jĂ€rgmistes iteratsioonides juurde pÀÀsemist.

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)
    {
        // töötle mitu paketti korraga
        u32 next0 = SAMPLE_NEXT_INTERFACE_OUTPUT;
        u32 next1 = SAMPLE_NEXT_INTERFACE_OUTPUT;
        // ...
        /* Eelprefetch jÀrgmise iteratsiooni jaoks. */
        {
            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);
        }
        // tegelikult töötle andmeid
        /* kinnita spekulatiivsed jĂ€rjekorrastamised, vĂ”ib-olla lĂŒlita praegune jĂ€rgmine raami * /
        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)
    {
        // töötle pakette ĂŒkshaaval
    }

    // töödeldi partii
    vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}

Nii et Healthcheckid teevad IPv6 kaudu VPP-le pÀringuid, mis muudab need IPv4-ks. Sellega tegeleb graafi sÔlm, mida me nimetame algoritmiliseks NAT-iks. Tagasitee liikluse (ja IPv6-st IPv4-ks konverteerimise) jaoks on olemas sama algoritmiline NAT-sÔlm.

Yandex.Cloudi vÔrgu koormuse tasakaalustaja arhitektuur

Otsene liiklus klientidelt tasakaalustaja lÀbib graafi sÔlmi, mis teostavad otsest tasakaalustamist. 

Yandex.Cloudi vÔrgu koormuse tasakaalustaja arhitektuur

Esimene sĂ”lm – sticky sessions. Selles hoitakse hash-i. 5-tuple paigaldatud seansside jaoks. 5-tuple sisaldab kliendi aadressi ja porti, kust teave edastatakse, ressursi aadressi ja porte, mis on saadaval liikluse vastuvĂ”tmiseks, ning vĂ”rgu protokolli. 

5-tuple'i hash aitab meil jĂ€rgmises konsistentse hashimise sĂ”lmes vĂ€hem arvutusi teha ning paremini hallata ressursside nimekirja muutumist koormuse tasakaalustaja taga. Kui koormuse tasakaalustajale tuleb pakett, mille jaoks pole seanssi, saadetakse see konsistentse hashimise sĂ”lme. Siin toimub tasakaalustus konsistentse hashimise abil: valime ressursi saadaval olevate "elavate" ressursside loendist. SeejĂ€rel saadetakse paketid NAT sĂ”lme, mis teeb tegeliku sihtaadressi asendamise ja kontrollsumma ĂŒmberarvutamise. Nagu nĂ€ete, jĂ€rgime VPP reegleid — sarnane sarnasega, grupeerime sarnased arvutused, et suurendada protsessori vahemĂ€lu efektiivsust.

Konsistentne hashimine

Miks me valisime just selle ja mis see ĂŒldse on? Alustame varasema ĂŒlesande kaalumisest — ressursi valimine loendist. 

Yandex.Cloudi vÔrgu koormuse tasakaalustaja arhitektuur

EbaĂŒhtlases hashimises arvutatakse sissetuleva paketi hash ja ressurssi valitakse loendist selle hash'i jagemise jÀÀ jĂ€rgi ressursside arvuga. Niikaua kui loend jÀÀb muutumatuks, töötab see skeem hĂ€sti: me saadame alati samade 5-tuple'idega paketid sama instantsi juurde. Kui aga mĂ”ni ressurss enam healthcheck'idele vastata ei suuda, siis muutub suure osa hash'ide valik. Kliendi TCP-ĂŒhendused katkeb: pakett, mis varem lĂ€ks instants A-le, vĂ”ib hakata minema instantsi B-le, mis ei tunne selle paketi seanssi.

Konsistentne hashimine lahendab kirjeldatud probleemi. KÔige lihtsam on seda kontseptsiooni selgitada jÀrgmiselt: kujutage ette, et teil on ring, millele jaotate ressursid hash'i (nÀiteks IP:port) jÀrgi. Ressursi valimine on ratta pööramine nurga all, mis mÀÀratakse paketi hash'i jÀrgi.

Yandex.Cloudi vÔrgu koormuse tasakaalustaja arhitektuur

Nii minimeeritakse liikluse ĂŒmberjaotamine, kui ressursside koosseis muutub. Ressursi eemaldamine mĂ”jutab ainult seda osa konsistentse hashimise ringist, kus see ressurss asus. Ressursi lisamine muudab samuti jaotust, kuid meil on olemas sticky sessions sĂ”lm, mis vĂ”imaldab juba loodud seanssid viia uutele ressurssidele.

Me oleme vaadanud, mis juhtub otse liiklusega tasakaalustaja ja ressursside vahel. NĂŒĂŒd vaatame tagasiliiklust. See jĂ€rgib sama skeemi nagu kontrollide liiklus — lĂ€bi algoritmilise NAT, st tagas NAT 44 kliendiliikluse jaoks ja NAT 46 healthcheckide liikluse jaoks. Me jĂ€rgime oma skeemi: ĂŒhtlustame healthcheckide liikluse ja tĂ”elise kasutajate liikluse.

Loadbalancer-node ja komponendid kogumina

Loadbalancer-node edastab teavet tasakaalustajate ja ressursside koosseisu VPP-s. See tellib sĂŒndmuste vooge loadbalancer-controllerilt, oskab ehitada hetke VPP oleku ja sihtoleku vahe, mis saadakse kontrollerilt. Saame suletud sĂŒsteemi: API-s sĂŒndmused jĂ”uavad tasakaalustaja kontrollerisse, mis mÀÀrab healthcheck-kontrollerile ĂŒlesandeid ressursside „elujĂ”u“ kontrollimiseks. See omakorda mÀÀrab ĂŒlesanded healthcheck-node'ile ja koondab tulemused, edastades need tagasi tasakaalustajate kontrollerile. Loadbalancer-node tellib sĂŒndmusi kontrollerilt ja muudab VPP olekut. Sellises sĂŒsteemis teab iga teenus ainult vajalikku naabrite teenustest. Seoste arv on piiratud ja meil on vĂ”imalus iseseisvalt hallata ja skaleerida erinevaid segmente.

Yandex.Cloudi vÔrgu koormuse tasakaalustaja arhitektuur

Milliseid kĂŒsimusi Ă”nnestus vĂ€ltida

KĂ”ik meie teenused control plane-s on kirjutatud Go-s ja neil on head skaleeritavuse ja usaldusvÀÀrsuse omadused. Go-s on palju avatud lĂ€htekoodiga raamatukogusid jaotatud sĂŒsteemide ehitamiseks. Me kasutame aktiivselt GRPC-t, kĂ”ik komponendid sisaldavad avatud lĂ€htekoodiga teenuste avastamise teostust — meie teenused jĂ€lgivad ĂŒksteise töövĂ”imet, saavad dĂŒnaamiliselt oma koosseisu muuta ning oleme selle sidunud GRPC tasakaalustamisega. Meetmete jaoks kasutame samuti avatud lĂ€htekoodiga lahendust. Andmeplaanis saavutasime korraliku jĂ”udluse ja suure ressursi reservi: oli vĂ€ga keeruline kokku panna seista, mille puhul vĂ”iksime jĂ”udlusesse kalduda VPP ja mitte riistvaralisse vĂ”rgukaardisse.

Probleemid ja lahendused

Mis lĂ€ks halvasti? Go-s on mĂ€lu haldamine automaatne, kuid mĂ€lu leke vĂ”ib siiski esineda. Lihtsaim viis nendega toime tulla on kĂ€ivitada gorutiinid ja mitte unustada neid lĂ”petada. JĂ€reldus: jĂ€lgige Go-programmide mĂ€lutarbimist. Sageli on hea indikaator gorutiinide arv. Selle looga on ka pluss: Go-s on lihtne saada andmeid runtime'i kohta — mĂ€lu tarbimise, kĂ€ivitatud gorutiinide arvu ja paljude muude parameetrite kohta.

Lisaks, Go ei pruugi olla parim valik funktsionaalsete testide jaoks. Need on ĂŒsna mahukad ning standardne lĂ€henemine „kĂ€ivitada kĂ”ik CI-s korraga” ei sobi neile just hĂ€sti. Asi on selles, et funktsionaalsed testid on ressursinĂ”udlikumad ja need vĂ”ivad tĂ”eliselt aeguda. SeetĂ”ttu vĂ”ivad testid ebaĂ”nnestuda, kuna CPU on hĂ”ivatud ĂŒhiktestidega. JĂ€reldus: proovige eraldada „raskemad” testid ĂŒhiktestidest. 

Mikroteenuste sĂŒndmustepĂ”hine arhitektuur on keerulisem kui monoliit: logide grepimine kĂŒmnetelt erinevatelt masinatelt pole just mugav. JĂ€reldus: kui teete mikroteenuseid, mĂ”elge kohe jĂ€lgimise peale.

Meie plaanid

KĂ€ivitame sise-balanseerija, IPv6-balanseerija, lisame Kubernetes'i skriptide toe, jĂ€tkame oma teenuste sharding'it (praegu on sharditud ainult healthcheck-node ja healthcheck-ctrl), lisame uusi healthcheck-e ning rakendame nutikat kontrollide koondamist. Uurime vĂ”imalust teha meie teenused veel sĂ”ltumatumaks — et nad ei suhtleks omavahel otse, vaid sĂ”numijĂ€rjekorra kaudu. Jaanuaris ilmus pilves SQS-i ĂŒhilduv teenus. Yandex Message Queue.

Hiljuti toimus Yandex Load Balancer'i avalik vÀljaanne. Uurige lÀhemalt dokumentatsioon teenusele, hallake balanseerijaid endale sobival viisil ja suurendage oma projektide taluvust katkestuste suhtes!

Allikas: habr.com

Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster