Nazaj k mikrostoritev z Istio. Del 2

Nazaj k mikrostoritev z Istio. Del 2

Op. prev.: Prvi del Ta cikel je bil posvečen spoznavanju zmogljivosti Istio in njihovi predstavitvi v praksi. Zdaj bomo govorili o bolj zapletenih vidikih konfiguracije in uporabe te storitvene mreže, zlasti o natančno nastavljenem usklajevanju in upravljanju omrežnega prometa.

Pripominjamo tudi, da članek uporablja konfiguracije (manifesti za Kubernetes in Istio) iz repozitorija. istio-mastery.

Upravljanje prometa

Z Istio v klastru se odpirajo nove možnosti, ki omogočajo:

  • Dinamično usklajevanje zahtevkov: kanarčna uvedba, A/B testiranje;
  • Uravnavanje obremenitve: preprosto in enotno, bazirano na hashu;
  • Obnavljanje po napakah: časovni preseki, ponovni poskusi, circuit breakers;
  • Sprožanje napak: zakasnitve, prekinitve zahtevkov itd.

V nadaljevanju članka bodo te možnosti prikazane na primeru izbranega aplikacije in obenem predstavljene nove koncepcije. Prva takšna koncept je DestinationRules (tj. pravila o prejemnikih prometa/zahtevkov — op. prev.), s pomočjo katerih aktiviramo A/B testiranje.

A/B testiranje: DestinationRules v praksi

A/B testiranje se uporablja, ko obstajata dve različici aplikacije (običajno se vizualno razlikujeta), in nismo prepričani, katera od njiju bo izboljšala uporabniško izkušnjo. Zato hkrati lansiramo obe različici in zbiramo metrike.

Za uvajanje druge različice sprednjega dela, potrebne za demonstracijo A/B testiranja, izvedite naslednji ukaz:

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

Manifest za uvedbo 'zelene različice' se razlikuje na dveh mestih:

  1. Slika temelji na drugem oznaki — istio-green,
  2. Pod'i imajo oznako version: green.

Ker imata oba uvajanja oznako app: sa-frontend, se zahtevki, usklajevani z.virtualno storitvijo sa-external-services za storitev sa-frontend, preusmerijo na vse njene primerke in obremenitev se razporedi po algoritmu round-robin, kar bo privedlo do naslednje situacije:

Nazaj k mikrostoritev z Istio. Del 2
Zahtevane datoteke niso bile najdene

Te datoteke niso bile najdene, ker se v različnih različicah aplikacije imenujejo različно. Preverimo to:

$ 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

To pomeni, da index.html, ki zahteva eno verzijo statičnih datotek, lahko pošlje uravnoteževalnik obremenitve na pod'e, ki imajo drugo verzijo, kjer takšnih datotek, iz razumljivih razlogov, ni. Zato, da bo aplikacija delovala, moramo postaviti omejitev: «ista verzija aplikacije, ki je poslala index.html, mora obravnavati tudi nadaljnje zahteve».

Cilja bomo dosegli z doslednim uravnoteženjem obremenitve na osnovi hash-ov (- Dosledno Hash Uravnoteževanje). V tem primeru zahteve enega naročnika so poslane enemu in istemu instanci strežnika, za kar se uporablja vnaprej določena lastnost — na primer, HTTP-zavihek. To se realizira z Destinacijskimi pravili.

DestinationRules

Po tem, ko VirtualService usmeri zahtevo v pravilen servis, z Destinacijskimi pravili lahko določimo politike, ki se bodo uporabljale za promet, namenjen instancam tega servisa:

Nazaj k mikrostoritev z Istio. Del 2
Upravljanje prometa z viri Istio

Napomena: Vpliv virov Istio na omrežni promet je tukaj predstavljen v poenostavljeni obliki. Natančneje, odločitev o tem, na katero instanco poslati zahtevo, sprejme Envoy v Ingress Gateway, nastavljenem v CRD.

