A Netramesh egy könnyű service mesh megoldás

A monolitikus alkalmazásról a mikroszolgáltatás-architektúrára való áttérés során új problémákkal találkozunk.

Monolitikus alkalmazás esetén általában elegendő csak meghatározni, hogy a rendszer mely részén történt a hiba. Valószínűleg a probléma a monolit kódjában vagy az adatbázisban keresendő. De amikor a mikroszolgáltatás-architektúrában próbáljuk megtalálni a problémát, ez már nem olyan nyilvánvaló. Meg kell találni az utat, amelyen a kérés az elejétől a végéig haladt, és ki kell emelni a százak között, amelyek mikroszolgáltatások. Ráadásul soknak saját tárolója van, ahol logikai hibák, teljesítmény- és megbízhatósági problémák is felmerülhetnek.

A Netramesh egy könnyű service mesh megoldás

Hosszú ideig kerestem egy eszközt, amely segítene megoldani az ilyen problémákat (erről a Habr-on írtam: 1, 2), de végül saját nyílt forráskódú megoldást készítettem. A cikkben a service mesh megközelítés előnyeiről írok, és megosztom az új eszközömet ennek megvalósításához.

A disztribuált tracing elterjedt megoldás a hibák keresésére elosztott rendszerekben. De mi van akkor, ha a rendszerben még nem került bevezetésre egy ilyen megközelítés a hálózati interakciók információgyűjtésében, vagy, ami még rosszabb, a rendszer egy részén már jól működik, míg a másik részén nem, mert a régi szolgáltatásokhoz nem adták hozzá? A probléma pontos gyökerének meghatározásához teljes képre van szükség arról, hogy mi történik a rendszerben. Különösen fontos megérteni, hogy mely mikroszolgáltatások játszanak szerepet az alapvetően üzletkritikus folyamatokban.

Itt segíthet nekünk a service mesh megközelítés, amely a szolgáltatások szintjén alacsonyabb szinten kezeli a hálózati információk gyűjtését. Ez a megközelítés lehetővé teszi számunkra, hogy elfogjuk az összes forgalmat és valós időben elemezzük azt. Ráadásul az alkalmazásoknak nem is kell tudniuk róla.

Service mesh megközelítés

A service mesh approach's main idea is to add another infrastructure layer over the network, allowing us to manage all aspects of inter-service communication. Most implementations work as follows: an additional sidecar container with a transparent proxy is added to each microservice, through which all incoming and outgoing traffic of the service is routed. This is where we can perform client-side load balancing, apply security policies, impose request limits, and gather vital information on service interactions in production.

A Netramesh egy könnyű service mesh megoldás

Megoldások

There are already several implementations of this approach: Istio és linkerd2. They offer a multitude of features out of the box. However, this also brings a significant resource overhead. Moreover, the larger the cluster in which such a system operates, the more resources are required to maintain the new infrastructure. At Avito, we operate Kubernetes clusters containing thousands of service instances (and their number continues to grow rapidly). In its current implementation, Istio consumes about 300Mb of RAM per service instance. Due to the numerous capabilities available, the transparent load balancing also impacts the total response time of services (up to 10ms).

As a result, we examined what specific capabilities we needed right now and concluded that the primary reason we began implementing such solutions was to gather tracing information from the entire system transparently. We also wanted to have control over service interactions and perform various manipulations with the headers passed between services.

Ultimately, we arrived at our solution:  Netramesh.

Netramesh

Netramesh — a lightweight service mesh solution with endless scalability regardless of the number of services in the system.

The main goals of the new solution were low resource overhead and high performance. We wanted to have the ability to transparently send tracing spans to our Jaeger system from the outset.

Manapság a legtöbb felhőalapú megoldás Golang nyelven valósul meg. Ennek természetesen megvannak a maga okai. A Golang nyelven írt hálózati alkalmazások kényelmesek és viszonylag egyszerűek, hiszen aszinkron módon képesek kezelni a bevitel-kivitelt és szükség szerint skálázódni a processzorok számát illetően. Ráadásul, ami szintén nagyon fontos, a teljesítmény elegendő ahhoz, hogy ezt a feladatot megoldhassa. Ezért mi is a Golang-ot választottuk.

Teljesítmény

Erőfeszítéseinket a maximális teljesítmény elérésére összpontosítottuk. Egy olyan megoldás esetében, amely minden szolgáltatás példány mellett telepítve van, alacsony memória- és processzoridő-fogyasztásra van szükség. Természetesen a válaszidőnek is alacsonynak kell lennie.

Nézzük meg, milyen eredmények születtek.

RAM

A Netramesh ~10Mb-ot fogyaszt, ha nincs forgalom, és maximum 50Mb-ot, ha 10000 RPS terhelésnek van kitéve egy példányon.

Az Istio envoy proxy mindig ~300Mb-ot fogyaszt a klaszterünkből, amelyben ezre számra találhatóak példányok. Ez nem teszi lehetővé a teljes klaszterre való skálázódást.

A Netramesh egy könnyű service mesh megoldás

A Netramesh egy könnyű service mesh megoldás

