Notă. transl.: Rețelele de servicii au devenit cu siguranță o soluție relevantă în infrastructura modernă pentru aplicațiile care urmează arhitectura microservicii. Deși Istio poate fi pe buzele multor ingineri DevOps, este un produs destul de nou care, deși cuprinzător în ceea ce privește capabilitățile pe care le oferă, poate necesita o perioadă semnificativă de timp pentru a se familiariza. Inginerul german Rinor Maloku, care este responsabil de cloud computing pentru clienții mari la compania de telecomunicații Orange Networks, a scris o serie minunată de materiale care vă permit să vă scufundați rapid și profund în Istio. El își începe povestea cu ce poate face Istio în general și cum o poți vedea rapid cu ochii tăi.
Istio — Un proiect Open Source dezvoltat în colaborare cu echipe de la Google, IBM și Lyft. Rezolvă complexitățile care apar în aplicațiile bazate pe microservicii, cum ar fi:
Administrarea traficului: expirări, reîncercări, echilibrare a încărcăturii;
Безопасность: autentificarea și autorizarea utilizatorului final;
Observabilitate: urmărire, monitorizare, logare.
Toate acestea pot fi rezolvate la nivel de aplicație, dar după aceea serviciile dumneavoastră nu vor mai fi „micro”. Tot efortul suplimentar de a rezolva aceste probleme este o risipă de resurse ale companiei care ar putea fi utilizate direct pentru valoarea afacerii. Să ne uităm la un exemplu:
Manager de proiect: Cât durează adăugarea unei funcții de feedback?
Dezvoltator: Două sprinturi.
MP: Ce?.. E doar CRUD!
R: Efectuarea CRUD este partea ușoară, dar încă trebuie să autentificăm și să autorizam utilizatorii și serviciile. Deoarece rețeaua nu este de încredere, va trebui să implementați solicitări repetate, precum și model de întrerupător in clienti. De asemenea, pentru a vă asigura că întregul sistem nu se prăbușește, veți avea nevoie de timeout-uri și pereți etanși(pentru mai multe detalii despre ambele modele menționate, vezi mai târziu în articol - aprox. traducere), iar pentru a detecta probleme, monitorizare, urmărire, […]
MP: Oh, atunci să introducem această caracteristică în serviciul Produs.
Cred că ideea este clară: cantitatea de pași și efort necesar pentru a adăuga un serviciu este enormă. În acest articol, ne vom uita la modul în care Istio elimină toată complexitatea menționată mai sus (care nu intenționează să fie logica de afaceri) din servicii.
Nota: Acest articol presupune că aveți cunoștințe practice despre Kubernetes. În rest, recomand să citești introducerea mea în Kubernetes și numai după aceea continuă să citești acest material.
Istio idee
Într-o lume fără Istio, un serviciu face solicitări directe altuia, iar în cazul unei defecțiuni, serviciul trebuie să se ocupe singur: să facă o nouă încercare, să ofere un timeout, să deschidă un întrerupător etc.
Trafic de rețea în Kubernetes
Istio oferă o soluție specializată, complet separată de servicii și care funcționează prin interferența cu comunicarea în rețea. Și astfel implementează:
toleranta la greseli: Pe baza codului de stare din răspuns, înțelege dacă cererea a eșuat și o reexecută.
Lansări Canary: redirecționează doar un procent fix de solicitări către noua versiune a serviciului.
Monitorizare și metrici: Cât a durat până când serviciul a răspuns?
Urmărirea și observabilitatea: adaugă anteturi speciale la fiecare cerere și le urmărește în cluster.
Безопасность: Preia jetonul JWT, autentifică și autorizează utilizatorii.
Acestea sunt doar câteva dintre posibilitățile (cu adevărat doar câteva!) de a vă intrigă. Acum să ne aruncăm în detalii tehnice!
Arhitectura Istio
Istio interceptează tot traficul de rețea și îi aplică un set de reguli, inserând un proxy inteligent sub forma unui container sidecar în fiecare pod. Proxy-urile care activează toate capabilitățile formează a Planul de dateși pot fi configurate dinamic folosind Planul de control.
Planul de date
Proxy-urile inserate în poduri îi permit lui Istio să îndeplinească cu ușurință cerințele de care avem nevoie. De exemplu, să verificăm funcțiile de reîncercare și întrerupător.
Cum sunt implementate reîncercările și întreruperea circuitului în Envoy
Rezumând:
trimis (vorbim despre un proxy situat într-un container sidecar, care este distribuit ca produs separat - aprox. traducere) trimite o cerere la prima instanță a serviciului B și eșuează.
Envoy Sidecar încearcă din nou (reîncercați). (1)
Solicitarea eșuează și este returnată proxy-ului care a apelat-o.
Aceasta deschide Circuit Breaker și apelează următorul serviciu pentru solicitările ulterioare. (2)
Aceasta înseamnă că nu trebuie să utilizați o altă bibliotecă Retry, nu trebuie să faceți propria implementare a Circuit Breaking și Service Discovery în limbajul de programare X, Y sau Z. Toate acestea și multe altele sunt disponibile de la cutie. în Istio și nu necesită nu modificări ale codului.
Grozav! Acum poate doriți să plecați într-o călătorie cu Istio, dar mai aveți câteva îndoieli, întrebări deschise. Dacă aceasta este o soluție universală pentru toate ocaziile din viață, atunci aveți o suspiciune firească: la urma urmei, toate astfel de soluții se dovedesc, în realitate, a fi nepotrivite pentru orice caz.
Și în sfârșit întrebi: „Este personalizabil?”
Acum sunteți gata pentru călătoria pe mare, să facem cunoștință cu avionul de control.
Planul de control
Este format din trei componente: Pilot, mixer и Cetate, care lucrează împreună pentru a configura Envoys să direcționeze traficul, să aplice politici și să colecteze date de telemetrie. Schematic totul arată astfel:
Interacțiunea planului de control cu planul de date
Trimisii (adică avionul de date) sunt configurați folosind Kubernetes CRD (Definiții personalizate de resurse) definite de Istio și destinate special în acest scop. Ce înseamnă asta pentru tine este că par a fi doar o altă resursă în Kubernetes cu o sintaxă familiară. Odată creată, această resursă va fi preluată de planul de control și aplicată trimișilor.
Relația de servicii cu Istio
Am descris relația Istio cu serviciile, dar nu invers: cum se raportează serviciile la Istio?
Sincer să fiu, serviciile sunt la fel de conștiente de prezența lui Istio precum peștii de apă atunci când se întreabă: „Ce este apa?”
Astfel, puteți lua un cluster de lucru și după implementarea componentelor Istio, serviciile aflate în acesta vor continua să funcționeze, iar după eliminarea acestor componente, totul va fi din nou bine. Este clar că în acest caz veți pierde capacitățile oferite de Istio.
Ajunge teorie - haideți să punem în practică aceste cunoștințe!
Istio în practică
Istio necesită un cluster Kubernetes cu cel puțin 4 vCPU-uri și 8 GB de RAM disponibile. Pentru a configura rapid un cluster și a urma instrucțiunile din articol, vă recomand să utilizați Google Cloud Platform, care oferă utilizatori noi gratuit 300 USD.
După crearea unui cluster și configurarea accesului la Kubernetes prin utilitarul consolei, puteți instala Istio prin managerul de pachete Helm.
Instalare cârmă
Instalați clientul Helm pe computer, așa cum este descris în documentație oficială. Vom folosi acest lucru pentru a genera șabloane pentru instalarea Istio în secțiunea următoare.
Instalarea Istio
Descărcați resurse Istio de la ultima lansare(linkul autorului original către versiunea 1.0.5 a fost schimbat cu cel actual, adică 1.0.6 - aprox. traducere), extrageți conținutul într-un singur director, pe care îl voi apela de acum înainte [istio-resources].
Pentru a identifica cu ușurință resursele Istio, creați un spațiu de nume în clusterul K8s istio-system:
$ kubectl create namespace istio-system
Finalizați instalarea accesând directorul [istio-resources] și rulează comanda:
Această comandă va scoate componentele cheie ale Istio într-un fișier istio.yaml. Am modificat șablonul standard pentru a ne potrivi, specificând următorii parametri:
global.mtls.enabled instalat în false(adică autentificarea mTLS este dezactivată - aprox.)pentru a simplifica procesul nostru de întâlniri;
tracing.enabled include urmărirea cererilor folosind Jaeger;
kiali.enabled instalează Kiali într-un cluster pentru a vizualiza serviciile și traficul;
grafana.enabled instalează Grafana pentru a vizualiza valorile colectate.
Să folosim resursele generate cu comanda:
$ kubectl apply -f istio.yaml
Instalarea Istio pe cluster este finalizată! Așteptați până când toate podurile sunt în spațiul de nume istio-system va fi capabil să Running sau Completedrulând comanda de mai jos:
$ kubectl get pods -n istio-system
Acum suntem gata să continuăm în secțiunea următoare, unde vom pune aplicația în funcțiune.
Arhitectura aplicatiei Sentiment Analysis
Să folosim exemplul aplicației de microserviciu Sentiment Analysis folosit în cele deja menționate Articol introductiv la Kubernetes. Este suficient de complex pentru a arăta capacitățile lui Istio în practică.
Aplicația constă din patru microservicii:
Serviciu SA-Frontend, care servește interfața unei aplicații Reactjs;
Serviciu SA-WebApp, care servește interogări de analiză a sentimentelor;
Serviciu SA-Feedback, care primește feedback de la utilizatori cu privire la acuratețea analizei.
În această diagramă, pe lângă servicii, vedem și Ingress Controller, care în Kubernetes direcționează cererile primite către serviciile corespunzătoare. Istio folosește un concept similar în Ingress Gateway, despre care vor urma mai multe detalii.
Rularea unei aplicații cu un proxy de la Istio
Pentru operațiuni suplimentare menționate în articol, clonează-ți depozitul istio-stăpânire. Conține aplicația și manifestele pentru Kubernetes și Istio.
Introducerea sidecar-urilor
Inserarea se poate face în mod automat sau de mână. Pentru a introduce automat containere sidecar, va trebui să setați o etichetă pentru spațiul de nume istio-injection=enabled, care se face cu următoarea comandă:
Acum fiecare pod care va fi implementat în spațiul de nume implicit (default) va primi containerul său sidecar. Pentru a verifica acest lucru, să implementăm aplicația de testare mergând la directorul rădăcină al depozitului [istio-mastery] și rulează următoarea comandă:
$ kubectl apply -f resource-manifests/kube
persistentvolumeclaim/sqlite-pvc created
deployment.extensions/sa-feedback created
service/sa-feedback created
deployment.extensions/sa-frontend created
service/sa-frontend created
deployment.extensions/sa-logic created
service/sa-logic created
deployment.extensions/sa-web-app created
service/sa-web-app created
După ce am implementat serviciile, să verificăm dacă pod-urile au două containere (cu serviciul în sine și sidecarul său) rulând comanda kubectl get pods și asigurându-se că sub coloană READY valoarea specificată 2/2, simbolizând că ambele containere rulează:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
sa-feedback-55f5dc4d9c-c9wfv 2/2 Running 0 12m
sa-frontend-558f8986-hhkj9 2/2 Running 0 12m
sa-logic-568498cb4d-2sjwj 2/2 Running 0 12m
sa-logic-568498cb4d-p4f8c 2/2 Running 0 12m
sa-web-app-599cf47c7c-s7cvd 2/2 Running 0 12m
Vizual arată așa:
Trimiteți proxy într-unul dintre poduri
Acum că aplicația este în funcțiune, va trebui să permitem traficului de intrare să intre în aplicație.
Gateway de intrare
Cea mai bună practică pentru a realiza acest lucru (permite traficul în cluster) este prin Gateway de intrare în Istio, care se află la „marginea” clusterului și vă permite să activați funcții Istio, cum ar fi rutarea, echilibrarea încărcăturii, securitatea și monitorizarea traficului de intrare.
Componenta Ingress Gateway și serviciul care o redirecționează extern au fost instalate în cluster în timpul instalării Istio. Pentru a afla adresa IP externă a serviciului, rulați:
$ kubectl get svc -n istio-system -l istio=ingressgateway
NAME TYPE CLUSTER-IP EXTERNAL-IP
istio-ingressgateway LoadBalancer 10.0.132.127 13.93.30.120
Vom continua să accesăm aplicația folosind acest IP (mă voi referi la ea ca EXTERNAL-IP), așa că pentru comoditate vom scrie valoarea într-o variabilă:
$ EXTERNAL_IP=$(kubectl get svc -n istio-system
-l app=istio-ingressgateway
-o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}')
Dacă încercați să accesați acest IP printr-un browser acum, veți primi o eroare Service Unavailable, deoarece implicit Istio blochează tot traficul de intrare, Gateway nu a fost încă definit.
Resursa gateway
Gateway este un CRD (Custom Resource Definition) în Kubernetes, definit după instalarea Istio în cluster și care permite posibilitatea de a specifica porturile, protocolul și gazdele pentru care dorim să permitem traficul de intrare.
În cazul nostru, dorim să permitem traficul HTTP pe portul 80 pentru toate gazdele. Sarcina este implementată prin următoarea definiție (http-gateway.yaml):
Această configurație nu are nevoie de explicații, cu excepția selectorului istio: ingressgateway. Cu acest selector putem specifica la ce gateway de intrare se aplică configurația. În cazul nostru, acesta este controlerul Ingress Gateway, care a fost instalat implicit în Istio.
Configurația se aplică apelând următoarea comandă:
$ kubectl apply -f resource-manifests/istio/http-gateway.yaml gateway.networking.istio.io/http-gateway created
Gateway-ul permite acum accesul la portul 80, dar nu are idee unde să direcționeze cererile. Pentru asta vei avea nevoie Servicii virtuale.
Resursa VirtualService
VirtualService îi spune Ingress Gateway cum să direcționeze cererile care sunt permise în cluster.
Solicitările către aplicația noastră care vin prin http-gateway trebuie trimise către serviciile sa-frontend, sa-web-app și sa-feedback:
Rute care trebuie configurate cu VirtualServices
Să ne uităm la solicitările care ar trebui trimise către SA-Frontend:
Potrivire exactă pe parcurs / ar trebui trimis la SA-Frontend pentru a obține index.html;
Căi prefixate /static/* trebuie trimis la SA-Frontend pentru a primi fișiere statice utilizate în frontend, cum ar fi CSS și JavaScript;
Căi potrivite prin expresia regulată '^.*.(ico|png|jpg)$', trebuie trimis la SA-Frontend, deoarece Acestea sunt pozele afisate pe pagina.
Acest Serviciu Virtual se referă la solicitările primite http-gateway;
В destination Serviciul către care sunt trimise cererile este determinat.
Nota: Configurația de mai sus este stocată într-un fișier sa-virtualservice-external.yaml, care conține și setări pentru rutare în SA-WebApp și SA-Feedback, dar a fost scurtat aici în articol pentru concizie.
Să aplicăm VirtualService sunând:
$ kubectl apply -f resource-manifests/istio/sa-virtualservice-external.yaml
virtualservice.networking.istio.io/sa-external-services created
Nota: Când consumăm resurse Istio, serverul API Kubernetes creează un eveniment care este primit de planul de control Istio, iar după aceea noua configurație este aplicată proxy-urilor Envoy ale fiecărui pod. Și controlerul Ingress Gateway pare a fi un alt Envoy configurat în Planul de control. Toate acestea arată așa în diagramă:
Configurație Istio-IngressGateway pentru rutarea cererilor
Aplicația Sentiment Analysis este acum disponibilă pe http://{EXTERNAL-IP}/. Nu vă faceți griji dacă obțineți starea Negăsit: Uneori, durează puțin mai mult pentru ca configurația să intre în vigoare și cache-urile Envoy să se actualizeze.
Înainte de a continua, jucați puțin cu aplicația pentru a genera trafic. (prezența acestuia este necesară pentru claritate în acțiunile ulterioare - aprox. traducere).
Kiali: observabilitate
Pentru a ajunge la interfața administrativă Kiali, rulați următoarea comandă:
$ kubectl port-forward
$(kubectl get pod -n istio-system -l app=kiali
-o jsonpath='{.items[0].metadata.name}')
-n istio-system 20001
... și deschis http://localhost:20001/, conectându-vă ca admin/admin. Aici veți găsi multe caracteristici utile, de exemplu, pentru a verifica configurația componentelor Istio, pentru a vizualiza serviciile folosind informațiile colectate din interceptarea solicitărilor de rețea, pentru a obține răspunsuri la întrebările „Cine contactează pe cine?”, „Ce versiune a serviciului se confruntă”. eșecuri?” și așa mai departe. În general, explorați capacitățile Kiali înainte de a trece la vizualizarea valorilor cu Grafana.
Grafana: vizualizare metrics
Valorile colectate în Istio intră în Prometheus și sunt vizualizate cu Grafana. Pentru a ajunge la interfața administrativă Grafana, rulați comanda de mai jos și apoi deschideți http://localhost:3000/:
$ kubectl -n istio-system port-forward
$(kubectl -n istio-system get pod -l app=grafana
-o jsonpath={.items[0].metadata.name}) 3000
Făcând clic pe meniu Acasă stânga sus și selectând Tabloul de bord Istio Service în colțul din stânga sus, începeți cu service sa-web-apppentru a vedea valorile colectate:
Ceea ce ne așteaptă aici este o performanță goală și complet plictisitoare - conducerea nu va fi niciodată de acord cu acest lucru. Să creăm o încărcare mică cu următoarea comandă:
$ while true; do
curl -i http://$EXTERNAL_IP/sentiment
-H "Content-type: application/json"
-d '{"sentence": "I love yogobella"}';
sleep .8; done
Acum avem grafice mult mai frumoase și, pe lângă acestea, minunate instrumente Prometheus pentru monitorizare și Grafana pentru vizualizarea unor metrici care ne vor permite să învățăm despre performanță, sănătate, îmbunătățiri/degradarea serviciilor în timp.
În cele din urmă, să ne uităm la solicitările de urmărire în servicii.
Jaeger: urmărire
Vom avea nevoie de urmărire, deoarece cu cât avem mai multe servicii, cu atât este mai dificil să ajungem la cauza eșecului. Să ne uităm la un caz simplu din imaginea de mai jos:
Exemplu tipic de solicitare nereușită aleatorie
Cererea vine, cade - Care este motivul? Primul serviciu? Sau al doilea? Există excepții în ambele - să ne uităm la jurnalele fiecăruia. Cât de des te-ai surprins făcând asta? Munca noastră seamănă mai mult cu detectivii de software decât cu dezvoltatorii...
Aceasta este o problemă comună în microservicii și este rezolvată de sistemele de urmărire distribuite, în care serviciile își transmit un antet unic între ele, după care aceste informații sunt transmise sistemului de urmărire, unde sunt comparate cu datele de solicitare. Iată o ilustrație:
TraceId este folosit pentru a identifica cererea
Istio folosește Jaeger Tracer, care implementează cadrul API OpenTracing independent de furnizor. Puteți accesa interfața de utilizator Jaeger cu următoarea comandă:
$ kubectl port-forward -n istio-system
$(kubectl get pod -n istio-system -l app=jaeger
-o jsonpath='{.items[0].metadata.name}') 16686
Acum du-te la http://localhost:16686/ și selectați un serviciu sa-web-app. Dacă serviciul nu este afișat în meniul derulant, afișați/generați activitate pe pagină și actualizați interfața. După aceea, faceți clic pe butonul Găsiți Urme, care va afișa cele mai recente urme - selectați orice - vor apărea informații detaliate despre toate urmele:
Această urmă arată:
Solicitarea vine istio-ingressgateway (aceasta este prima interacțiune cu unul dintre servicii și este generat un Trace ID pentru cerere), după care gateway-ul trimite cererea către serviciu sa-web-app.
În funcțiune sa-web-app cererea este preluată de sidecar-ul Envoy, un „copil” este creat în interval (de aceea îl vedem în urme) și redirecționat către container sa-web-app. (Deschidere - o unitate logică de lucru în Jaeger, care are un nume, ora de începere a operațiunii și durata acesteia. Traversele pot fi imbricate și ordonate. Un grafic aciclic direcționat al intervalelor formează o urmă. — aprox. traducere)
Aici cererea este procesată prin metoda analiza sentimentelor. Aceste urme sunt deja generate de aplicație, adică. au cerut modificări de cod.
Din acest moment, se inițiază o solicitare POST în sa-logica. ID-ul urmăririi trebuie redirecționat de la sa-web-app.
...
Nota: La pasul 4, aplicația ar trebui să vadă anteturile generate de Istio și să le transmită solicitărilor ulterioare, așa cum se arată în imaginea de mai jos:
(A) Istio este responsabil pentru transmiterea antetelor; (B) Serviciile sunt responsabile pentru anteturi
Istio face cea mai mare parte a muncii pentru că... generează anteturi pentru cererile primite, creează noi intervale în fiecare sidecare și le transmite. Cu toate acestea, fără a lucra cu anteturi în interiorul serviciilor, calea completă a urmăririi cererii se va pierde.
Trebuie luate în considerare următoarele anteturi:
Aceasta nu este o sarcină dificilă, dar pentru a simplifica implementarea sa există deja multe biblioteci - de exemplu, în serviciul sa-web-app, clientul RestTemplate transmite aceste antete dacă adăugați pur și simplu bibliotecile Jaeger și OpenTracing la dependențele lui.
Rețineți că aplicația Sentiment Analysis demonstrează implementări în Flask, Spring și ASP.NET Core.
Acum că este clar ce scoatem din cutie (sau aproape din cutie), să ne uităm la rutarea reglată, gestionarea traficului de rețea, securitate etc.!
Notă. transl.: Citiți despre acest lucru în următoarea parte a materialelor despre Istio de la Rinor Maloku, ale căror traduceri vor urma pe blogul nostru în viitorul apropiat. UPDATE (14 martie): A doua parte a fost deja publicat.