Netramesh - řešení lehkého servisního pletiva

S přechodem od monolitické aplikace k architektuře mikroslužeb čelíme novým výzvám.

V monolitické aplikaci je obvykle docela snadné určit, ve které části systému došlo k chybě. S největší pravděpodobností je problém v kódu samotného monolitu nebo v databázi. Když ale začneme hledat problém v architektuře mikroslužeb, vše už není tak zřejmé. Musíme najít celou cestu, kterou požadavek prošel od začátku do konce, a vybrat ji ze stovek mikroslužeb. Navíc mnoho z nich má také vlastní úložiště, což může také způsobit logické chyby, stejně jako problémy s výkonem a odolností proti chybám.

Netramesh - řešení lehkého servisního pletiva

Dlouho jsem hledal nástroj, který by mi pomohl vyrovnat se s takovými problémy (psal jsem o tom na Habré: 1, 2), ale nakonec jsem vytvořil vlastní open source řešení. V tomto článku mluvím o výhodách přístupu service mesh a sdílím nový nástroj pro jeho implementaci.

Distribuované trasování je běžné řešení problému hledání chyb v distribuovaných systémech. Ale co když tento přístup ke shromažďování informací o síťových interakcích ještě nebyl v systému implementován, nebo, což je horší, v části systému již funguje správně, ale v části ne, protože nebyl přidán do starých služeb ? K určení přesné příčiny problému je nutné mít úplný obraz o tom, co se v systému děje. Je obzvláště důležité porozumět tomu, které mikroslužby jsou zapojeny do klíčových kritických obchodních cest.

Zde nám může pomoci přístup service mesh, který se bude zabývat veškerým aparátem pro sběr síťových informací na nižší úrovni, než fungují samotné služby. Tento přístup nám umožňuje zachytit veškerý provoz a analyzovat jej za běhu. Navíc o tom aplikace ani nemusí nic vědět.

Servisní síťový přístup

Hlavní myšlenkou přístupu service mesh je přidat další infrastrukturní vrstvu přes síť, což nám umožní dělat cokoli s interakcí mezi službami. Většina implementací funguje následovně: ke každé mikroslužbě je přidán další kontejner postranního vozíku s transparentním proxy, přes který prochází veškerý příchozí a odchozí provoz služby. A to je právě místo, kde můžeme provádět vyvažování klientů, uplatňovat bezpečnostní zásady, ukládat omezení na počet požadavků a shromažďovat důležité informace o interakci služeb ve výrobě.

Netramesh - řešení lehkého servisního pletiva

Řešení

Již existuje několik implementací tohoto přístupu: Stejný и linkerd2. Poskytují mnoho funkcí hned po vybalení. Zároveň však přichází velká režie na zdroje. Navíc, čím větší je klastr, ve kterém takový systém funguje, tím více zdrojů bude potřeba na údržbu nové infrastruktury. Ve společnosti Avito provozujeme clustery kubernetes, které obsahují tisíce instancí služeb (a jejich počet stále rychle roste). Ve své aktuální implementaci Istio spotřebovává ~300 Mb RAM na instanci služby. Vzhledem k velkému množství možností má transparentní balancování vliv i na celkovou dobu odezvy služeb (až 10 ms).

V důsledku toho jsme se podívali přesně na to, jaké schopnosti právě teď potřebujeme, a rozhodli jsme se, že hlavním důvodem, proč jsme začali implementovat taková řešení, byla schopnost transparentně shromažďovat informace o sledování z celého systému. Chtěli jsme mít také kontrolu nad interakcí služeb a dělat různé manipulace s hlavičkami, které se mezi službami přenášejí.

V důsledku toho jsme dospěli k našemu rozhodnutí:  Netramesh.

Netramesh

Netramesh je odlehčené řešení sítě služeb se schopností nekonečně škálovat bez ohledu na počet služeb v systému.

Hlavním cílem nového řešení byla nízká režie zdrojů a vysoký výkon. Mezi hlavní funkce jsme okamžitě chtěli být schopni transparentně posílat trasovací rozsahy do našeho systému Jaeger.

Dnes je většina cloudových řešení implementována v Golangu. A samozřejmě to má své důvody. Psaní síťových aplikací v Golangu, které pracují asynchronně s I/O a škálují se napříč jádry podle potřeby, je pohodlné a docela jednoduché. A co je také velmi důležité, výkon je dostatečný k vyřešení tohoto problému. Proto jsme také zvolili Golang.

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

Naše úsilí jsme zaměřili na dosažení maximální produktivity. Pro řešení, které je nasazeno vedle každé instance služby, je vyžadována malá spotřeba paměti RAM a času CPU. A samozřejmě by zpoždění odezvy mělo být také malé.

Podívejme se, jaké výsledky jsme získali.

RAM

Netramesh spotřebuje ~10Mb bez provozu a maximálně 50Mb se zatížením až 10000 XNUMX RPS na instanci.

Istio envoy proxy vždy spotřebuje ~ 300 Mb v našich clusterech s tisíci instancemi. To neumožňuje jeho škálování na celý cluster.

Netramesh - řešení lehkého servisního pletiva

Netramesh - řešení lehkého servisního pletiva

S Netramesh jsme dosáhli ~10x snížení spotřeby paměti.

procesor

Využití CPU je při zátěži relativně stejné. Závisí to na počtu požadavků za jednotku času na sajdkáru. Hodnoty při 3000 žádostech za sekundu ve špičce:

Netramesh - řešení lehkého servisního pletiva

Netramesh - řešení lehkého servisního pletiva

Je tu ještě jeden důležitý bod: Netramesh – řešení bez řídicí roviny a bez zátěže nespotřebovává čas CPU. S Istio postranní vozíky vždy aktualizují koncové body služby. V důsledku toho vidíme tento obrázek bez zatížení:

Netramesh - řešení lehkého servisního pletiva

Pro komunikaci mezi službami používáme HTTP/1. Nárůst doby odezvy pro Istio při proxy přes envoy byl až 5-10 ms, což je poměrně hodně pro služby, které jsou připraveny reagovat během milisekund. S Netramesh se tento čas snížil na 0.5-2 ms.

Škálovatelnost

Malé množství zdrojů spotřebovaných každým proxy serverem umožňuje umístit jej vedle každé služby. Netramesh byl záměrně vytvořen bez součásti řídicí roviny, aby byl každý sajdkár jednoduše lehký. V řešeních servisní sítě často řídicí rovina distribuuje informace o zjištění služby do každého postranního vozíku. Spolu s tím přichází informace o timeoutech a nastavení balancování. To vše vám umožňuje dělat spoustu užitečných věcí, ale bohužel to nafukuje postranní vozíky.

Zjištění služby

Netramesh - řešení lehkého servisního pletiva

Netramesh nepřidává žádné další mechanismy pro zjišťování služeb. Veškerý provoz je transparentně zprostředkován prostřednictvím postranního vozíku netra.

Netramesh podporuje aplikační protokol HTTP/1. K jeho definování se používá konfigurovatelný seznam portů. Typicky má systém několik portů, přes které probíhá HTTP komunikace. Například pro interakci mezi službami a externími požadavky používáme 80, 8890, 8080. V tomto případě je lze nastavit pomocí proměnné prostředí NETRA_HTTP_PORTS.

Pokud používáte Kubernetes jako orchestrátor a jeho mechanismus entity Service pro komunikaci v rámci clusteru mezi službami, mechanismus zůstane úplně stejný. Nejprve mikroslužba získá IP adresu služby pomocí kube-dns a otevře k ní nové připojení. Toto spojení je nejprve navázáno s místním netra-sidecar a všechny TCP pakety nejprve dorazí na netra. Dále netra-sidecar naváže spojení s původní destinací. NAT na pod IP na nodu zůstává úplně stejný jako bez netra.

Distribuované sledování a předávání kontextu

Netramesh poskytuje funkce potřebné k odesílání trasovacích úseků o interakcích HTTP. Netra-sidecar analyzuje HTTP protokol, měří zpoždění požadavků a extrahuje potřebné informace z HTTP hlaviček. Nakonec získáme všechny stopy v jediném systému Jaeger. Pro jemnou konfiguraci můžete také použít proměnné prostředí poskytované oficiální knihovnou knihovna jaeger go.

Netramesh - řešení lehkého servisního pletiva

Netramesh - řešení lehkého servisního pletiva

Ale je tu problém. Dokud služby nevygenerují a neodešlou speciální hlavičku uber, neuvidíme v systému připojené rozsahy trasování. A to je to, co potřebujeme, abychom rychle našli příčinu problémů. Netramesh má opět řešení. Proxy čtou HTTP hlavičky, a pokud neobsahují uber trace id, vygenerují je. Netramesh také ukládá informace o příchozích a odchozích požadavcích do postranního vozíku a porovnává je tím, že je obohatí o potřebné hlavičky odchozích požadavků. Vše, co musíte ve službách udělat, je odeslat pouze jednu hlavičku X-Request-Id, kterou lze konfigurovat pomocí proměnné prostředí NETRA_HTTP_REQUEST_ID_HEADER_NAME. Chcete-li řídit velikost kontextu v Netramesh, můžete nastavit následující proměnné prostředí: NETRA_TRACING_CONTEXT_EXPIRATION_MILLISECONDS (doba, po kterou bude kontext uložen) a NETRA_TRACING_CONTEXT_CLEANUP_INTERVAL (frekvence čištění kontextu).