Z Destinacijskimi pravili lahko nastavite uravnoteženje obremenitve tako, da se uporabljajo dosledni hash-i in zagotavljajo odgovori iste instančne storitve istemu uporabniku. Naslednja konfiguracija to omogoča (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 se bo generiral na osnovi vsebine HTTP-zavihka version.

Konfiguracijo uporabite z naslednjim ukazom:

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

Sedaj pa izvedite spodnji ukaz in se prepričajte, da prejemate prave datoteke, ko navedete zavihek version:

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

Napomena: Da dodate različne vrednosti v zavihku in testirate rezultate neposredno v brskalniku, lahko uporabite to razširitev za Chrome (ali tole za Firefox — op. prev.).

Na splošno pa ima Destinacijska pravila več možnosti na področju uravnoteženja obremenitve — podrobnosti preverite pri uradni dokumentaciji.

Preden se poglobimo v VirtualService, bomo izbrisali "zeleno različico" aplikacije in ustrezno pravilo za usmerjanje prometa z naslednjimi ukazi:

$ 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

Zrcaljenje: Virtual Services v praksi

Shadowing ("ekraniranje") ali Mirroring ("zrcaljenje") se uporablja, kadar želimo testirati spremembo v produkciji, ne da bi vplivali na končne uporabnike: zato podvojimo ("zrcalimo") zahteve na drugi primer, kjer so bile opravljene potrebne spremembe, in opazujemo posledice. Enostavno povedano, to je, ko vaš(a) kolega izbere najpomembnejši problem in naredi pull request v obliki takega ogromnega kupčka blata, da ga nihče dejansko ne more pregledati.

Da preverimo ta scenarij v praksi, bomo ustvarili drugi primer SA-Logic z napakami (buggy), z izvajanjem naslednjega ukaza:

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

In zdaj bomo izvedli ukaz, da se prepričamo, da imajo vsi primeri z app=sa-logic tudi oznake z ustreznimi različicami:

$ 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

Storitve sa-logic cilja na pod'e z oznako app=sa-logic, zato se bodo vse zahteve razdelile med vse primere:

Nazaj k mikrostoritev z Istio. Del 2

… ampak želimo, da se zahteve usmerjajo na primere z različico v1 in zrcalijo na primere z različico v2:

Nazaj k mikrostoritev z Istio. Del 2

To bomo dosegli preko VirtualService v kombinaciji z DestinationRule, kjer bodo pravila določila podmnožice in poti VirtualService do določene podmnožice.

Določitev podmnožic v Destination Rules

Podmnožice (subsets) so določene z naslednjo konfiguracijo (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. Gostitelj (host) določa, da se to pravilo uporablja samo v primerih, ko se usmeritev odvija proti storitvi sa-logic;
  2. Imena (name) podmnožic se uporabljajo pri usmerjanju na primere podmnožice;
  3. Oznaka (label) določa pare ključ-vrednost, katerim morajo ustrezati primerki, da postanejo del podmnožice.

Konfiguracijo uporabite z naslednjim ukazom:

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

Zdaj, ko so podmnožice definirane, lahko nadaljujemo z nastavitvijo VirtualService, da uporabi pravila za poizvedbe na sa-logic, tako da:

  1. so usmerjene na podmnožico v1,
  2. so zrcaljene na podmnožico v2.

Naslednji manifest omogoča dosego zamisli (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

Razlage tu niso potrebne, zato si le oglejmo akcijo:

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

Dodajmo obremenitev z izvajanjem naslednjega ukaza:

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

Oglejmo si rezultate v Grafani, kjer lahko vidimo, da različica z napakami (buggy) povzroči napakke za ~60 % poizvedb, vendar nobena od teh napak ne vpliva na končne uporabnike, saj nanje odgovarja delujoča storitev.

Nazaj k mikrostoritev z Istio. Del 2
Uspešnost odgovorov različnih različic storitve sa-logic

Tukaj smo prvič videli, kako se VirtualService uporablja v povezavi z Envoy-ji naših storitev: ko sa-web-app izvede poizvedbo na sa-logic, gre skozi sidecar Envoy, ki je preko VirtualService nastavljen na usmeritev poizvedbe na podmnožico v1 in zrcalitev poizvedbe na podmnožico v2 storitve sa-logic.

Vem: že ste pomislili, da so Virtual Services enostavni. V naslednjem razdelku bomo to mnenje razširili s tem, da so tudi resnično čudoviti.

Canary uvajanja

Canary Deployment — postopek uvajanja nove različice aplikacije za majhno število uporabnikov. Uporablja se, da se prepričamo, da ni težav v izdaji, in šele nato, ko smo prepričani o zadostni kakovosti (izdaje), jo razširimo na booljšo občinstvo.

Za demonstracijo kanarčnih izdaj bomo nadaljevali z delom z podmnožico buggy za sa-logic.

Ne bomo se obremenjevali in takoj usmerili 20 % uporabnikov na različico z napakami (ta bo predstavljala naš kanarčni rollout), preostalih 80 % pa na normalno storitev. Za to bomo uporabili naslednji VirtualService (sa-logic-subsets-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 — to je težina (tezina), koja određuje postotak zahteva koji će biti usmereni na odredište ili podskup odredišta.

Ažuriraćemo prethodnu konfiguraciju VirtualService sa sa-logic sledećom komandom:

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

… i odmah ćemo videti da deo zahteva dovodi do grešaka:

$ 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 aktiviraju kanare izdanja: u ovom slučaju smo suzili potencijalne posledice problema na 20 % korisničke baze. Odlično! Sada, svaki put kada nismo sigurni u naš kod (drugim rečima — uvek…), možemo koristiti zrcaljenje i kanare izdanja.

Vremenski limiti i ponovni pokušaji

Ali ne ponekad greške su u kodu. Na listi od „8 zabluda u distribuiranim računarstvima" prvo mesto zauzima pogrešno verovanje da je „mreža pouzdana“. U stvarnosti, mreža ne je pouzdana i zato su nam potrebni vremenski limiti (timeouts) i ponovni pokušaji (retries).

Da bismo to demonstrirali, nastavićemo da koristimo istu verziju problema sa-logic (buggy), a nepouzdano ponašanje mreže ćemo simulirati nasumičnim greškama.

Neka naš servis sa greškom ima 1/3 šanse za predugo odgovaranje, 1/3 za grešku unutrašnjeg servera i 1/3 za uspešno vraćanje stranice.

Da bismo ublažili posledice takvih problema i učinili život korisnicima boljim, možemo:

  1. dodati vremenski limit ako servis odgovara duže od 8 sekundi,
  2. ponoviti pokušaj ako dođe do greške sa zahtevom.

Za implementaciju, koristićemo sledeću definiciju resursa (sa-logic-retries-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. Vremenski limit za zahtev postavljen je na 8 sekundi;
  2. Ponovni pokušaji zahteva vrše se 3 puta;
  3. Vsaka poskus se šteje za neuspešnega, če čas odziva preseže 3 sekunde.

Tako smo dosegli optimizacijo, saj uporabnik ne bo moral čakati več kot 8 sekund, mi pa bomo opravili tri nove poskuse za pridobitev odgovora v primeru napak, kar povečuje verjetnost uspešnega odgovora.

Uvedite posodobljeno konfiguracijo z naslednjim ukazom:

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

In preverite v grafih Grafana, da je število uspešnih odgovorov preseglo:

Nazaj k mikrostoritev z Istio. Del 2
Izboljšave v statistiki uspešnih odgovorov po dodajanju časovnih omejitev in ponovnih poskusov

Preden preidemo na naslednji oddelek (oziroma že na naslednji del članka, ker v tem ne bo več praktičnih eksperimentov — op. prev.), izbrišite sa-logic-buggy in VirtualService tako, da izvedete naslednje ukaze:

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

Vzorce Circuit Breaker in Bulkhead

Gre za dva pomembna vzorca v mikroservisni arhitekturi, ki omogočata samostojno obnovitev (self-healing) servisov.

Circuit Breaker („samodejni stikalo“) se uporablja za prekinitev zahtevkov, ki prihajajo na primerke servisa, ki se šteje za bolnega, in njegovo obnovitev, medtem ko se zahtevki strank preusmerijo na zdrave primerke tega servisa (kar povečuje odstotek uspešnih odgovorov). (Op. prev.: Podrobnejši opis vzorca lahko najdete, na primer, ovde.)

Bulkhead („pregradu“) izolira okvare v storitvah od širjenja napak na celoten sistem. Na primer, servis B je pokvarjen, drug servis (stranka servisa B) pa pošlje zahtevo k servisu B, kar povzroči, da porabi svoj sklad niti in ne more obravnavati drugih zahtev (tudi če niso povezane s servisom B). (Op. prev.: Podrobnejši opis vzorca lahko najdete, na primer, ovde.)

Podrobnosti o implementaciji teh vzorcev bom izpustil, ker jih je enostavno najti v uradni dokumentaciji, poleg tega pa že zelo želim prikazati avtentikacijo in avtorizacijo, o čemer bo govora v naslednjem delu članka.

P.S. od prevajalca

Preberite tudi na našem blogu:

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster