När vi går från en monolitisk applikation till en mikrotjänstarkitektur står vi inför nya utmaningar.
I en monolitisk applikation är det vanligtvis ganska lätt att avgöra i vilken del av systemet felet uppstod. Troligtvis ligger problemet i koden för själva monoliten eller i databasen. Men när vi börjar leta efter ett problem i en mikrotjänstarkitektur är allt inte längre så självklart. Vi måste hitta hela vägen som begäran tog från början till slut och välja den från hundratals mikrotjänster. Dessutom har många av dem också sina egna lagringsmöjligheter, vilket också kan orsaka logiska fel, liksom problem med prestanda och feltolerans.
Jag har letat länge efter ett verktyg som skulle hjälpa till att hantera sådana problem (jag skrev om detta på Habré:
Distribuerad spårning är en vanlig lösning på problemet med att hitta fel i distribuerade system. Men vad händer om detta tillvägagångssätt för att samla in information om nätverksinteraktioner ännu inte har implementerats i systemet, eller ännu värre, i en del av systemet fungerar det redan korrekt, men delvis inte, eftersom det inte har lagts till i gamla tjänster ? För att fastställa den exakta grundorsaken till ett problem är det nödvändigt att ha en fullständig bild av vad som händer i systemet. Det är särskilt viktigt att förstå vilka mikrotjänster som är involverade i viktiga affärskritiska vägar.
Här kan servicemesh-metoden komma till vår hjälp, som kommer att hantera alla maskiner för att samla in nätverksinformation på en nivå som är lägre än vad tjänsterna själva fungerar. Detta tillvägagångssätt gör att vi kan fånga upp all trafik och analysera den i farten. Dessutom behöver applikationer inte ens veta något om det.
Service mesh tillvägagångssätt
Huvudidén med servicemesh-metoden är att lägga till ytterligare ett infrastrukturlager över nätverket, vilket gör att vi kan göra vad som helst med inter-service interaktion. De flesta implementeringar fungerar enligt följande: en extra sidovagnsbehållare med en transparent proxy läggs till varje mikrotjänst, genom vilken all inkommande och utgående trafik för tjänsten skickas. Och det här är själva platsen där vi kan göra klientbalansering, tillämpa säkerhetspolicyer, införa begränsningar för antalet förfrågningar och samla in viktig information om interaktionen mellan tjänster i produktionen.
Решения
Det finns redan flera implementeringar av detta tillvägagångssätt:
Som ett resultat av detta tittade vi på exakt vilka möjligheter vi behövde just nu och kom fram till att den främsta anledningen till att vi började implementera sådana lösningar var möjligheten att samla in spårningsinformation från hela systemet på ett transparent sätt. Vi ville också ha kontroll över interaktionen av tjänster och göra olika manipulationer med headers som överförs mellan tjänster.
Som ett resultat kom vi till vårt beslut:
Netramesh
Huvudmålen med den nya lösningen var låg resurskostnad och hög prestanda. Bland huvudfunktionerna ville vi omedelbart kunna skicka spårningsspann till vårt Jaeger-system på ett transparent sätt.
Idag är de flesta molnlösningar implementerade i Golang. Och det finns förstås skäl till detta. Att skriva nätverksapplikationer i Golang som fungerar asynkront med I/O och skalas över kärnor efter behov är bekvämt och ganska enkelt. Och vad som också är mycket viktigt, prestandan är tillräcklig för att lösa detta problem. Därför valde vi också Golang.
Производительность
Vi har fokuserat våra ansträngningar på att uppnå maximal produktivitet. För en lösning som distribueras bredvid varje instans av tjänsten krävs en liten förbrukning av RAM och CPU-tid. Och naturligtvis bör svarsfördröjningen också vara liten.
Låt oss se vilka resultat vi fick.
RAM
Netramesh förbrukar ~10Mb utan trafik och 50Mb maximalt med en belastning på upp till 10000 XNUMX RPS per instans.
Istio envoy proxy förbrukar alltid ~300 Mb i våra kluster med tusentals instanser. Detta tillåter inte att den skalas till hela klustret.
Med Netramesh fick vi en ~10x minskning av minnesförbrukningen.
CPU
CPU-användningen är relativt lika under belastning. Det beror på antalet förfrågningar per tidsenhet till sidvagnen. Värden vid 3000 förfrågningar per sekund vid topp:
Det finns ytterligare en viktig punkt: Netramesh - en lösning utan kontrollplan och utan belastning förbrukar inte CPU-tid. Med Istio uppdaterar sidvagnar alltid tjänstens slutpunkter. Som ett resultat kan vi se den här bilden utan belastning:
Vi använder HTTP/1 för kommunikation mellan tjänster. Ökningen av svarstid för Istio vid proxysändning via envoy var upp till 5-10ms, vilket är ganska mycket för tjänster som är redo att svara på en millisekund. Med Netramesh har denna tid minskat till 0.5-2ms.
Skalbarhet
Den lilla mängd resurser som förbrukas av varje proxy gör det möjligt att placera den bredvid varje tjänst. Netramesh skapades avsiktligt utan en kontrollplanskomponent för att helt enkelt hålla varje sidovagn lätt. Ofta i servicenätlösningar distribuerar kontrollplanet serviceupptäcktsinformation till varje sidovagn. Tillsammans kommer information om timeouts och balanseringsinställningar. Allt detta låter dig göra många användbara saker, men tyvärr sväller det sidvagnar i storlek.
Service upptäckt
Netramesh lägger inte till några ytterligare mekanismer för att upptäcka tjänster. All trafik proxias transparent genom netra sidovagn.
Netramesh stöder HTTP/1-applikationsprotokoll. För att definiera det används en konfigurerbar lista över portar. Vanligtvis har systemet flera portar genom vilka HTTP-kommunikation sker. Till exempel använder vi 80, 8890, 8080 för interaktion mellan tjänster och externa förfrågningar. I det här fallet kan de ställas in med en miljövariabel NETRA_HTTP_PORTS
.
Om du använder Kubernetes som en orkestrator och dess tjänsteenhetsmekanism för intra-klusterkommunikation mellan tjänster, förblir mekanismen exakt densamma. Först erhåller mikrotjänsten en tjänst IP-adress med hjälp av kube-dns och öppnar en ny anslutning till den. Denna anslutning upprättas först med den lokala netra-sidecaren och alla TCP-paket anländer initialt till netra. Därefter upprättar netra-sidecar en förbindelse med den ursprungliga destinationen. NAT på pod IP på noden förblir exakt densamma som utan netra.
Distribuerad spårning och kontextvidarebefordran
Netramesh tillhandahåller den funktionalitet som behövs för att skicka spårningsspann om HTTP-interaktioner. Netra-sidecar analyserar HTTP-protokollet, mäter begärandefördröjningar och extraherar nödvändig information från HTTP-huvuden. I slutändan får vi alla spår i ett enda Jaeger-system. För finkornig konfiguration kan du också använda de miljövariabler som tillhandahålls av det officiella biblioteket
Men det är ett problem. Tills tjänster genererar och skickar en speciell uber-header kommer vi inte att se anslutna spårningsspann i systemet. Och det här är vad vi behöver för att snabbt hitta orsaken till problemen. Även här har Netramesh en lösning. Proxyer läser HTTP-rubriker och, om de inte innehåller spårnings-id:t för uber, genererar du ett. Netramesh lagrar också information om inkommande och utgående förfrågningar i en sidovagn och matchar dem genom att berika dem med de nödvändiga utgående förfrågningarnas rubriker. Allt du behöver göra i tjänsterna är att bara skicka en rubrik X-Request-Id
, som kan konfigureras med en miljövariabel NETRA_HTTP_REQUEST_ID_HEADER_NAME
. För att styra storleken på sammanhanget i Netramesh kan du ställa in följande miljövariabler: NETRA_TRACING_CONTEXT_EXPIRATION_MILLISECONDS
(den tid under vilken sammanhanget kommer att lagras) och NETRA_TRACING_CONTEXT_CLEANUP_INTERVAL
(frekvens av kontextrensning).
Det är också möjligt att kombinera flera sökvägar på ditt system genom att markera dem med en speciell sessionstoken. Netra låter dig installera HTTP_HEADER_TAG_MAP
för att omvandla HTTP-rubriker till motsvarande spårningsspan-taggar. Detta kan vara särskilt användbart för testning. Efter att ha klarat funktionstestet kan du se vilken del av systemet som påverkades av filtrering med motsvarande sessionsnyckel.
Fastställande av förfrågningskällan
För att avgöra var begäran kom ifrån kan du använda funktionen att automatiskt lägga till en rubrik med källan. Använder en miljövariabel NETRA_HTTP_X_SOURCE_HEADER_NAME
Du kan ange ett rubriknamn som kommer att installeras automatiskt. Genom att använda NETRA_HTTP_X_SOURCE_VALUE
du kan ställa in värdet som X-Source-huvudet kommer att ställas in på för alla utgående förfrågningar.
Detta gör att distributionen av denna användbara rubrik kan distribueras enhetligt över hela nätverket. Sedan kan du använda det i tjänster och lägga till det i loggar och mätvärden.
Trafikdirigering och Netramesh interns
Netramesh består av två huvudkomponenter. Den första, netra-init, sätter nätverksregler för att fånga upp trafik. Han använder INBOUND_INTERCEPT_PORTS, OUTBOUND_INTERCEPT_PORTS
.
Verktyget har också en intressant funktion - probabilistisk routing. Om du använder Netramesh enbart för att samla in spårningsintervall, kan du i en produktionsmiljö spara resurser och möjliggöra probabilistisk routing med hjälp av variabler NETRA_INBOUND_PROBABILITY
и NETRA_OUTBOUND_PROBABILITY
(från 0 till 1). Standardvärdet är 1 (all trafik avlyssnas).
Efter lyckad avlyssning accepterar netra sidovagn den nya anslutningen och använder SO_ORIGINAL_DST
socket alternativ för att få den ursprungliga destinationen. Netra öppnar sedan en ny anslutning till den ursprungliga IP-adressen och upprättar tvåvägs TCP-kommunikation mellan parterna och lyssnar på all trafik som passerar igenom. Om porten är definierad som HTTP, försöker Netra analysera och spåra den. Om HTTP-analys misslyckas, faller Netra tillbaka till TCP och proxar transparent byte.
Bygga en beroendegraf
Efter att ha fått en stor mängd spårningsinformation i Jaeger vill jag få en komplett graf över interaktioner i systemet. Men om ditt system är ganska laddat och miljarder spårningsintervall ackumuleras per dag, blir det inte så lätt att aggregera dem. Det finns ett officiellt sätt att göra detta:
Om du använder Elasticsearch för att lagra spårningsintervall kan du använda
Hur man använder Netramesh
Netra kan enkelt läggas till i vilken tjänst som helst som kör vilken orkestrator som helst. Du kan se ett exempel
Just nu har Netra inte möjlighet att automatiskt implementera sidovagnar till tjänster, men det finns planer på implementering.
Framtiden för Netramesh
huvudmål
I framtiden kommer Netramesh att stödja andra applikationslagerprotokoll förutom HTTP. L7-routing kommer att finnas tillgänglig inom en snar framtid.
Använd Netramesh om du stöter på liknande problem och skriv till oss med frågor och förslag.
Källa: will.com