A Netramesh használatával ~10-szeres memóriafogyasztás-csökkenést értünk el.

CPU

A CPU használata terhelés alatt viszonylag azonos. Ez a sidecar-hoz egy időben érkező kérések számától függ. A csúcsértékek 3000 kéréssel másodpercenként a következőképpen alakulnak:

A Netramesh egy könnyű service mesh megoldás

A Netramesh egy könnyű service mesh megoldás

Van még egy fontos tényező: a Netramesh egy control plane nélküli megoldás, és terhelés hiányában nem fogyaszt processzoridőt. Az Istio sidecar-ja mindig frissíti a szolgáltatások végpontjait. A végeredmény egy ilyen kép terhelés nélkül:

A Netramesh egy könnyű service mesh megoldás

HTTP/1-et használunk a szolgáltatások közötti kommunikációra. Az Istio proxy-áláskor az envoy-on keresztül a válaszidő akár 5-10ms-ra is nőtt, ami elég sok azoknak a szolgáltatásoknak, melyek készen állnak az egymilliomod másodpercre való válaszadásra. A Netramesh esetében ez az idő 0.5-2ms-ra csökkent.

Skálázhatóság

A proxy-k által felhasznált kis mennyiségű erőforrás lehetővé teszi, hogy minden szolgáltatás mellett helyet kapjanak. A Netramesh-t szándékosan control plane összetevő nélkül alkották meg, hogy minden sidecar könnyen karbantartható maradjon. Gyakran a service mesh megoldásokban a control plane elosztja a szolgáltatás-felfedezés információját minden sidecar-hoz. Ezzel együtt érkezik a timeout és a terheléselosztási beállítások információja is. Mindez lehetővé teszi számos hasznos dolog elvégzését, de sajnálatos módon megnöveli a sidecar-ok méretét.

Szolgáltatás felfedezés

A Netramesh egy könnyű service mesh megoldás

A Netramesh nem ad hozzá semmilyen extra mechanizmust a szolgáltatás-felfedezéshez. Az összes forgalom átlátszóan kerül proxy-zásra a netra sidecar-on keresztül.

A Netramesh támogatja a HTTP/1 alkalmazási protokollt. A meghatározásához konfigurálható portlistát használunk. Általában a rendszerben több olyan port van, amelyeken HTTP-n keresztül történik a kommunikáció. Például számunkra a szolgáltatások és a külső kérések közötti interakció során a 80, 8890, 8080 portokat használjuk. Ilyenkor ezeket környezeti változó segítségével állíthatjuk be. NETRA_HTTP_PORTS.

Ha Kubernetes-t használsz orkestrátorként és a Service entitások mechanizmusát az intra-cluster szolgáltatások közötti interakcióhoz, akkor a mechanizmus pontosan ugyanaz marad. Először a mikroszolgáltatás a kube-dns segítségével lekéri a service IP címet, és új kapcsolatot nyit vele. Ez a kapcsolat először a helyi netra-sidecar-ral jön létre, és minden TCP csomag először is a netra-ba érkezik. Ezután a netra-sidecar létesít kapcsolatot az eredeti célponttal. A NAT a pod IP-n a nodon pontosan ugyanaz marad, mint netra nélkül.

Elosztott tracing és a kontextus átadása

A Netramesh olyan funkcionalitást biztosít, amely szükséges a HTTP interakciókról szóló tracing span-ek küldéséhez. A netra-sidecar elemzi a HTTP protokollt, méri a kérések késleltetését, és kiolvassa a szükséges információt a HTTP fejlécből. Végül az összes trace a Jaeger rendszerben összegyűlik. Finomabb konfiguráláshoz a hivatalos könyvtár által biztosított környezeti változókat is használhatod. jaeger go library.

A Netramesh egy könnyű service mesh megoldás

A Netramesh egy könnyű service mesh megoldás

De van egy probléma. Amíg a szolgáltatások nem generálnak és nem továbbítanak egy speciális uber fejlécet, nem látjuk a csatlakozott tracing span-eket a rendszerben. Pedig erre van szükségünk a problémák gyors felkutatásához. Itt a Netramesh újra megoldást kínál. A proxyk olvassák a HTTP fejléceket, és ha nincs uber trace id, akkor generálják azt. A Netramesh emellett tárolja a bejövő és kimenő kérések információit a sidecar-ban, és összepárosítja őket a szükséges fejlécel a kimenő kérések gazdagítása útján. A szolgáltatásokban mindössze egy fejlécet kell továbbítani. X-Request-Id, amelyet környezeti változó segítségével konfigurálhatsz. NETRA_HTTP_REQUEST_ID_HEADER_NAME. A Netramesh kontextusának méretének kezelésére a következő környezeti változókat lehet beállítani: NETRA_TRACING_CONTEXT_EXPIRATION_MILLISECONDS (az idő, ameddig a kontextus tárolódik) és NETRA_TRACING_CONTEXT_CLEANUP_INTERVAL (a kontextus tisztításának gyakorisága).