Je také možné kombinovat více cest ve vašem systému tak, že je označíte speciálním tokenem relace. Netra umožňuje instalaci HTTP_HEADER_TAG_MAP pro přeměnu hlaviček HTTP na odpovídající značky rozsahu sledování. To může být užitečné zejména pro testování. Po absolvování funkčního testu můžete vidět, která část systému byla ovlivněna filtrováním odpovídajícím klíčem relace.

Určení zdroje požadavku

Chcete-li zjistit, odkud požadavek přišel, můžete použít funkci automatického přidání záhlaví se zdrojem. Použití proměnné prostředí NETRA_HTTP_X_SOURCE_HEADER_NAME Můžete zadat název záhlaví, který se automaticky nainstaluje. Používáním NETRA_HTTP_X_SOURCE_VALUE můžete nastavit hodnotu, na kterou bude hlavička X-Source nastavena pro všechny odchozí požadavky.

To umožňuje distribuci této užitečné hlavičky rovnoměrně po celé síti. Poté jej můžete použít ve službách a přidat do protokolů a metrik.

Traffic routing a Netramesh internals

Netramesh se skládá ze dvou hlavních složek. První, netra-init, nastavuje síťová pravidla pro zachycování provozu. Používá pravidla přesměrování iptables k zachycení veškerého provozu nebo jeho části na postranním vozíku, který je druhou hlavní součástí Netramesh. Můžete nakonfigurovat, které porty mají být zachyceny pro příchozí a odchozí TCP relace: INBOUND_INTERCEPT_PORTS, OUTBOUND_INTERCEPT_PORTS.

Nástroj má také zajímavou funkci - pravděpodobnostní směrování. Pokud používáte Netramesh výhradně pro shromažďování rozpětí trasování, pak v produkčním prostředí můžete ušetřit zdroje a povolit pravděpodobnostní směrování pomocí proměnných NETRA_INBOUND_PROBABILITY и NETRA_OUTBOUND_PROBABILITY (od 0 do 1). Výchozí hodnota je 1 (veškerý provoz je zachycen).

Po úspěšném odposlechu netra sajdkára přijímá nové spojení a používá SO_ORIGINAL_DST možnost zásuvky pro získání původního cíle. Netra poté otevře nové spojení na původní IP adresu a naváže obousměrnou TCP komunikaci mezi stranami, přičemž naslouchá veškerému procházejícímu provozu. Pokud je port definován jako HTTP, Netra se jej pokusí analyzovat a sledovat. Pokud selže analýza HTTP, Netra přejde zpět na TCP a transparentně zprostředkuje bajty.

Vytvoření grafu závislosti

Po obdržení velkého množství informací o sledování v Jaegeru chci získat kompletní graf interakcí v systému. Ale pokud je váš systém dost zatížený a denně se hromadí miliardy trasovacích úseků, jejich agregace není tak snadný úkol. Existuje oficiální způsob, jak to udělat: jiskrové závislosti. Vytvoření kompletního grafu však zabere hodiny a donutí vás stáhnout celý soubor dat z Jaeger za posledních XNUMX hodin.

Pokud používáte Elasticsearch k ukládání rozpětí trasování, můžete použít jednoduchý nástroj Golang, který vytvoří stejný graf během několika minut pomocí funkcí a možností Elasticsearch.

Netramesh - řešení lehkého servisního pletiva

Jak používat Netramesh

Netra lze snadno přidat do jakékoli služby provozující jakýkoli orchestrátor. Můžete vidět příklad zde.

Netra v tuto chvíli nemá možnost automaticky implementovat postranní vozíky do služeb, ale existují plány na implementaci.

Budoucnost Netrameshe

hlavní cíl Netramesh je dosáhnout minimálních nákladů na zdroje a vysokého výkonu, poskytující základní schopnosti pro pozorovatelnost a kontrolu mezislužební komunikace.

V budoucnu bude Netramesh podporovat další protokoly aplikační vrstvy kromě HTTP. Směrování L7 bude k dispozici v blízké budoucnosti.

Pokud narazíte na podobné problémy, použijte Netramesh a napište nám s dotazy a návrhy.

Zdroj: www.habr.com

Přidat komentář