Netramesh - soluție ușoară de plasă de serviciu

Pe măsură ce trecem de la o aplicație monolitică la o arhitectură de microservicii, ne confruntăm cu noi provocări.

Într-o aplicație monolitică, este de obicei destul de ușor să determinați în ce parte a sistemului a apărut eroarea. Cel mai probabil, problema este în codul monolitului în sine sau în baza de date. Dar când începem să căutăm o problemă într-o arhitectură de microservicii, totul nu mai este atât de evident. Trebuie să găsim întreaga cale pe care a luat-o cererea de la început până la sfârșit și să o selectăm din sute de microservicii. Mai mult, multe dintre ele au și propriile facilități de stocare, care pot provoca și erori logice, precum și probleme cu performanța și toleranța la erori.

Netramesh - soluție ușoară de plasă de serviciu

Caut de multă vreme un instrument care să ajute să facă față unor astfel de probleme (am scris despre asta pe Habré: 1, 2), dar până la urmă mi-am făcut propria mea soluție open source. În acest articol vorbesc despre beneficiile abordării rețelei de servicii și împărtășesc un nou instrument pentru implementarea acesteia.

Urmărirea distribuită este o soluție comună la problema găsirii erorilor în sistemele distribuite. Dar ce se întâmplă dacă această abordare a colectării informațiilor despre interacțiunile rețelei nu a fost încă implementată în sistem sau, mai rău, într-o parte a sistemului funcționează deja corect, dar în parte nu, deoarece nu a fost adăugată la serviciile vechi ? Pentru a determina cauza exactă a unei probleme, este necesar să aveți o imagine completă a ceea ce se întâmplă în sistem. Este deosebit de important să înțelegem care microservicii sunt implicate în căile esențiale pentru afaceri.

Aici ne poate veni în ajutor abordarea rețelei de servicii, care se va ocupa de toate mașinile de colectare a informațiilor din rețea la un nivel mai scăzut decât serviciile în sine. Această abordare ne permite să interceptăm tot traficul și să-l analizăm din mers. Mai mult, aplicațiile nici nu trebuie să știe nimic despre asta.

Abordarea prin plasă de serviciu

Ideea principală a abordării rețelei de servicii este de a adăuga un alt strat de infrastructură peste rețea, care ne va permite să facem orice lucru cu interacțiunea inter-servicii. Majoritatea implementărilor funcționează după cum urmează: la fiecare microserviciu este adăugat un container sidecar suplimentar cu un proxy transparent, prin care este trecut tot traficul de intrare și de ieșire al serviciului. Și chiar acesta este locul unde putem face echilibrarea clienților, aplică politici de securitate, impunem restricții asupra numărului de solicitări și colectăm informații importante despre interacțiunea serviciilor în producție.

Netramesh - soluție ușoară de plasă de serviciu

Soluții

Există deja mai multe implementări ale acestei abordări: Istio и linkerd2. Ele oferă o mulțime de caracteristici din cutie. Dar, în același timp, vine o mare suprasarcină a resurselor. Mai mult, cu cât clusterul în care funcționează un astfel de sistem este mai mare, cu atât vor fi necesare mai multe resurse pentru întreținerea noii infrastructuri. La Avito, operăm clustere kubernetes care conțin mii de instanțe de servicii (și numărul acestora continuă să crească rapid). În implementarea sa actuală, Istio consumă ~ 300 Mb de RAM per instanță de serviciu. Datorită numărului mare de posibilități, echilibrarea transparentă afectează și timpul general de răspuns al serviciilor (până la 10 ms).

Drept urmare, ne-am uitat la exact ce capabilități avem nevoie în acest moment și am decis că principalul motiv pentru care am început să implementăm astfel de soluții a fost capacitatea de a colecta informații de urmărire din întregul sistem în mod transparent. De asemenea, am vrut să avem control asupra interacțiunii serviciilor și să facem diverse manipulări cu anteturile care sunt transferate între servicii.

Drept urmare, am ajuns la decizia noastră:  Netramesh.

Netramesh

Netramesh este o soluție ușoară de rețea de servicii, cu capacitatea de a se scala la infinit, indiferent de numărul de servicii din sistem.

Principalele obiective ale noii soluții au fost resursele generale reduse și performanța ridicată. Dintre caracteristicile principale, ne-am dorit imediat să putem trimite în mod transparent intervale de urmărire către sistemul nostru Jaeger.

Astăzi, majoritatea soluțiilor cloud sunt implementate în Golang. Și, desigur, există motive pentru asta. Scrierea aplicațiilor de rețea în Golang care funcționează asincron cu I/O și se scalează pe nuclee după cum este necesar este convenabilă și destul de simplă. Și, ceea ce este de asemenea foarte important, performanța este suficientă pentru a rezolva această problemă. De aceea am ales și Golang.

productivitate

