Netramesh - lett servicenettingsløsning

Når vi går fra en monolitisk applikasjon til en mikrotjenestearkitektur, står vi overfor nye utfordringer.

I en monolitisk applikasjon er det vanligvis ganske enkelt å finne ut hvilken del av systemet feilen oppstod i. Mest sannsynlig er problemet i koden til selve monolitten, eller i databasen. Men når vi begynner å lete etter et problem i en mikrotjenestearkitektur, er ikke alt så åpenbart lenger. Vi må finne hele banen som forespørselen tok fra start til slutt og velge den fra hundrevis av mikrotjenester. Dessuten har mange av dem også egne lagringsanlegg, som også kan forårsake logiske feil, samt problemer med ytelse og feiltoleranse.

Netramesh - lett servicenettingsløsning

Jeg har lenge lett etter et verktøy som kan hjelpe med å takle slike problemer (jeg skrev om dette på Habré: 1, 2), men til slutt laget jeg min egen åpen kildekode-løsning. I denne artikkelen snakker jeg om fordelene med service mesh-tilnærmingen og deler et nytt verktøy for implementeringen.

Distribuert sporing er en vanlig løsning på problemet med å finne feil i distribuerte systemer. Men hva om denne tilnærmingen til å samle informasjon om nettverksinteraksjoner ennå ikke er implementert i systemet, eller enda verre, i en del av systemet fungerer den allerede riktig, men delvis ikke, siden den ikke er lagt til gamle tjenester ? For å finne den nøyaktige årsaken til et problem, er det nødvendig å ha et fullstendig bilde av hva som skjer i systemet. Det er spesielt viktig å forstå hvilke mikrotjenester som er involvert i viktige forretningskritiske veier.

Her kan service mesh-tilnærmingen komme oss til hjelp, som vil håndtere alle maskineriet for å samle nettverksinformasjon på et nivå lavere enn tjenestene selv opererer. Denne tilnærmingen lar oss avskjære all trafikk og analysere den på fly. Dessuten trenger ikke applikasjoner engang å vite noe om det.

Service mesh-tilnærming

Hovedideen med service mesh-tilnærmingen er å legge til et nytt infrastrukturlag over nettverket, som vil tillate oss å gjøre hva som helst med inter-service interaksjon. De fleste implementeringer fungerer som følger: en ekstra sidevognbeholder med en gjennomsiktig proxy legges til hver mikrotjeneste, som all innkommende og utgående trafikk av tjenesten sendes gjennom. Og dette er selve stedet hvor vi kan gjøre klientbalansering, anvende sikkerhetspolicyer, pålegge begrensninger på antall forespørsler og samle inn viktig informasjon om samspillet mellom tjenester i produksjonen.

Netramesh - lett servicenettingsløsning

Løsninger

Det er allerede flere implementeringer av denne tilnærmingen: Samme и linkerd2. De gir mange funksjoner ut av esken. Men samtidig kommer det store overhead på ressurser. Dessuten, jo større klyngen et slikt system opererer i, jo mer ressurser vil det kreves for å vedlikeholde den nye infrastrukturen. Hos Avito driver vi kubernetes-klynger som inneholder tusenvis av tjenesteforekomster (og antallet fortsetter å vokse raskt). I sin nåværende implementering bruker Istio ~300 Mb RAM per tjenesteforekomst. På grunn av det store antallet muligheter, påvirker gjennomsiktig balansering også den totale responstiden til tjenestene (opptil 10 ms).

Som et resultat så vi på nøyaktig hvilke evner vi trengte akkurat nå, og bestemte oss for at hovedgrunnen til at vi begynte å implementere slike løsninger var muligheten til å samle sporingsinformasjon fra hele systemet på en transparent måte. Vi ønsket også å ha kontroll over interaksjonen av tjenester og gjøre ulike manipulasjoner med overskriftene som overføres mellom tjenester.

Som et resultat kom vi til vår beslutning:  Netramesh.

Netramesh

Netramesh er en lett service mesh-løsning med mulighet til å skalere i det uendelige, uavhengig av antall tjenester i systemet.

Hovedmålene for den nye løsningen var lav ressursoverhead og høy ytelse. Blant hovedfunksjonene ønsket vi umiddelbart å kunne sende sporingsspenn på en transparent måte til vårt Jaeger-system.

I dag er de fleste skyløsninger implementert i Golang. Og det er selvfølgelig grunner til dette. Å skrive nettverksapplikasjoner i Golang som fungerer asynkront med I/O og skalerer på tvers av kjerner etter behov er praktisk og ganske enkelt. Og det som også er veldig viktig, ytelsen er tilstrekkelig til å løse dette problemet. Derfor valgte vi også Golang.

Производительность

