Netramesh - letvægts servicenetløsning

Når vi bevæger os fra en monolitisk applikation til en mikroservicearkitektur, står vi over for nye udfordringer.

I en monolitisk applikation er det normalt ret nemt at bestemme, hvilken del af systemet fejlen opstod i. Sandsynligvis ligger problemet i selve monolittens kode eller i databasen. Men når vi begynder at lede efter et problem i en mikroservicearkitektur, er alt ikke længere så indlysende. Vi skal finde hele stien, som anmodningen tog fra start til slut, og vælge den fra hundredvis af mikrotjenester. Desuden har mange af dem også deres egne lagerfaciliteter, hvilket også kan forårsage logiske fejl, samt problemer med ydeevne og fejltolerance.

Netramesh - letvægts servicenetløsning

Jeg har længe ledt efter et værktøj, der kunne hjælpe med at klare sådanne problemer (jeg skrev om dette på Habré: 1, 2), men til sidst lavede jeg min egen open source-løsning. I denne artikel taler jeg om fordelene ved service mesh-tilgangen og deler et nyt værktøj til dens implementering.

Distribueret sporing er en almindelig løsning på problemet med at finde fejl i distribuerede systemer. Men hvad nu hvis denne tilgang til indsamling af information om netværksinteraktioner endnu ikke er implementeret i systemet, eller værre, i en del af systemet fungerer den allerede korrekt, men til dels ikke, da den ikke er blevet tilføjet til gamle tjenester ? For at bestemme den nøjagtige årsag til et problem, er det nødvendigt at have et komplet billede af, hvad der sker i systemet. Det er især vigtigt at forstå, hvilke mikrotjenester der er involveret i vigtige forretningskritiske veje.

Her kan service mesh-tilgangen komme os til hjælp, som vil håndtere alle maskineri til indsamling af netværksinformation på et niveau, der er lavere end tjenesterne selv opererer. Denne tilgang giver os mulighed for at opsnappe al trafik og analysere den på farten. Desuden behøver applikationer ikke engang at vide noget om det.

Service mesh tilgang

Hovedideen med service mesh-tilgangen er at tilføje endnu et infrastrukturlag over netværket, som vil give os mulighed for at gøre hvad som helst med inter-service interaktion. De fleste implementeringer fungerer som følger: En ekstra sidevognsbeholder med en gennemsigtig proxy tilføjes til hver mikrotjeneste, hvorigennem al indgående og udgående trafik af tjenesten sendes. Og det er netop det sted, hvor vi kan foretage klientbalancering, anvende sikkerhedspolitikker, pålægge begrænsninger for antallet af anmodninger og indsamle vigtig information om interaktionen mellem tjenester i produktionen.

Netramesh - letvægts servicenetløsning

Решения

Der er allerede flere implementeringer af denne tilgang: Samme и linkerd2. De giver en masse funktioner ud af boksen. Men samtidig kommer der en stor overhead på ressourcerne. Desuden, jo større klynge et sådant system opererer i, jo flere ressourcer vil der kræves for at vedligeholde den nye infrastruktur. Hos Avito driver vi kubernetes-klynger, der indeholder tusindvis af serviceforekomster (og deres antal fortsætter med at vokse hurtigt). I sin nuværende implementering bruger Istio ~300 Mb RAM pr. tjenesteinstans. På grund af det store antal muligheder påvirker gennemsigtig afbalancering også den samlede responstid for tjenester (op til 10 ms).

Som et resultat kiggede vi på præcis, hvilke muligheder vi havde brug for lige nu, og besluttede, at hovedårsagen til, at vi begyndte at implementere sådanne løsninger, var evnen til at indsamle sporingsinformation fra hele systemet gennemsigtigt. Vi ønskede også at have kontrol over interaktionen af ​​tjenester og lave forskellige manipulationer med de overskrifter, der overføres mellem tjenester.

Som et resultat kom vi til vores beslutning:  Netramesh.

Netramesh

Netramesh er en letvægts service mesh-løsning med mulighed for at skalere uendeligt, uanset antallet af services i systemet.

Hovedmålene med den nye løsning var lav ressourceoverhead og høj ydeevne. Blandt hovedfunktionerne ønskede vi straks at være i stand til transparent at sende sporingsspænd til vores Jaeger-system.

I dag er de fleste cloud-løsninger implementeret i Golang. Og det er der selvfølgelig grunde til. At skrive netværksapplikationer i Golang, der arbejder asynkront med I/O og skalerer på tværs af kerner efter behov, er praktisk og ganske enkelt. Og hvad der også er meget vigtigt, ydeevnen er tilstrækkelig til at løse dette problem. Derfor valgte vi også Golang.

Ydelse