Ne-am concentrat eforturile pe atingerea productivității maxime. Pentru o soluție care este implementată lângă fiecare instanță a serviciului, este necesar un mic consum de RAM și timp CPU. Și, desigur, întârzierea răspunsului ar trebui să fie, de asemenea, mică.

Să vedem ce rezultate avem.

RAM

Netramesh consumă ~10Mb fără trafic și maxim 50Mb cu o încărcare de până la 10000 RPS per instanță.

Istio envoy proxy consumă întotdeauna ~300 Mb în clusterele noastre cu mii de instanțe. Acest lucru nu îi permite să fie scalat la întregul cluster.

Netramesh - soluție ușoară de plasă de serviciu

Netramesh - soluție ușoară de plasă de serviciu

Cu Netramesh am obținut o reducere de ~10 ori a consumului de memorie.

Procesor

Utilizarea procesorului este relativ egală sub sarcină. Depinde de numărul de solicitări pe unitatea de timp către sidecar. Valori la 3000 de solicitări pe secundă la vârf:

Netramesh - soluție ușoară de plasă de serviciu

Netramesh - soluție ușoară de plasă de serviciu

Mai există un punct important: Netramesh - o soluție fără plan de control și fără încărcare nu consumă timp CPU. Cu Istio, sidecar-urile actualizează întotdeauna punctele finale de serviciu. Ca rezultat, putem vedea această imagine fără încărcare:

Netramesh - soluție ușoară de plasă de serviciu

Folosim HTTP/1 pentru comunicarea între servicii. Creșterea timpului de răspuns pentru Istio la proxy prin envoy a fost de până la 5-10 ms, ceea ce este destul de mult pentru serviciile care sunt gata să răspundă într-o milisecundă. Cu Netramesh, acest timp a scăzut la 0.5-2 ms.

Scalabilitate

Cantitatea mică de resurse consumată de fiecare proxy face posibilă plasarea acestuia lângă fiecare serviciu. Netramesh a fost creat în mod intenționat fără o componentă a planului de control pentru a menține pur și simplu fiecare sidecar ușor. Adesea, în soluțiile de rețea de serviciu, planul de control distribuie informații de descoperire a serviciului fiecărui sidecar. Odată cu acesta, vin și informații despre timeout-uri și setările de echilibrare. Toate acestea vă permit să faceți o mulțime de lucruri utile, dar, din păcate, umflă sidecar-urile în dimensiune.

Descoperirea serviciului

Netramesh - soluție ușoară de plasă de serviciu

Netramesh nu adaugă niciun mecanism suplimentar pentru descoperirea serviciului. Tot traficul este transmis transparent prin netra sidecar.

Netramesh acceptă protocolul de aplicație HTTP/1. Pentru a-l defini, se folosește o listă configurabilă de porturi. De obicei, sistemul are mai multe porturi prin care are loc comunicarea HTTP. De exemplu, folosim 80, 8890, 8080 pentru interacțiunea dintre servicii și solicitări externe. În acest caz, acestea pot fi setate folosind o variabilă de mediu NETRA_HTTP_PORTS.

Dacă utilizați Kubernetes ca orchestrator și mecanismul său de entitate Service pentru comunicarea intra-cluster între servicii, atunci mecanismul rămâne exact același. În primul rând, microserviciul obține o adresă IP a serviciului folosind kube-dns și deschide o nouă conexiune la acesta. Această conexiune este stabilită mai întâi cu netra-sidecar-ul local și toate pachetele TCP ajung inițial la netra. În continuare, netra-sidecar stabilește o legătură cu destinația inițială. NAT pe pod IP pe nod rămâne exact la fel ca și fără netra.

Urmărirea distribuită și redirecționarea contextului

Netramesh oferă funcționalitatea necesară pentru a trimite intervale de urmărire despre interacțiunile HTTP. Netra-sidecar analizează protocolul HTTP, măsoară întârzierile solicitărilor și extrage informațiile necesare din anteturile HTTP. În cele din urmă, obținem toate urmele într-un singur sistem Jaeger. Pentru o configurație fină, puteți utiliza și variabilele de mediu furnizate de biblioteca oficială biblioteca jaeger go.

Netramesh - soluție ușoară de plasă de serviciu

Netramesh - soluție ușoară de plasă de serviciu

Dar aici e o problema. Până când serviciile nu generează și trimit un antet uber special, nu vom vedea intervale de urmărire conectate în sistem. Și de asta avem nevoie pentru a găsi rapid cauza problemelor. Aici, din nou, Netramesh are o soluție. Proxy-urile citesc anteturile HTTP și, dacă nu conțin ID-ul de urmărire uber, generează unul. Netramesh stochează, de asemenea, informații despre cererile de intrare și de ieșire într-un sidecar și le potrivește îmbogățindu-le cu anteturile necesare cererilor de ieșire. Tot ce trebuie să faci în servicii este să trimiți un singur antet X-Request-Id, care poate fi configurat folosind o variabilă de mediu NETRA_HTTP_REQUEST_ID_HEADER_NAME. Pentru a controla dimensiunea contextului în Netramesh, puteți seta următoarele variabile de mediu: NETRA_TRACING_CONTEXT_EXPIRATION_MILLISECONDS (timpul pentru care contextul va fi stocat) și NETRA_TRACING_CONTEXT_CLEANUP_INTERVAL (frecvența curățării contextului).

De asemenea, este posibil să combinați mai multe căi pe sistemul dvs. prin marcarea lor cu un simbol de sesiune special. Netra vă permite să instalați HTTP_HEADER_TAG_MAP pentru a transforma antetele HTTP în etichete de urmărire corespunzătoare. Acest lucru poate fi util în special pentru testare. După trecerea testului funcțional, puteți vedea ce parte a sistemului a fost afectată prin filtrarea după cheia de sesiune corespunzătoare.

Determinarea sursei cererii

Pentru a determina de unde a venit cererea, puteți utiliza funcționalitatea de a adăuga automat un antet cu sursa. Utilizarea unei variabile de mediu NETRA_HTTP_X_SOURCE_HEADER_NAME Puteți specifica un nume de antet care va fi instalat automat. Prin utilizarea NETRA_HTTP_X_SOURCE_VALUE puteți seta valoarea la care va fi setat antetul X-Source pentru toate cererile trimise.

Acest lucru permite distribuția acestui antet util să fie distribuită uniform în întreaga rețea. Apoi îl puteți utiliza în servicii și îl puteți adăuga la jurnalele și valorile.

Dirijarea traficului și elementele interne Netramesh

Netramesh este format din două componente principale. Primul, netra-init, stabilește reguli de rețea pentru a intercepta traficul. El foloseste reguli de redirecționare iptables pentru a intercepta întregul sau parțial traficul pe sidecar, care este a doua componentă principală a Netramesh. Puteți configura ce porturi trebuie interceptate pentru sesiunile TCP de intrare și de ieșire: INBOUND_INTERCEPT_PORTS, OUTBOUND_INTERCEPT_PORTS.

Instrumentul are și o caracteristică interesantă - rutarea probabilistică. Dacă utilizați Netramesh exclusiv pentru colectarea intervalelor de urmărire, atunci într-un mediu de producție puteți economisi resurse și puteți activa rutarea probabilistică folosind variabile NETRA_INBOUND_PROBABILITY и NETRA_OUTBOUND_PROBABILITY (de la 0 la 1). Valoarea implicită este 1 (tot traficul este interceptat).

După interceptarea cu succes, netra sidecar acceptă noua conexiune și folosește SO_ORIGINAL_DST opțiunea socket pentru a obține destinația inițială. Netra deschide apoi o nouă conexiune la adresa IP originală și stabilește o comunicare TCP bidirecțională între părți, ascultând tot traficul care trece. Dacă portul este definit ca HTTP, Netra încearcă să îl analizeze și să îl urmărească. Dacă analiza HTTP eșuează, Netra revine la TCP și trimite în mod transparent octeții.

Construirea unui grafic de dependență

După ce am primit o cantitate mare de informații de urmărire în Jaeger, vreau să obțin un grafic complet al interacțiunilor din sistem. Dar dacă sistemul dvs. este destul de încărcat și miliarde de intervale de urmărire se acumulează pe zi, agregarea lor nu devine o sarcină atât de ușoară. Există o modalitate oficială de a face acest lucru: dependențe de scânteie. Cu toate acestea, va dura ore pentru a construi un grafic complet și vă va forța să descărcați întregul set de date de la Jaeger pentru ultimele 24 de ore.

Dacă utilizați Elasticsearch pentru a stoca intervale de urmărire, puteți utiliza un simplu utilitar Golang, care va construi același grafic în câteva minute folosind funcțiile și capacitățile Elasticsearch.

Netramesh - soluție ușoară de plasă de serviciu

Cum se utilizează Netramesh

Netra poate fi adăugat cu ușurință la orice serviciu care rulează orice orchestrator. Puteți vedea un exemplu aici.

Momentan, Netra nu are capacitatea de a implementa automat sidecar-uri la servicii, dar există planuri de implementare.

Viitorul Netramesh

scopul principal Netramesh este de a obține costuri minime de resurse și performanță ridicată, oferind capabilități de bază pentru observabilitatea și controlul comunicațiilor inter-servicii.

În viitor, Netramesh va suporta alte protocoale de nivel de aplicație în afară de HTTP. Rutarea L7 va fi disponibilă în viitorul apropiat.

Utilizați Netramesh dacă întâmpinați probleme similare și scrieți-ne cu întrebări și sugestii.

Sursa: www.habr.com

Adauga un comentariu