Vi har fokusert vår innsats på å oppnå maksimal produktivitet. For en løsning som er distribuert ved siden av hver forekomst av tjenesten, kreves et lite forbruk av RAM og CPU-tid. Og responsforsinkelsen bør selvfølgelig også være liten.

La oss se hvilke resultater vi fikk.

RAM

Netramesh bruker ~10 Mb uten trafikk og maksimalt 50 Mb med en belastning på opptil 10000 XNUMX RPS per forekomst.

Istio envoy proxy bruker alltid ~300 Mb i våre klynger med tusenvis av forekomster. Dette tillater ikke at den skaleres til hele klyngen.

Netramesh - lett servicenettingsløsning

Netramesh - lett servicenettingsløsning

Med Netramesh fikk vi en ~10x reduksjon i minneforbruk.

prosessor

CPU-bruken er relativt lik under belastning. Det avhenger av antall forespørsler per tidsenhet til sidevognen. Verdier ved 3000 forespørsler per sekund på topp:

Netramesh - lett servicenettingsløsning

Netramesh - lett servicenettingsløsning

Det er enda et viktig poeng: Netramesh - en løsning uten kontrollplan og uten belastning bruker ikke CPU-tid. Med Istio oppdaterer sidevogner alltid tjenesteendepunkter. Som et resultat kan vi se dette bildet uten belastning:

Netramesh - lett servicenettingsløsning

Vi bruker HTTP/1 for kommunikasjon mellom tjenester. Økningen i responstid for Istio ved proxying gjennom envoy var opptil 5-10ms, noe som er ganske mye for tjenester som er klare til å svare på et millisekund. Med Netramesh har denne tiden gått ned til 0.5-2ms.

Skalerbarhet

Den lille mengden ressurser som forbrukes av hver proxy gjør det mulig å plassere den ved siden av hver tjeneste. Netramesh ble med vilje laget uten en kontrollplankomponent for ganske enkelt å holde hver sidevogn lett. Ofte i servicenettløsninger distribuerer kontrollplanet serviceoppdagelsesinformasjon til hver sidevogn. Sammen med det kommer informasjon om tidsavbrudd og balanseinnstillinger. Alt dette lar deg gjøre mange nyttige ting, men dessverre blåser det opp sidevogner i størrelse.

Tjenesteoppdagelse

Netramesh - lett servicenettingsløsning

Netramesh legger ikke til noen ekstra mekanismer for tjenesteoppdagelse. All trafikk sendes transparent gjennom netra sidevogn.

Netramesh støtter HTTP/1-applikasjonsprotokoll. For å definere det, brukes en konfigurerbar liste over porter. Systemet har vanligvis flere porter som HTTP-kommunikasjon skjer gjennom. For eksempel bruker vi 80, 8890, 8080 for interaksjon mellom tjenester og eksterne forespørsler. I dette tilfellet kan de settes ved hjelp av en miljøvariabel NETRA_HTTP_PORTS.

Hvis du bruker Kubernetes som en orkestrator og dens tjenesteenhetsmekanisme for intra-klyngekommunikasjon mellom tjenester, forblir mekanismen nøyaktig den samme. Først skaffer mikrotjenesten en tjeneste IP-adresse ved hjelp av kube-dns og åpner en ny tilkobling til den. Denne forbindelsen etableres først med den lokale netra-sidevognen, og alle TCP-pakker ankommer først til netra. Deretter etablerer netra-sidecar en forbindelse med den opprinnelige destinasjonen. NAT på pod IP på noden forblir nøyaktig den samme som uten netra.

Distribuert sporing og kontekstvideresending

Netramesh gir funksjonaliteten som trengs for å sende sporingsspenn om HTTP-interaksjoner. Netra-sidecar analyserer HTTP-protokollen, måler forespørselsforsinkelser og trekker ut nødvendig informasjon fra HTTP-hoder. Til syvende og sist får vi alle sporene i et enkelt Jaeger-system. For finkornet konfigurasjon kan du også bruke miljøvariablene fra det offisielle biblioteket jaeger go bibliotek.

Netramesh - lett servicenettingsløsning

Netramesh - lett servicenettingsløsning

Men det er et problem. Inntil tjenester genererer og sender en spesiell uber-header, vil vi ikke se tilkoblede sporingsspenn i systemet. Og det er dette vi trenger for raskt å finne årsaken til problemene. Her har Netramesh igjen en løsning. Proxyer leser HTTP-overskrifter, og hvis de ikke inneholder uber-sporings-IDen, genererer du en. Netramesh lagrer også informasjon om innkommende og utgående forespørsler i en sidevogn og matcher dem ved å berike dem med de nødvendige utgående forespørselshodene. Alt du trenger å gjøre i tjenestene er å sende bare én overskrift X-Request-Id, som kan konfigureres ved hjelp av en miljøvariabel NETRA_HTTP_REQUEST_ID_HEADER_NAME. For å kontrollere størrelsen på konteksten i Netramesh, kan du angi følgende miljøvariabler: NETRA_TRACING_CONTEXT_EXPIRATION_MILLISECONDS (tiden som konteksten vil bli lagret for) og NETRA_TRACING_CONTEXT_CLEANUP_INTERVAL (hyppighet av kontekstopprydding).