Vi har fokuseret vores indsats på at opnå maksimal produktivitet. For en løsning, der installeres ved siden af ​​hver instans af tjenesten, kræves et lille forbrug af RAM og CPU-tid. Og svarforsinkelsen skal selvfølgelig også være lille.

Lad os se, hvilke resultater vi fik.

RAM

Netramesh forbruger ~10 Mb uden trafik og 50 Mb maksimalt med en belastning på op til 10000 RPS pr. instans.

Istio envoy proxy bruger altid ~300 Mb i vores klynger med tusindvis af forekomster. Dette tillader ikke, at den skaleres til hele klyngen.

Netramesh - letvægts servicenetløsning

Netramesh - letvægts servicenetløsning

Med Netramesh fik vi en ~10x reduktion i hukommelsesforbrug.

CPU

CPU-brug er relativt lige under belastning. Det afhænger af antallet af anmodninger pr. tidsenhed til sidevognen. Værdier ved 3000 forespørgsler i sekundet ved peak:

Netramesh - letvægts servicenetløsning

Netramesh - letvægts servicenetløsning

Der er endnu et vigtigt punkt: Netramesh - en løsning uden kontrolplan og uden belastning bruger ikke CPU-tid. Med Istio opdaterer sidevogne altid serviceendepunkter. Som et resultat kan vi se dette billede uden belastning:

Netramesh - letvægts servicenetløsning

Vi bruger HTTP/1 til kommunikation mellem tjenester. Stigningen i responstid for Istio ved proxying via envoy var op til 5-10ms, hvilket er ret meget for tjenester, der er klar til at svare på et millisekund. Med Netramesh er denne tid faldet til 0.5-2ms.

Skalerbarhed

Den lille mængde ressourcer, der forbruges af hver proxy, gør det muligt at placere den ved siden af ​​hver tjeneste. Netramesh blev med vilje skabt uden en kontrolplankomponent for blot at holde hver sidevogn let. Ofte i servicenetløsninger distribuerer kontrolplanet serviceopdagelsesinformation til hver sidevogn. Sammen med det kommer information om timeouts og balanceringsindstillinger. Alt dette giver dig mulighed for at gøre en masse nyttige ting, men desværre blæser det sidevogne i størrelse.

Service opdagelse

Netramesh - letvægts servicenetløsning

Netramesh tilføjer ingen yderligere mekanismer til serviceopdagelse. Al trafik proxes transparent gennem netra sidevogn.

Netramesh understøtter HTTP/1-applikationsprotokol. For at definere det, bruges en konfigurerbar liste over porte. Systemet har typisk flere porte, hvorigennem HTTP-kommunikation sker. For eksempel bruger vi 80, 8890, 8080 til interaktion mellem tjenester og eksterne anmodninger. I dette tilfælde kan de indstilles ved hjælp af en miljøvariabel NETRA_HTTP_PORTS.

Hvis du bruger Kubernetes som en orkestrator og dens Service-entitetsmekanisme til intra-cluster-kommunikation mellem tjenester, så forbliver mekanismen nøjagtig den samme. Først opnår mikrotjenesten en tjeneste-IP-adresse ved hjælp af kube-dns og åbner en ny forbindelse til den. Denne forbindelse etableres først med den lokale netra-sidecar, og alle TCP-pakker ankommer i starten til netra. Dernæst etablerer netra-sidecar en forbindelse med den oprindelige destination. NAT på pod IP på noden forbliver nøjagtig den samme som uden netra.

Distribueret sporing og kontekstvideresendelse

Netramesh giver den nødvendige funktionalitet til at sende sporingsspænd om HTTP-interaktioner. Netra-sidecar analyserer HTTP-protokollen, måler anmodningsforsinkelser og udtrækker de nødvendige oplysninger fra HTTP-headere. I sidste ende får vi alle sporene i et enkelt Jaeger-system. Til finmasket konfiguration kan du også bruge miljøvariablerne fra det officielle bibliotek jaeger go bibliotek.

Netramesh - letvægts servicenetløsning

Netramesh - letvægts servicenetløsning

Men der er et problem. Indtil tjenester genererer og sender en speciel uber-header, vil vi ikke se forbundne sporingsspænd i systemet. Og det er det, vi skal bruge for hurtigt at finde årsagen til problemerne. Her har Netramesh igen en løsning. Proxyer læser HTTP-headere og genererer en, hvis de ikke indeholder uber-sporings-id'et. Netramesh gemmer også information om indgående og udgående anmodninger i en sidevogn og matcher dem ved at berige dem med de nødvendige udgående anmodningsheaders. Alt du skal gøre i tjenesterne er kun at sende én header X-Request-Id, som kan konfigureres ved hjælp af en miljøvariabel NETRA_HTTP_REQUEST_ID_HEADER_NAME. For at kontrollere størrelsen af ​​konteksten i Netramesh kan du indstille følgende miljøvariabler: NETRA_TRACING_CONTEXT_EXPIRATION_MILLISECONDS (det tidspunkt, hvor konteksten vil blive gemt) og NETRA_TRACING_CONTEXT_CLEANUP_INTERVAL (hyppighed af kontekstoprydning).

