Netramesh - lahka servisna mrežna rešitev

Ko prehajamo iz monolitne aplikacije v arhitekturo mikrostoritev, se soočamo z novimi izzivi.

V monolitni aplikaciji je običajno zelo enostavno ugotoviti, v katerem delu sistema je prišlo do napake. Najverjetneje je težava v kodi samega monolita ali v bazi podatkov. Ko pa začnemo iskati problem v mikroservisni arhitekturi, ni več vse tako očitno. Najti moramo celotno pot, po kateri je zahteva potekala od začetka do konca, in jo izbrati med stotinami mikrostoritev. Poleg tega imajo mnogi od njih tudi svoje prostore za shranjevanje, kar lahko povzroči tudi logične napake, pa tudi težave z zmogljivostjo in toleranco napak.

Netramesh - lahka servisna mrežna rešitev

Dolgo sem iskal orodje, ki bi pomagalo obvladati takšne težave (o tem sem pisal na Habréju: 1, 2), vendar sem na koncu naredil svojo odprtokodno rešitev. V tem članku govorim o prednostih storitvenega mrežnega pristopa in delim novo orodje za njegovo implementacijo.

Porazdeljeno sledenje je običajna rešitev za problem iskanja napak v porazdeljenih sistemih. A kaj, ko ta pristop k zbiranju informacij o omrežnih interakcijah še ni implementiran v sistem ali, kar je še huje, v delu sistema že deluje pravilno, v delu pa ne, saj ni dodan starim storitvam ? Za določitev točnega temeljnega vzroka težave je treba imeti popolno sliko o tem, kaj se dogaja v sistemu. Še posebej pomembno je razumeti, katere mikrostoritve so vključene v ključne poslovne poti.

Tu nam lahko na pomoč priskoči storitveni mrežni pristop, ki se bo ukvarjal z vsemi stroji za zbiranje omrežnih informacij na nižji ravni, kot delujejo same storitve. Ta pristop nam omogoča, da prestrežemo ves promet in ga sproti analiziramo. Poleg tega aplikacijam sploh ni treba vedeti ničesar o tem.

Storitveni mrežni pristop

Glavna ideja storitvenega mrežnega pristopa je dodati še eno infrastrukturno plast preko omrežja, kar nam bo omogočilo, da naredimo karkoli z interakcijo med storitvami. Večina implementacij deluje na naslednji način: vsaki mikrostoritvi je dodan dodatni vsebnik sidecar s preglednim proxyjem, skozi katerega poteka ves dohodni in odhodni promet storitve. In prav tukaj lahko izvajamo uravnoteženje odjemalcev, uporabljamo varnostne politike, nalagamo omejitve glede števila zahtev in zbiramo pomembne informacije o interakciji storitev v proizvodnji.

Netramesh - lahka servisna mrežna rešitev

Rešitve

Obstaja že več izvedb tega pristopa: Istio и linkerd2. Zagotavljajo veliko funkcij takoj po namestitvi. Toda hkrati pride do velikih stroškov pri virih. Še več, večji kot je grozd, v katerem tak sistem deluje, več sredstev bo potrebnih za vzdrževanje nove infrastrukture. Pri Avitu upravljamo gruče kubernetes, ki vsebujejo na tisoče primerkov storitev (in njihovo število še naprej hitro raste). V trenutni izvedbi Istio porabi ~300 Mb RAM-a na primerek storitve. Zaradi velikega števila možnosti transparentno izravnavanje vpliva tudi na skupni odzivni čas storitev (do 10ms).

Posledično smo natančno preučili, katere zmogljivosti trenutno potrebujemo, in se odločili, da je glavni razlog, zakaj smo začeli izvajati takšne rešitve, sposobnost preglednega zbiranja informacij o sledenju iz celotnega sistema. Želeli smo imeti tudi nadzor nad interakcijo storitev in izvajati različne manipulacije z glavami, ki se prenašajo med storitvami.

Posledično smo prišli do odločitve:  Netramesh.

Netramesh

Netramesh je lahka storitvena mrežasta rešitev z možnostjo neskončnega prilagajanja, ne glede na število storitev v sistemu.

Glavni cilji nove rešitve so bili nizki stroški virov in visoka zmogljivost. Med glavnimi funkcijami smo takoj želeli imeti možnost preglednega pošiljanja razponov sledenja v naš sistem Jaeger.

Danes je večina rešitev v oblaku implementiranih v Golangu. In za to seveda obstajajo razlogi. Pisanje omrežnih aplikacij v Golangu, ki delujejo asinhrono z V/I in se po potrebi spreminjajo med jedri, je priročno in precej preprosto. In kar je zelo pomembno, zmogljivost je zadostna za rešitev tega problema. Zato smo tudi izbrali Golang.

Produktivnost

Svoja prizadevanja smo usmerili v doseganje maksimalne produktivnosti. Za rešitev, ki je razporejena poleg vsakega primerka storitve, je potrebna majhna poraba RAM-a in časa procesorja. In seveda mora biti tudi odzivna zamuda majhna.

Poglejmo, kakšne rezultate smo dosegli.

RAM

Netramesh porabi ~10Mb brez prometa in največ 50Mb z obremenitvijo do 10000 RPS na instanco.

Istio envoy proxy vedno porabi ~300 Mb v naših gručih s tisočimi primerki. To ne omogoča prilagajanja celotnemu grozdu.

Netramesh - lahka servisna mrežna rešitev

Netramesh - lahka servisna mrežna rešitev

Z Netramesh smo dosegli ~10-kratno zmanjšanje porabe pomnilnika.

CPU

Poraba procesorja je pod obremenitvijo relativno enaka. Odvisno je od števila zahtev na časovno enoto stranski prikolici. Vrednosti pri 3000 zahtevah na sekundo na vrhu:

Netramesh - lahka servisna mrežna rešitev

Netramesh - lahka servisna mrežna rešitev

Obstaja še ena pomembna točka: Netramesh - rešitev brez nadzorne ravnine in brez obremenitve ne porabi časa procesorja. Z Istio sidecars vedno posodobijo končne točke storitev. Posledično lahko vidimo to sliko brez obremenitve:

Netramesh - lahka servisna mrežna rešitev

Za komunikacijo med storitvami uporabljamo HTTP/1. Povečanje odzivnega časa za Istio pri proxyju prek envoy je bilo do 5-10 ms, kar je precej za storitve, ki so pripravljene odgovoriti v milisekundi. Z Netramesh se je ta čas zmanjšal na 0.5-2 ms.

Razširljivost

Majhna količina virov, ki jih porabi vsak proxy, omogoča, da ga postavite poleg vsake storitve. Netramesh je bil namenoma ustvarjen brez komponente krmilne ravnine, da bi bila vsaka stranska prikolica preprosto lahka. Pogosto v rešitvah servisne mreže krmilna ravnina distribuira informacije o odkrivanju storitve vsaki stranski prikolici. Skupaj z njim so informacije o časovnih omejitvah in nastavitvah uravnoteženja. Vse to vam omogoča, da naredite veliko koristnih stvari, vendar na žalost napihne stranske prikolice v velikosti.

Odkrivanje storitve

Netramesh - lahka servisna mrežna rešitev

Netramesh ne dodaja nobenih dodatnih mehanizmov za odkrivanje storitev. Ves promet je proksiran pregledno prek netra sidecar.

Netramesh podpira aplikacijski protokol HTTP/1. Za določitev se uporablja nastavljiv seznam vrat. Običajno ima sistem več vrat, prek katerih poteka komunikacija HTTP. Za interakcijo med storitvami in zunanjimi zahtevami na primer uporabljamo 80, 8890, 8080. V tem primeru jih lahko nastavimo s spremenljivko okolja NETRA_HTTP_PORTS.

Če uporabljate Kubernetes kot orkestrator in njegov mehanizem storitvene entitete za komunikacijo med storitvami znotraj gruče, potem mehanizem ostane popolnoma enak. Najprej mikrostoritev pridobi naslov IP storitve s pomočjo kube-dns in odpre novo povezavo z njim. Ta povezava se najprej vzpostavi z lokalnim netra-sidecarjem in vsi paketi TCP prvotno prispejo na netra. Nato netra-sidecar vzpostavi povezavo s prvotnim ciljem. NAT na pod IP na vozlišču ostane popolnoma enak kot brez netre.

Porazdeljeno sledenje in posredovanje konteksta

Netramesh zagotavlja funkcionalnost, potrebno za pošiljanje razponov sledenja o interakcijah HTTP. Netra-sidecar razčleni protokol HTTP, meri zamude zahtev in izvleče potrebne informacije iz glav HTTP. Končno dobimo vse sledi v enem samem sistemu Jaeger. Za natančno konfiguracijo lahko uporabite tudi spremenljivke okolja, ki jih nudi uradna knjižnica knjižnica jaeger go.

Netramesh - lahka servisna mrežna rešitev

Netramesh - lahka servisna mrežna rešitev

Vendar obstaja problem. Dokler storitve ne ustvarijo in ne pošljejo posebne glave uber, v sistemu ne bomo videli povezanih razponov sledenja. In to je tisto, kar moramo hitro najti vzrok težav. Tudi tukaj ima Netramesh rešitev. Posredniki preberejo glave HTTP in, če ne vsebujejo ID-ja sledenja uber, ga ustvarijo. Netramesh shranjuje tudi informacije o dohodnih in odhodnih zahtevah v stranski prikolici in jih ujema tako, da jih obogati s potrebnimi glavami odhodnih zahtev. Vse, kar morate storiti v storitvah, je, da pošljete samo eno glavo X-Request-Id, ki ga je mogoče konfigurirati s spremenljivko okolja NETRA_HTTP_REQUEST_ID_HEADER_NAME. Če želite nadzorovati velikost konteksta v Netramesh, lahko nastavite naslednje spremenljivke okolja: NETRA_TRACING_CONTEXT_EXPIRATION_MILLISECONDS (čas, za katerega bo kontekst shranjen) in NETRA_TRACING_CONTEXT_CLEANUP_INTERVAL (pogostost čiščenja konteksta).

Možno je tudi kombinirati več poti v vašem sistemu, tako da jih označite s posebnim žetonom seje. Netra vam omogoča namestitev HTTP_HEADER_TAG_MAP za pretvorbo glav HTTP v ustrezne oznake razpona sledenja. To je lahko še posebej koristno za testiranje. Po opravljenem funkcionalnem preizkusu lahko vidite, na kateri del sistema je vplivalo filtriranje z ustreznim ključem seje.

Določitev vira zahteve

Če želite ugotoviti, od kod prihaja zahteva, lahko uporabite funkcijo samodejnega dodajanja glave z virom. Uporaba spremenljivke okolja NETRA_HTTP_X_SOURCE_HEADER_NAME Določite lahko ime glave, ki bo samodejno nameščeno. Z uporabo NETRA_HTTP_X_SOURCE_VALUE nastavite lahko vrednost, na katero bo nastavljena glava X-Source za vse odhodne zahteve.

To omogoča enakomerno porazdelitev te uporabne glave po celotnem omrežju. Nato ga lahko uporabite v storitvah in dodate v dnevnike in meritve.

Usmerjanje prometa in notranjost Netramesh

Netramesh je sestavljen iz dveh glavnih komponent. Prvi, netra-init, nastavi omrežna pravila za prestrezanje prometa. On uporablja pravila preusmeritve iptables za prestrezanje celotnega ali dela prometa na stranski prikolici, ki je druga glavna komponenta Netramesha. Konfigurirate lahko, katera vrata je treba prestreči za dohodne in odhodne seje TCP: INBOUND_INTERCEPT_PORTS, OUTBOUND_INTERCEPT_PORTS.

Orodje ima tudi zanimivo lastnost – verjetnostno usmerjanje. Če uporabljate Netramesh izključno za zbiranje razponov sledenja, potem lahko v produkcijskem okolju prihranite vire in omogočite verjetnostno usmerjanje z uporabo spremenljivk NETRA_INBOUND_PROBABILITY и NETRA_OUTBOUND_PROBABILITY (od 0 do 1). Privzeta vrednost je 1 (ves promet je prestrežen).

Po uspešnem prestrezanju bočna prikolica netra sprejme novo povezavo in jo uporabi SO_ORIGINAL_DST možnost vtičnice, da dobite prvotni cilj. Netra nato odpre novo povezavo s prvotnim naslovom IP in vzpostavi dvosmerno komunikacijo TCP med strankama, pri čemer posluša ves promet, ki poteka mimo. Če so vrata definirana kot HTTP, jih Netra poskuša razčleniti in izslediti. Če razčlenjevanje HTTP ne uspe, se Netra vrne na TCP in pregledno proksira bajte.

Gradnja grafa odvisnosti

Po prejemu velike količine informacij o sledenju v Jaegerju želim dobiti celoten graf interakcij v sistemu. Toda če je vaš sistem precej obremenjen in se na dan nabere milijarde razponov sledenja, njihovo združevanje ne postane tako lahka naloga. Obstaja uraden način za to: odvisnosti od iskre. Vendar pa bo trajalo več ur, da zgradite celoten graf, in vas bo prisililo, da prenesete celoten nabor podatkov iz Jaegerja za zadnjih XNUMX ur.

Če uporabljate Elasticsearch za shranjevanje razponov sledenja, lahko uporabite preprost pripomoček Golang, ki bo v nekaj minutah zgradil enak graf z uporabo funkcij in zmožnosti Elasticsearch.

Netramesh - lahka servisna mrežna rešitev

Kako uporabljati Netramesh

Netro je mogoče preprosto dodati kateri koli storitvi, ki izvaja kateri koli orkestrator. Lahko vidite primer tukaj.

Trenutno Netra nima zmožnosti samodejne implementacije stranskih prikolic v storitve, vendar obstajajo načrti za implementacijo.

Prihodnost Netramesha

Glavni cilj Netramesh je doseči minimalne stroške virov in visoko zmogljivost, ki zagotavlja osnovne zmogljivosti za opazovanje in nadzor komunikacije med storitvami.

V prihodnosti bo Netramesh poleg HTTP podpiral tudi druge protokole aplikacijske plasti. Usmerjanje L7 bo na voljo v bližnji prihodnosti.

Uporabite Netramesh, če naletite na podobne težave in nam pišite z vprašanji in predlogi.

Vir: www.habr.com

Dodaj komentar