Det er også mulig å kombinere flere baner på systemet ditt ved å merke dem med et spesielt økttoken. Netra lar deg installere HTTP_HEADER_TAG_MAP for å gjøre HTTP-hoder om til tilsvarende sporingsspenn-tagger. Dette kan være spesielt nyttig for testing. Etter å ha bestått funksjonstesten kan du se hvilken del av systemet som ble berørt av filtrering etter den tilsvarende øktnøkkelen.

Bestemme forespørselskilden

For å finne ut hvor forespørselen kom fra, kan du bruke funksjonaliteten til automatisk å legge til en overskrift med kilden. Bruke en miljøvariabel NETRA_HTTP_X_SOURCE_HEADER_NAME Du kan spesifisere et overskriftsnavn som vil bli installert automatisk. Ved bruk av NETRA_HTTP_X_SOURCE_VALUE du kan angi verdien som X-Source-overskriften skal settes til for alle utgående forespørsler.

Dette gjør at distribusjonen av denne nyttige overskriften kan distribueres jevnt over hele nettverket. Deretter kan du bruke det i tjenester og legge det til logger og beregninger.

Trafikkruting og Netramesh internals

Netramesh består av to hovedkomponenter. Den første, netra-init, setter nettverksregler for å avskjære trafikk. Han bruker iptables omdirigeringsregler å avskjære hele eller deler av trafikken på sidevogn, som er den andre hovedkomponenten i Netramesh. Du kan konfigurere hvilke porter som må fanges opp for innkommende og utgående TCP-økter: INBOUND_INTERCEPT_PORTS, OUTBOUND_INTERCEPT_PORTS.

Verktøyet har også en interessant funksjon - probabilistisk ruting. Hvis du bruker Netramesh utelukkende for å samle sporingsspenn, kan du i et produksjonsmiljø spare ressurser og aktivere probabilistisk ruting ved hjelp av variabler NETRA_INBOUND_PROBABILITY и NETRA_OUTBOUND_PROBABILITY (fra 0 til 1). Standardverdien er 1 (all trafikk blir fanget opp).

Etter vellykket avlytting aksepterer netra sidevogn den nye forbindelsen og bruken SO_ORIGINAL_DST socket-alternativ for å få den opprinnelige destinasjonen. Netra åpner deretter en ny forbindelse til den opprinnelige IP-adressen og etablerer toveis TCP-kommunikasjon mellom partene, og lytter til all trafikk som går gjennom. Hvis porten er definert som HTTP, prøver Netra å analysere og spore den. Hvis HTTP-parsing mislykkes, faller Netra tilbake til TCP og fullfører transparente byte.

Bygge en avhengighetsgraf

Etter å ha mottatt en stor mengde sporingsinformasjon i Jaeger, ønsker jeg å få en fullstendig graf over interaksjoner i systemet. Men hvis systemet ditt er ganske belastet og milliarder av sporingsspenn samler seg per dag, blir det ikke så lett å samle dem. Det er en offisiell måte å gjøre dette på: gnistavhengigheter. Det vil imidlertid ta timer å bygge en fullstendig graf og vil tvinge deg til å laste ned hele datasettet fra Jaeger de siste XNUMX timene.

Hvis du bruker Elasticsearch til å lagre sporingsspenn, kan du bruke et enkelt Golang-verktøy, som vil bygge den samme grafen på minutter ved å bruke funksjonene og egenskapene til Elasticsearch.

Netramesh - lett servicenettingsløsning

Hvordan bruke Netramesh

Netra kan enkelt legges til en hvilken som helst tjeneste som kjører en hvilken som helst orkestrator. Du kan se et eksempel her.

For øyeblikket har ikke Netra mulighet til automatisk å implementere sidevogner til tjenester, men det er planer om implementering.

Fremtiden til Netramesh

Hoved mål Netramesh er å oppnå minimale ressurskostnader og høy ytelse, og gi grunnleggende evner for observerbarhet og kontroll av kommunikasjon mellom tjenestene.

I fremtiden vil Netramesh støtte andre applikasjonslagsprotokoller i tillegg til HTTP. L7-ruting vil være tilgjengelig i nær fremtid.

Bruk Netramesh hvis du støter på lignende problemer og skriv til oss med spørsmål og forslag.

Kilde: www.habr.com

Legg til en kommentar