Det er også muligt at kombinere flere stier på dit system ved at markere dem med et særligt sessionstoken. Netra giver dig mulighed for at installere HTTP_HEADER_TAG_MAP at omdanne HTTP-headere til tilsvarende sporingsspændingstags. Dette kan især være nyttigt til test. Efter at have bestået funktionstesten kan du se, hvilken del af systemet, der blev påvirket af filtrering efter den tilsvarende sessionsnøgle.

Bestemmelse af anmodningskilden

For at bestemme, hvor anmodningen kom fra, kan du bruge funktionaliteten til automatisk at tilføje en header med kilden. Brug af en miljøvariabel NETRA_HTTP_X_SOURCE_HEADER_NAME Du kan angive et headernavn, der automatisk installeres. Ved hjælp af NETRA_HTTP_X_SOURCE_VALUE du kan indstille den værdi, som X-Source-headeren indstilles til for alle udgående anmodninger.

Dette gør det muligt at distribuere denne nyttige header ensartet over hele netværket. Så kan du bruge det i tjenester og tilføje det til logfiler og metrics.

Trafik routing og Netramesh internals

Netramesh består af to hovedkomponenter. Den første, netra-init, sætter netværksregler for at opsnappe trafik. Han bruger iptables omdirigeringsregler at opsnappe hele eller dele af trafikken på sidevognen, som er den anden hovedkomponent i Netramesh. Du kan konfigurere, hvilke porte der skal opsnappes til indgående og udgående TCP-sessioner: INBOUND_INTERCEPT_PORTS, OUTBOUND_INTERCEPT_PORTS.

Værktøjet har også en interessant funktion - probabilistisk routing. Hvis du udelukkende bruger Netramesh til at indsamle sporingsspænd, kan du i et produktionsmiljø spare ressourcer og aktivere probabilistisk routing ved hjælp af variabler NETRA_INBOUND_PROBABILITY и NETRA_OUTBOUND_PROBABILITY (fra 0 til 1). Standardværdien er 1 (al trafik opfanges).

Efter vellykket aflytning accepterer netra sidevogn den nye forbindelse og bruger SO_ORIGINAL_DST socket mulighed for at få den oprindelige destination. Netra åbner derefter en ny forbindelse til den oprindelige IP-adresse og etablerer to-vejs TCP-kommunikation mellem parterne og lytter til al trafik, der passerer igennem. Hvis porten er defineret som HTTP, forsøger Netra at parse og spore den. Hvis HTTP-parsing mislykkes, falder Netra tilbage til TCP og proxyer transparent bytes.

Opbygning af en afhængighedsgraf

Efter at have modtaget en stor mængde sporingsinformation i Jaeger, ønsker jeg at få en komplet graf over interaktioner i systemet. Men hvis dit system er ret belastet, og der akkumuleres milliarder af sporingsspænd om dagen, bliver det ikke så let at samle dem. Der er en officiel måde at gøre dette på: gnistafhængigheder. Det vil dog tage timer at bygge en komplet graf og vil tvinge dig til at downloade hele datasættet fra Jaeger for de sidste XNUMX timer.

Hvis du bruger Elasticsearch til at gemme sporingsspænd, kan du bruge et simpelt Golang-værktøj, som vil bygge den samme graf på få minutter ved hjælp af funktionerne og mulighederne i Elasticsearch.

Netramesh - letvægts servicenetløsning

Sådan bruger du Netramesh

Netra kan nemt tilføjes til enhver tjeneste, der kører enhver orkestrator. Du kan se et eksempel her.

Netra har i øjeblikket ikke mulighed for automatisk at implementere sidevogne til tjenester, men der er planer om implementering.

Fremtiden for Netramesh

hovedmål Netramesh er at opnå minimale ressourceomkostninger og høj ydeevne, hvilket giver grundlæggende muligheder for observerbarhed og kontrol af kommunikation mellem tjenester.

I fremtiden vil Netramesh understøtte andre applikationslagsprotokoller udover HTTP. L7-routing vil være tilgængelig i den nærmeste fremtid.

Brug Netramesh, hvis du støder på lignende problemer, og skriv til os med spørgsmål og forslag.

Kilde: www.habr.com

Tilføj en kommentar