Több útvonal kombinálása lehetséges az Ön rendszerében, speciális munkamenet-jelzők használatával. A Netra lehetővé teszi, hogy beállítsa HTTP_HEADER_TAG_MAP az HTTP-fejlécek megfelelő tracing span címkékké való átalakításához. Ez különösen hasznos lehet tesztelés esetén. A funkcionális tesztelés után meg lehet nézni, hogy a rendszer melyik részét érintette a megfelelő munkamenet-azonosító szűrése alapján.

A kérés forrásának meghatározása

A kérés forrásának meghatározásához használhatja az automatikus forrás-azonosító fejléc hozzáadásának funkcióját. A "NETRA_HTTP_X_SOURCE_HEADER_NAME" környezeti változóval meghatározhatja a fejléc nevét, amely automatikusan beállításra kerül. A "NETRA_HTTP_X_SOURCE_VALUE" változó segítségével meghatározhatja az értéket, amelybe az X-Source fejléc minden kimenő kéréshez beállításra kerül. Ez lehetővé teszi, hogy az egész hálózaton egységesen terjeszthesse ezt a hasznos fejlécet. Ezt követően már használhatja a szolgáltatásokban és hozzáadhatja a naplókhoz, metrikákhoz. Forgalomirányítás és a Netramesh belső működése

A Netramesh két fő összetevőből áll. Az első, a netra-init, a forgalom elfogására vonatkozó hálózati szabályokat állít be. Az

iptables redirect szabályok

minden, vagy a forgalom egy részének elfogására szolgálnak a sidecar számára, amely a Netramesh második fő összetevője. Beállíthatja, hogy pontosan mely portokat kell elfogni a bejövő és kimenő TCP munkameneteknél: INBOUND_INTERCEPT_PORTS, OUTBOUND_INTERCEPT_PORTS Az eszközben érdekes lehetőség is van — valószínűségi forgalomirányítás. Ha a Netramesht kizárólag tracing span-ek gyűjtésére használja, a termelési környezetben erőforrásokat takaríthat meg, és valószínűségi forgalomirányítást aktiválhat a NETRA_INBOUND_PROBABILITY, NETRA_OUTBOUND_PROBABILITY.

(0 és 1 között). Az alapértelmezett érték 1 (az összes forgalom elfogása). A sikeres elfogás után a netra sidecar új kapcsolatot vesz fel, és használja és SO_ORIGINAL_DST a socket opciót az eredeti célpont megszerzéséhez. Ezután a Netra új kapcsolatot létesít az eredeti IP-címhez, és kétirányú TCP kommunikációt állít fel a felek között, figyelve az összes bejövő forgalmat. Ha a port HTTP-ként van beállítva, a Netra megpróbálja elemezni és nyomozni. Ha a HTTP elemzés nem sikerül, a Netra visszalép a TCP-re és átlátszóan proxyzza a biteket.

После успешного перехвата netra sidecar принимает новое соединение и использует SO_ORIGINAL_DST опцию сокета для получения изначальной точки назначения. Затем Netra открывает новое соединение к изначальному IP-адресу и устанавливает двустороннее TCP-общение между сторонами, слушая весь проходящий трафик. Если порт определен как HTTP, Netra пытается парсить его и трейсить. Если парсинг HTTP оказывается неуспешным, Netra делает фоллбэк на TCP и прозрачно проксирует байты.

A függőségek grafikonjának felépítése

Miután nagy mennyiségű tracing információt kaptunk a Jaegerben, szeretnénk megkapni a rendszer interakcióinak teljes grafikonját. De ha a rendszered eléggé leterhelt, és naponta milliárdos nagyságrendben gyűlnek össze a tracing spanok, akkor az aggregálásuk már nem olyan egyszerű feladat. Van egy hivatalos mód erre: spark-dependencies. Ennek ellenére órákba telik a teljes grafikon felépítése, és arra kényszerít, hogy a Jaegerből le kell tölteni az elmúlt 24 óra teljes adathalmaszt.

Ha Elasticsearch-t használsz a tracing spanok tárolására, akkor használhatsz egy egyszerű Golang eszközt, amely hasonló grafikont épít fel percek alatt, kihasználva az Elasticsearch jellemzőit és képességeit.

A Netramesh egy könnyű service mesh megoldás

A Netramesh használata

A Netrát egyszerűen hozzá lehet adni bármely szolgáltatáshoz, amely bármilyen orkhesztrátor mellett működik. Meg lehet nézni egy példát itt.

Jelenleg a Netrának nincs lehetősége a sidecar automatikus integrálására a szolgáltatásokhoz, de tervek vannak a megvalósítására.

A Netramesh jövője

A legfőbb célja Netramesh a minimális erőforrás-költségek elérése és a magas teljesítmény biztosítása, alapvető lehetőségeket nyújtva az observability és a mikro-szolgáltatások közötti interakciók ellenőrzésére.

A jövőben a Netramesh támogatni fogja más alkalmazási szintű protokollokat is a HTTP mellett. A közeljövőben megjelenik az L7 irányítás lehetősége.

Használj Netramesht, ha ilyen problémákkal találkozol, és írj nekünk kérdéseket és javaslatokat.

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster