Tilbage til mikroservices med Istio. Del 2

Tilbage til mikroservices med Istio. Del 2

Bem. overs.: Første del Denne cyklus var dedikeret til at introducere mulighederne for Istio og demonstrere dem i aktion. Nu vil vi fokusere på de mere komplekse aspekter af konfiguration og brug af dette service mesh, især den fint indstillede routing og trafikstyring.

Vi minder også om, at artiklen bruger konfigurationer (manifester til Kubernetes og Istio) fra depotet. istio-mastery.

Trafikstyring

Med Istio i klyngen opstår der nye muligheder, der gør det muligt at sikre:

  • Dynamisk routing af forespørgsler: kanary-udrulninger, A/B-test;
  • Lastbalancering: enkel og konsekvent, baseret på hashes;
  • Genopretning efter fejl: timeouts, genforsøg, circuit breakers;
  • Indsættelse af fejl: forsinkelser, afbrydelser af forespørgsler osv.

I fortsættelsen af artiklen vil disse muligheder blive vist ved hjælp af et udvalgt program, og nye koncepter vil desuden blive præsenteret. Den første af disse koncepter vil være DestinationRules (dvs. regler for modtageren af trafik/forespørgsler — red.)., som vi bruger til at aktivere A/B-test.

A/B-test: DestinationRules i praksis

A/B-test anvendes i situationer, hvor der findes to versioner af et program (de adskiller sig typisk visuelt), og vi ikke er sikre på 100%, hvilken der vil forbedre brugeroplevelsen. Derfor kører vi begge versioner samtidigt og indsamler metrics.

For at deploye den anden version af frontend’en, som er nødvendig til demonstration af A/B-test, skal du udføre følgende kommando:

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

Manifestet for deployment af 'grøn version' adskiller sig på to punkter:

  1. Billedet er baseret på en anden tag — istio-green,
  2. Pods har et label version: green.

Da begge deployment har label app: sa-frontend, vil forespørgsler, der routeres gennem den virtuelle tjeneste sa-external-services til tjenesten sa-frontend, blive omdirigeret til alle dens instanser, og belastningen vil blive fordelt via round-robin algoritmen, hvilket vil føre til følgende situation:

Tilbage til mikroservices med Istio. Del 2
Anmodede filer blev ikke fundet

Disse filer blev ikke fundet, fordi de har forskellige navne i de forskellige versioner af programmet. Lad os sikre os dette:

$ 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

Det betyder, at index.html, en anmodning om en version af statiske filer kan sendes af lastbalancer til pods, der har en anden version, hvor sådanne filer, af åbenlyse grunde, ikke eksisterer. Derfor er det nødvendigt for applikationen at fastsætte en begrænsning: «den samme version af applikationen, som leverede index.html, skal betjene de efterfølgende anmodninger».

Vi vil nå målet ved hjælp af konsistent belastningsbalancering baseret på hashing (Consistent Hash Loadbalancing). I dette tilfælde sendes anmodninger fra én klient til den samme backend-forekomst, hvilket opnås ved hjælp af en foruddefineret egenskab – for eksempel en HTTP-header. Dette implementeres med DestinationRules.

DestinationRules

Efter at VirtualService har dirigeret anmodningen til den rette service, kan vi ved hjælp af DestinationRules definere politikker, der vil blive anvendt på trafikken for de instanser af denne service:

Tilbage til mikroservices med Istio. Del 2
Trafikstyring med Istio-ressourcer

Bemærk: Indflydelsen af Istio-ressourcer på netværkstrafik præsenteres her i en forenklet forståelig form. For at være præcis, træffes beslutningen om, hvilken instans anmodningen skal sendes til, af Envoy i Ingress Gateway, der er konfigureret i CRD.

Ved hjælp af Destination Rules kan vi konfigurere lastbalancering, så der anvendes konsistente hashes, og der sikres, at den samme serviceinstans altid svarer til den samme bruger. Den følgende konfiguration muliggør dette (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 vil blive genereret baseret på indholdet af HTTP-headeren version.

Anvend konfigurationen med følgende kommando:

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

Udfør nu kommandoen nedenfor og bekræft, at du får de ønskede filer, når du angiver headeren version:

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

Bemærk: For at tilføje forskellige værdier til headeren og teste resultaterne direkte i browseren, kan du bruge denne udvidelse til Chrome (eller denne til Firefox — bem. overs..

Generelt har DestinationRules flere muligheder inden for lastbalancering — kontakt for nærmere oplysninger. den officielle dokumentation.

Før vi fortsætter med at studere VirtualService, fjerner vi den "grønne version" af applikationen og det tilsvarende trafikstyrringsregel ved at udføre følgende kommandoer:

$ 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

Spejling: Virtual Services i praksis

Shadowing ("skygge") eller Mirroring ("spejling") anvendes i situationer, hvor vi ønsker at teste en ændring i produktion uden at påvirke slutbrugerne: til dette duplikerer vi ("spejler") forespørgslerne til en anden instans, hvor de ønskede ændringer er foretaget, og ser på konsekvenserne. Sagt på en enklere måde, det er når din kollega tager det mest kritiske problem og laver en pull request i form af et så stort rod, at ingen rent faktisk kan anmelde det.

For at teste dette scenarie i aktion, opretter vi en anden instans af SA-Logic med fejl (buggy), ved at udføre følgende kommando:

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

Og nu udfører vi en kommando for at sikre os, at alle instanser med app=sa-logic også har etiketter med de relevante versioner:

$ kubectl get pods -l app=sa-logic --show-labels
NAVN                              KLAR   ETIKETTER
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

Service sa-logic er rettet mod pods med etiketten app=sa-logic, derfor vil alle forespørgsler blive fordel delt mellem alle instanser:

Tilbage til mikroservices med Istio. Del 2

… men vi ønsker, at forespørgsler skal sendes til instanser med version v1 og spejles til instanser med version v2:

Tilbage til mikroservices med Istio. Del 2

Dette vil vi opnå via VirtualService i kombination med DestinationRule, hvor reglerne vil bestemme delmængder og ruter for VirtualService til det specifikke delmængde.

Definition af delmængder i Destination Rules

Delmængder (subsets) defineres ved følgende konfiguration (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. Værten (host) definerer, at denne regel kun gælder, når ruten går mod tjenesten sa-logic;
  2. Navne (name) for delmængderne bruges til at rute til instanser i delmængden;
  3. Etiketten (label) definerer nøgle-værdi par, som instanser skal opfylde for at blive en del af undergruppen.

Anvend konfigurationen med følgende kommando:

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

Nu hvor undergrupperne er defineret, kan vi gå videre og konfigurere VirtualService til at anvende reglerne på anmodninger til sa-logic, så de:

  1. Rutes til undergruppen v1,
  2. Spejles til undergruppen v2.

Den næste manifest opnår det ønskede (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

Der er ikke behov for forklaringer her, så lad os se det i aktion:

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

Lad os tilføje belastningen ved at kalde denne kommando:

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

Lad os se på resultaterne i Grafana, hvor vi kan se, at versionen med fejl (buggy) forårsager fejlslag til ~60 % af anmodningerne, men ingen af disse fejl påvirker de endelige brugere, da de får svar fra den fungerende tjeneste.

Tilbage til mikroservices med Istio. Del 2
Succesen af svarene fra forskellige versioner af tjenesten sa-logic

Her så vi første gang, hvordan VirtualService anvendes i forhold til vores tjenesters Envoy’er: når sa-web-app der gør en anmodning til sa-logic, går den gennem sidecar Envoy, som – via VirtualService – er konfigureret til at rute anmodningen til undergruppen v1 og spejle anmodningen til undergruppen v2 af tjenesten sa-logic.

Jeg ved: du har allerede tænkt, at Virtual Services er enkle. I det næste afsnit vil vi udvide denne opfattelse ved at vise, at de rent faktisk også er fantastiske.

Canary deployments

Canary Deployment er processen med at rulle en ny version af applikationen ud til et lille antal brugere. Det bruges til at sikre, at der ikke er problemer i udgivelsen, og først derefter, når man er sikker på, at kvaliteten af udgivelsen er tilstrækkelig, udbrede den til enfleste afstørre audience.

For at demonstrere canary-udrulninger vil vi fortsætte arbejdet med undergruppen buggy af sa-logic.

Lad os ikke være smålige og sende 20 % af brugerne direkte til versionen med fejl (det vil være vores canary-udrulning), mens de resterende 80 % går til den normale tjeneste. For dette anvender vi følgende 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 — dette er vægten (weight), der bestemmer procentdelen af anmodninger, der sendes til modtageren eller en undergruppe af modtageren.

Lad os opdatere den tidligere VirtualService-konfiguration med sa-logic følgende kommando:

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

… og vi vil straks se, at en del af anmodningerne fører til fejl:

$ 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 aktiverer kanary-udrulninger: i dette tilfælde har vi indsnævret de potentielle konsekvenser af problemer til 20 % af brugerbasen. Fantastisk! Nu, hver gang vi ikke er sikre på vores kode (med andre ord — altid...), kan vi bruge spejling og kanary-udrulninger.

Timeouts og genforsøg

Men fejl ligger ikke altid i koden. På listen over „8 misforståelser i distribuerede computere” er det fejlaktige indtryk, at „netværket er pålideligt“ det første punkt. I virkeligheden er netværket ikke pålideligt, og derfor har vi brug for timeouts (timeouts) og genforsøg (retries).

For at demonstrere vil vi fortsætte med den samme problemversion sa-logic (buggy), mens netværksusikkerheden vil blive simuleret med tilfældige fejl.

Lad vores fejlbehæftede service have 1/3 chance for et for langvarigt svar, 1/3 chance for at afslutte med en Internal Server Error, og 1/3 chance for at returnere en succesfuld side.

For at mildne konsekvenserne af sådanne problemer og gøre livet lettere for brugerne kan vi:

  1. tilføje en timeout, hvis servicen svarer længere end 8 sekunder,
  2. foretage et genforsøg, hvis anmodningen fejler.

Til implementeringen vil vi bruge følgende ressourcebeskrivelse (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. Timeout for anmodningen er indstillet til 8 sekunder;
  2. Genforsøg af anmodninger foretages 3 gange;
  3. Og hver forsøg betragtes som mislykket, hvis svartiden overstiger 3 sekunder.

På denne måde opnåede vi optimering, da brugeren ikke vil skulle vente mere end 8 sekunder, og vi vil foretage tre nye forsøg på at få et svar i tilfælde af fejl og dermed øge chancen for et succesfuldt svar.

Anvend den opdaterede konfiguration med følgende kommando:

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

Og tjek i Grafana-diagrammerne, at antallet af succesfulde svar er steget over:

Tilbage til mikroservices med Istio. Del 2
Forbedringer i statistikken for succesfulde svar efter tilføjelse af tidsgrænser og gentagelser

Før vi går videre til næste sektion (eller rettere sagt - allerede til næste del af artiklen, da der ikke vil være flere praktiske eksperimenter i denne - bem. overs.), slet sa-logic-buggy og VirtualService ved at udføre følgende kommandoer:

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

Mønstre for Circuit Breaker og Bulkhead

Det handler om to vigtige mønstre i mikrotjenestearkitektur, der muliggør selvhelbredelse (self-healing) af tjenester.

Circuit Breaker («automatiske afbryder») bruges til at stoppe anmodninger, der kommer til en tjenesteinstans, der betragtes som usund, og dens genopretning, mens anmodninger fra kunder omdirigeres til sunde instanser af denne tjeneste (hvilket øger procentdelen af succesfulde svar). (Bem. overs.: En mere detaljeret beskrivelse af mønsteret kan findes, f.eks. her.)

Bulkhead («skillevæg») isolerer fejl i tjenester fra at påvirke hele systemet. For eksempel, hvis tjeneste B er nede, og en anden tjeneste (klient af tjeneste B) laver en anmodning til tjeneste B, vil den udnytte sin trådpool og ikke være i stand til at håndtere andre anmodninger (selv hvis de ikke relaterer til tjeneste B). (Bem. overs.: En mere detaljeret beskrivelse af mønsteret kan findes, f.eks. her.)

Jeg vil undlade at gå ind i detaljerne om implementeringen af disse mønstre, da de er lette at finde, den officielle dokumentation, og jeg vil virkelig gerne vise autentificering og autorisation, som vil blive behandlet i den næste del af artiklen.

P.S. fra oversætteren

Læs også på vores blog:

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster