Înapoi la microservicii cu Istio. Partea 2

Înapoi la microservicii cu Istio. Partea 2

Notă. transl.: Prima parte Această serie a fost dedicată introducerii capabilităților Istio și demonstrării lor în acțiune. Acum vom vorbi despre aspecte mai complexe ale configurației și utilizării acestei rețele de servicii și, în special, despre rutarea fin reglată și gestionarea traficului de rețea.

De asemenea, vă reamintim că articolul folosește configurații (manifeste pentru Kubernetes și Istio) din depozit istio-stăpânire.

Administrarea traficului

Cu Istio, noi capabilități apar în cluster pentru a oferi:

  • Dirijarea dinamică a cererilor: lansări canare, testare A/B;
  • Echilibrarea sarcinii: simplu și consistent, bazat pe hashes;
  • Recuperare după cădere: timeout-uri, reîncercări, întrerupătoare;
  • Inserarea defectelor: întârzieri, solicitări renunțate etc.

Pe măsură ce articolul continuă, aceste capabilități vor fi ilustrate folosind aplicația selectată ca exemplu și vor fi introduse noi concepte pe parcurs. Primul astfel de concept va fi DestinationRules (adică reguli despre destinatarul traficului/solicitărilor - aprox. traducere), cu ajutorul căruia activăm A/B testing.

Testare A/B: Reguli de destinație în practică

Testarea A/B este folosită în cazurile în care există două versiuni ale unei aplicații (de obicei sunt diferite vizual) și nu suntem 100% siguri care dintre ele va îmbunătăți experiența utilizatorului. Prin urmare, rulăm ambele versiuni simultan și colectăm valori.

Pentru a implementa cea de-a doua versiune a frontend-ului, necesară pentru demonstrarea testării A/B, rulați următoarea comandă:

$ kubectl apply -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions/sa-frontend-green created

Manifestul de implementare pentru versiunea verde diferă în două locuri:

  1. Imaginea se bazează pe o altă etichetă - istio-green,
  2. Podurile au o etichetă version: green.

Deoarece ambele implementări au o etichetă app: sa-frontend,cereri direcționate prin serviciu virtual sa-external-services pentru service sa-frontend, va fi redirecționat către toate instanțele sale și încărcarea va fi distribuită prin algoritm round-robin, ceea ce va duce la următoarea situație:

Înapoi la microservicii cu Istio. Partea 2
Fișierele solicitate nu au fost găsite

Aceste fișiere nu au fost găsite deoarece sunt denumite diferit în diferite versiuni ale aplicației. Să ne asigurăm de asta:

$ curl --silent http://$EXTERNAL_IP/ | tr '"' 'n' | grep main
/static/css/main.c7071b22.css
/static/js/main.059f8e9c.js
$ curl --silent http://$EXTERNAL_IP/ | tr '"' 'n' | grep main
/static/css/main.f87cd8c9.css
/static/js/main.f7659dbb.js

Acest lucru înseamnă că index.html, care solicită o versiune de fișiere statice, poate fi trimisă de echilibrator de încărcare către poduri care au o versiune diferită, unde, din motive evidente, astfel de fișiere nu există. Prin urmare, pentru ca aplicația să funcționeze, trebuie să stabilim o restricție: „aceeași versiune a aplicației care a servit index.html ar trebui să servească solicitările ulterioare".

Vom ajunge acolo cu o echilibrare a încărcăturii bazată pe hash (Echilibrare hash constantă). În acest caz cererile de la același client sunt trimise către aceeași instanță backend, pentru care este utilizată o proprietate predefinită - de exemplu, un antet HTTP. Implementat folosind DestinationRules.

Reguli de destinație

După Serviciu virtual a trimis o solicitare către serviciul dorit, folosind DestinationRules putem defini politici care vor fi aplicate traficului destinat instanțelor acestui serviciu:

Înapoi la microservicii cu Istio. Partea 2
Gestionarea traficului cu resurse Istio

Nota: Impactul resurselor Istio asupra traficului de rețea este prezentat aici într-un mod ușor de înțeles. Mai exact, decizia asupra cărei instanțe să trimită cererea este luată de Envoy în Ingress Gateway configurat în CRD.

Cu Destination Rules, putem configura echilibrarea încărcăturii pentru a utiliza hashuri consistente și a ne asigura că aceeași instanță de serviciu răspunde aceluiași utilizator. Următoarea configurație vă permite să realizați acest lucru (destinationrule-sa-frontend.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: sa-frontend
spec:
  host: sa-frontend
  trafficPolicy:
    loadBalancer:
      consistentHash:
        httpHeaderName: version   # 1

1 - hash va fi generat pe baza conținutului antetului HTTP version.

Aplicați configurația cu următoarea comandă:

$ kubectl apply -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io/sa-frontend created

Acum rulați comanda de mai jos și asigurați-vă că obțineți fișierele potrivite când specificați antetul version:

$ curl --silent -H "version: yogo" http://$EXTERNAL_IP/ | tr '"' 'n' | grep main

Nota: Pentru a adăuga diferite valori în antet și a testa rezultatele direct în browser, puteți utiliza această extensie la Chrome (Sau, cu asta pentru Firefox - aprox. traducere).

În general, DestinationRules are mai multe capacități în domeniul echilibrării sarcinii - verificați detalii în documentație oficială.

Înainte de a studia în continuare VirtualService, să ștergem „versiunea verde” a aplicației și regula corespunzătoare de direcție a traficului, rulând următoarele comenzi:

$ kubectl delete -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions “sa-frontend-green” deleted
$ kubectl delete -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io “sa-frontend” deleted

Oglindire: Servicii virtuale în practică

shadowing („protecție”) sau Oglindire ("oglindire") utilizat în cazurile în care dorim să testăm o schimbare în producție fără a afecta utilizatorii finali: pentru a face acest lucru, duplicăm cererile („oglindă”) către o a doua instanță în care s-au făcut modificările dorite și ne uităm la consecințe. Mai simplu spus, acesta este momentul în care colegul tău alege cea mai critică problemă și face o cerere de tragere sub forma unui bulgăre atât de mare de murdărie încât nimeni nu o poate revizui cu adevărat.

Pentru a testa acest scenariu în acțiune, să creăm oa doua instanță a SA-Logic cu erori (buggy) prin rularea următoarei comenzi:

$ kubectl apply -f resource-manifests/kube/shadowing/sa-logic-service-buggy.yaml
deployment.extensions/sa-logic-buggy created

Și acum să rulăm comanda pentru a ne asigura că toate instanțele cu app=sa-logic Au și etichete cu versiunile corespunzătoare:

$ kubectl get pods -l app=sa-logic --show-labels
NAME                              READY   LABELS
sa-logic-568498cb4d-2sjwj         2/2     app=sa-logic,version=v1
sa-logic-568498cb4d-p4f8c         2/2     app=sa-logic,version=v1
sa-logic-buggy-76dff55847-2fl66   2/2     app=sa-logic,version=v2
sa-logic-buggy-76dff55847-kx8zz   2/2     app=sa-logic,version=v2

Serviciu sa-logic vizează păstăile cu o etichetă app=sa-logic, astfel încât toate solicitările vor fi distribuite între toate instanțele:

Înapoi la microservicii cu Istio. Partea 2

... dar dorim ca cererile să fie trimise la instanțe v1 și reflectate în instanțe v2:

Înapoi la microservicii cu Istio. Partea 2

Vom realiza acest lucru prin VirtualService în combinație cu DestinationRule, unde regulile vor determina subseturile și rutele VirtualService către un anumit subset.

Definirea subseturi în regulile de destinație

Subseturi (subseturi) sunt determinate de următoarea configurație (sa-logic-subsets-destinationrule.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: sa-logic
spec:
  host: sa-logic    # 1
  subsets:
  - name: v1        # 2
    labels:
      version: v1   # 3
  - name: v2
    labels:
      version: v2

  1. Gazdă (host) definește că această regulă se aplică numai cazurilor în care ruta merge spre serviciu sa-logic;
  2. Titluri (name) subseturile sunt folosite la rutarea către instanțe de subseturi;
  3. Eticheta (label) definește perechile cheie-valoare cu care instanțele trebuie să se potrivească pentru a deveni parte a subsetului.

Aplicați configurația cu următoarea comandă:

$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets-destinationrule.yaml
destinationrule.networking.istio.io/sa-logic created

Acum că subseturile sunt definite, putem trece mai departe și configura VirtualService să aplice reguli cererilor către sa-logic, astfel încât acestea:

  1. Dirijat către un subset v1,
  2. Oglindă într-un subset v2.

Următorul manifest vă permite să vă îndepliniți planurile (sa-logic-subsets-shadowing-vs.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic          
  http:
  - route:
    - destination:
        host: sa-logic  
        subset: v1      
    mirror:             
      host: sa-logic     
      subset: v2

Nu este nevoie de explicații aici, așa că haideți să o vedem în acțiune:

$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets-shadowing-vs.yaml
virtualservice.networking.istio.io/sa-logic created

Să adăugăm încărcarea apelând următoarea comandă:

$ while true; do curl -v http://$EXTERNAL_IP/sentiment 
    -H "Content-type: application/json" 
    -d '{"sentence": "I love yogobella"}'; 
    sleep .8; done

Să ne uităm la rezultatele din Grafana, unde puteți vedea că versiunea cu bug-uri (buggy) duce la eșec pentru ~60% din solicitări, dar niciuna dintre aceste eșecuri nu afectează utilizatorii finali, deoarece li se răspunde la un serviciu care rulează.

Înapoi la microservicii cu Istio. Partea 2
Răspunsuri de succes ale diferitelor versiuni ale serviciului sa-logic

Aici am văzut mai întâi cum se aplică VirtualService trimișilor serviciilor noastre: când sa-web-app face o cerere către sa-logic, trece prin sidecar Envoy, care - prin VirtualService - este configurat să direcționeze cererea către subsetul v1 și să oglindească cererea către subsetul v2 al serviciului sa-logic.

Știu, s-ar putea să credeți deja că Serviciile Virtuale sunt simple. În secțiunea următoare, vom extinde acest lucru spunând că sunt, de asemenea, cu adevărat grozave.

Lansări Canary

Canary Deployment este procesul de lansare a unei noi versiuni a unei aplicații pentru un număr mic de utilizatori. Este folosit pentru a vă asigura că nu există probleme în lansare și numai după aceea, având deja încredere în calitatea sa (lansării), îl distribuiți altor utilizatori.оaudienta mai mare.

Pentru a demonstra lansările Canary, vom continua să lucrăm cu un subset buggy у sa-logic.

Să nu pierdem timpul cu fleacuri și să trimitem imediat 20% dintre utilizatori la versiunea cu erori (aceasta va reprezenta lansarea noastră canar), iar restul de 80% la serviciul normal. Pentru a face acest lucru, utilizați următorul VirtualService (sa-logic-subseturi-canary-vs.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic    
  http:
  - route: 
    - destination: 
        host: sa-logic
        subset: v1
      weight: 80         # 1
    - destination: 
        host: sa-logic
        subset: v2
      weight: 20 # 1

1 este greutatea (weight), care specifică procentul de solicitări care vor fi direcționate către un destinatar sau un subset al destinatarului.

Să actualizăm configurația anterioară VirtualService pentru sa-logic cu următoarea comandă:

$ kubectl apply -f resource-manifests/istio/canary/sa-logic-subsets-canary-vs.yaml
virtualservice.networking.istio.io/sa-logic configured

... și vom vedea imediat că unele solicitări duc la eșecuri:

$ while true; do 
   curl -i http://$EXTERNAL_IP/sentiment 
   -H "Content-type: application/json" 
   -d '{"sentence": "I love yogobella"}' 
   --silent -w "Time: %{time_total}s t Status: %{http_code}n" 
   -o /dev/null; sleep .1; done
Time: 0.153075s Status: 200
Time: 0.137581s Status: 200
Time: 0.139345s Status: 200
Time: 30.291806s Status: 500

VirtualServices permit lansările canare: în acest caz, am redus impactul potențial al problemelor la 20% din baza de utilizatori. Minunat! Acum, în fiecare caz când nu suntem siguri de codul nostru (cu alte cuvinte - întotdeauna...), putem folosi oglindirea și lansările canary.

Timeouts și reîncercări

Dar erorile nu ajung întotdeauna în cod. În lista de la "8 Concepții greșite despre calculul distribuit„În primul rând este credința eronată că „rețeaua este fiabilă”. In realitate reteaua nu fiabile și din acest motiv avem nevoie de timeout-uri (time-out) și reîncercați (reîncercați).

Pentru demonstrație vom continua să folosim aceeași versiune cu probleme sa-logic (buggy), și vom simula nefiabilitatea rețelei cu defecțiuni aleatorii.

Permiteți serviciului nostru cu erori să aibă o șansă de 1/3 să dureze prea mult să răspundă, o șansă de 1/3 să se încheie cu o eroare internă a serverului și o șansă de 1/3 de a returna pagina cu succes.

Pentru a atenua impactul unor astfel de probleme și pentru a face viața mai bună pentru utilizatori, putem:

  1. adăugați un timeout dacă serviciul durează mai mult de 8 secunde pentru a răspunde,
  2. reîncercați dacă cererea eșuează.

Pentru implementare, vom folosi următoarea definiție a resursei (sa-logic-retry-timeouts-vs.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic
  http:
  - route: 
    - destination: 
        host: sa-logic
        subset: v1
      weight: 50
    - destination: 
        host: sa-logic
        subset: v2
      weight: 50
    timeout: 8s           # 1
    retries:
      attempts: 3         # 2
      perTryTimeout: 3s # 3

  1. Timeout-ul pentru cerere este setat la 8 secunde;
  2. Solicitările sunt reîncercate de 3 ori;
  3. Și fiecare încercare este considerată nereușită dacă timpul de răspuns depășește 3 secunde.

Aceasta este o optimizare deoarece utilizatorul nu va trebui să aștepte mai mult de 8 secunde și vom face trei noi încercări pentru a obține un răspuns în caz de eșecuri, crescând șansa unui răspuns de succes.

Aplicați configurația actualizată cu următoarea comandă:

$ kubectl apply -f resource-manifests/istio/retries/sa-logic-retries-timeouts-vs.yaml
virtualservice.networking.istio.io/sa-logic configured

Și verificați în graficele Grafana că numărul de răspunsuri reușite a crescut mai sus:

Înapoi la microservicii cu Istio. Partea 2
Îmbunătățiri ale statisticilor de răspuns de succes după adăugarea de timeout-uri și reîncercări

Înainte de a trece la următoarea secțiune (sau mai degrabă, la următoarea parte a articolului, pentru că în aceasta nu vor mai exista experimente practice - aprox. traducere), șterge sa-logic-buggy și VirtualService rulând următoarele comenzi:

$ kubectl delete deployment sa-logic-buggy
deployment.extensions “sa-logic-buggy” deleted
$ kubectl delete virtualservice sa-logic
virtualservice.networking.istio.io “sa-logic” deleted

Modele întreruptoare și pereți

Vorbim despre două modele importante în arhitectura de microservicii care vă permit să realizați auto-recuperarea (auto vindecare) Servicii.

Întrerupător de circuit ("întrerupător de circuit") folosit pentru a termina cererile care vin la o instanță a unui serviciu care este considerat nesănătos și a le restabili în timp ce solicitările clientului sunt redirecționate către instanțe sănătoase ale serviciului respectiv (ceea ce crește procentul de răspunsuri reușite). (Notă: o descriere mai detaliată a modelului poate fi găsită, de exemplu, aici.)

Bulkhead („partiție”) izolează defecțiunile serviciului de a afecta întregul sistem. De exemplu, Serviciul B este întrerupt și un alt serviciu (clientul Serviciului B) face o solicitare către Serviciul B, determinându-l să își epuizeze pool-ul de fire și să nu poată deservi alte solicitări (chiar dacă acestea nu sunt de la Serviciul B). (Notă: o descriere mai detaliată a modelului poate fi găsită, de exemplu, aici.)

Voi omite detaliile de implementare ale acestor modele deoarece sunt ușor de găsit documentație oficială, și chiar vreau să arăt autentificarea și autorizarea, despre care vor fi discutate în următoarea parte a articolului.

PS de la traducator

Citește și pe blogul nostru:

Sursa: www.habr.com

Adauga un comentariu