Tillbaka till mikrotjänster med Istio. Del 2

Tillbaka till mikrotjänster med Istio. Del 2

Notera. transl.: Den första delen Den här serien var tillägnad att introducera Istio-funktioner och visa dem i aktion. Nu kommer vi att prata om mer komplexa aspekter av konfigurationen och användningen av detta tjänstnät, och i synnerhet om finjusterad routing och nätverkstrafikhantering.

Vi påminner dig också om att artikeln använder konfigurationer (manifest för Kubernetes och Istio) från förvaret istio-mästarskap.

Trafikledning

Med Istio dyker nya funktioner upp i klustret för att ge:

  • Dynamisk förfrågningsdirigering: utrullningar av kanariefåglar, A/B-testning;
  • Lastbalansering: enkel och konsekvent, baserad på hash;
  • Återhämtning efter fall: timeouts, återförsök, strömbrytare;
  • Att lägga in fel: förseningar, uteblivna förfrågningar, etc.

När artikeln fortsätter kommer dessa funktioner att illustreras med den valda applikationen som exempel och nya koncept kommer att introduceras längs vägen. Det första sådant konceptet kommer att vara DestinationRules (dvs regler om mottagare av trafik/förfrågningar - ca översättning), med vars hjälp vi aktiverar A/B-testning.

A/B-testning: DestinationRules i praktiken

A/B-testning används i fall där det finns två versioner av en applikation (vanligtvis är de visuellt olika) och vi är inte 100% säkra på vilken som kommer att förbättra användarupplevelsen. Därför kör vi båda versionerna samtidigt och samlar in mätvärden.

För att distribuera den andra versionen av frontend, som krävs för att demonstrera A/B-testning, kör följande kommando:

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

Implementeringsmanifestet för den gröna versionen skiljer sig på två ställen:

  1. Bilden är baserad på en annan tagg - istio-green,
  2. Pods har en etikett version: green.

Eftersom båda distributionerna har en etikett app: sa-frontend,förfrågningar dirigeras av virtuell tjänst sa-external-services för service sa-frontend, kommer att omdirigeras till alla dess instanser och belastningen kommer att distribueras genom round-robin algoritm, vilket kommer att leda till följande situation:

Tillbaka till mikrotjänster med Istio. Del 2
De begärda filerna hittades inte

Dessa filer hittades inte eftersom de heter olika i olika versioner av programmet. Låt oss se till detta:

$ 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 att index.html, som begär en version av statiska filer, kan skickas av lastbalanseraren till pods som har en annan version, där sådana filer av uppenbara skäl inte finns. Därför, för att applikationen ska fungera måste vi sätta en begränsning: "samma version av programmet som serverade index.html ska tjäna efterföljande förfrågningar".

Vi kommer att nå dit med konsekvent hash-baserad lastbalansering (Konsekvent Hash Load Balancing). I det här fallet förfrågningar från samma klient skickas till samma backend-instans, för vilken en fördefinierad egenskap används - till exempel en HTTP-rubrik. Implementerat med hjälp av DestinationRules.

Destinationsregler

Efter VirtualService skickade en begäran till den önskade tjänsten, med hjälp av DestinationRules kan vi definiera policyer som kommer att tillämpas på trafik avsedd för instanser av denna tjänst:

Tillbaka till mikrotjänster med Istio. Del 2
Trafikledning med Istio-resurser

Notera: Istio-resursernas inverkan på nätverkstrafiken presenteras här på ett sätt som är lätt att förstå. För att vara exakt, beslutet om vilken instans förfrågan ska skickas till fattas av sändebudet i Ingress Gateway som konfigurerats i CRD.

Med Destination Rules kan vi konfigurera lastbalansering för att använda konsekventa hash och säkerställa att samma tjänsteinstans svarar på samma användare. Följande konfiguration låter dig uppnå detta (destinationsregel-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 kommer att genereras baserat på innehållet i HTTP-huvudet version.

Använd konfigurationen med följande kommando:

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

Kör nu kommandot nedan och se till att du får rätt filer när du anger rubriken version:

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

Notera: För att lägga till olika värden i rubriken och testa resultaten direkt i webbläsaren kan du använda denna förlängning till Chrome (eller med detta för Firefox - ca. översätt.).

I allmänhet har DestinationRules fler möjligheter inom området lastbalansering - kolla för detaljer i officiell dokumentation.

Innan vi studerar VirtualService vidare, låt oss ta bort den "gröna versionen" av applikationen och motsvarande trafikriktningsregel genom att köra följande kommandon:

$ 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

Spegling: virtuella tjänster i praktiken

skuggning ("avskärmning") eller Spegling ("spegling") används i fall där vi vill testa en förändring i produktionen utan att påverka slutanvändarna: för att göra detta duplicerar (”speglar”) vi förfrågningar till en andra instans där de önskade ändringarna har gjorts, och tittar på konsekvenserna. Enkelt uttryckt är det när din kollega väljer den mest kritiska frågan och gör en pull-begäran i form av en så enorm smutsklump att ingen faktiskt kan granska den.

För att testa detta scenario i aktion, låt oss skapa en andra instans av SA-Logic med buggar (buggy) genom att köra följande kommando:

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

Och låt oss nu köra kommandot för att se till att alla instanser med app=sa-logic De har också etiketter med motsvarande versioner:

$ 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

Tjänsten sa-logic riktar in sig på baljor med en etikett app=sa-logic, så alla förfrågningar kommer att distribueras till alla instanser:

Tillbaka till mikrotjänster med Istio. Del 2

... men vi vill att förfrågningar ska skickas till v1-instanser och speglas till v2-instanser:

Tillbaka till mikrotjänster med Istio. Del 2

Vi kommer att uppnå detta genom VirtualService i kombination med DestinationRule, där reglerna kommer att bestämma delmängder och rutter för VirtualService till en specifik delmängd.

Definiera delmängder i destinationsregler

Delmängder (delmängder) bestäms av följande 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ärd (host) definierar att denna regel endast gäller fall då rutten går mot tjänsten sa-logic;
  2. Titlar (name) delmängder används vid routning till delmängdsinstanser;
  3. Etikett (label) definierar nyckel-värdeparen som instanser måste matcha för att bli en del av delmängden.

Använd konfigurationen med följande kommando:

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

Nu när delmängderna är definierade kan vi gå vidare och konfigurera VirtualService för att tillämpa regler på förfrågningar till sa-logic så att de:

  1. Leds till en delmängd v1,
  2. Speglad till en delmängd v2.

Följande manifest låter dig uppnå dina planer (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

Ingen förklaring behövs här, så låt oss bara se det i aktion:

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

Låt oss lägga till belastningen genom att anropa följande kommando:

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

Låt oss titta på resultaten i Grafana, där du kan se att versionen med buggar (buggy) resulterar i misslyckanden för ~60 % av förfrågningarna, men inget av dessa fel påverkar slutanvändare eftersom de besvaras av en tjänst som körs.

Tillbaka till mikrotjänster med Istio. Del 2
Framgångsrika svar av olika versioner av sa-logic-tjänsten

Här såg vi först hur VirtualService tillämpas på våra tjänsters sändebud: när sa-web-app gör en begäran till sa-logic, går den genom sidovagnen Envoy, som - via VirtualService - är konfigurerad att dirigera begäran till v1-delmängden och spegla begäran till v2-delmängden av tjänsten sa-logic.

Jag vet, du kanske redan tror att virtuella tjänster är enkelt. I nästa avsnitt kommer vi att utöka det genom att säga att de också är riktigt bra.

Kanarie-utrullningar

Canary Deployment är processen att rulla ut en ny version av en applikation till ett litet antal användare. Det används för att se till att det inte finns några problem i releasen och först efter det, som redan är säker på dess (releasens) kvalitet, distribuerar den till andra användare.оstörre publik.

För att demonstrera utrullningar av kanariefåglar kommer vi att fortsätta arbeta med en delmängd buggy у sa-logic.

Låt oss inte slösa tid på bagateller och omedelbart skicka 20 % av användarna till versionen med buggar (detta kommer att representera vår kanariefågel) och de återstående 80 % till den normala tjänsten. För att göra detta, använd följande 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 är vikten (weight), som anger procentandelen förfrågningar som kommer att riktas till en mottagare eller en delmängd av mottagaren.

Låt oss uppdatera den tidigare VirtualService-konfigurationen för sa-logic med följande kommando:

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

... och vi kommer omedelbart att se att vissa förfrågningar leder till misslyckanden:

$ 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 möjliggör utrullning av kanariefåglar: I det här fallet har vi minskat den potentiella effekten av problemen till 20 % av användarbasen. Underbar! Nu, i alla fall när vi inte är säkra på vår kod (med andra ord - alltid...), kan vi använda spegling och kanariefågel.

Timeout och återförsök

Men buggar hamnar inte alltid i koden. I listan från "8 Missuppfattningar om distribuerad datoranvändning"I första hand är den felaktiga tron ​​att "nätverket är pålitligt." I verkligheten nätverket ingen pålitlig, och därför behöver vi timeouts (timeout) och försöker igen (försöker igen).

För demonstration kommer vi att fortsätta att använda samma problemversion sa-logic (buggy), och vi kommer att simulera nätverkets opålitlighet med slumpmässiga fel.

Låt vår tjänst med buggar ha en 1/3 chans att ta för lång tid att svara, en 1/3 chans att sluta med ett internt serverfel och en 1/3 chans att framgångsrikt returnera sidan.

För att mildra effekterna av sådana problem och göra livet bättre för användarna kan vi:

  1. lägg till en timeout om tjänsten tar längre tid än 8 sekunder att svara,
  2. försök igen om begäran misslyckas.

För implementering kommer vi att använda följande resursdefinition (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. Tidsgränsen för begäran är inställd på 8 sekunder;
  2. Förfrågningar prövas igen 3 gånger;
  3. Och varje försök anses misslyckat om svarstiden överstiger 3 sekunder.

Detta är en optimering eftersom användaren inte behöver vänta mer än 8 sekunder och vi kommer att göra tre nya försök för att få ett svar vid misslyckanden, vilket ökar chansen för ett lyckat svar.

Använd den uppdaterade konfigurationen med följande kommando:

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

Och kolla i Grafana-graferna att antalet lyckade svar har ökat ovan:

Tillbaka till mikrotjänster med Istio. Del 2
Förbättringar av framgångsrik svarsstatistik efter att tidsgränser lagts till och omförsök

Innan du går vidare till nästa avsnitt (eller snarare, till nästa del av artikeln, för i denna kommer det inte att finnas fler praktiska experiment - ca översättning), radera sa-logic-buggy och VirtualService genom att köra följande kommandon:

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

Kretsbrytare och skottmönster

Vi pratar om två viktiga mönster i mikrotjänstarkitektur som gör att du kan uppnå självåterställning (självläkande) tjänster.

Strömbrytare ("strömbrytare") används för att avsluta förfrågningar som kommer till en instans av en tjänst som anses ohälsosam och återställa den medan klientförfrågningar omdirigeras till sunda instanser av den tjänsten (vilket ökar andelen framgångsrika svar). (Obs: En mer detaljerad beskrivning av mönstret finns t.ex. här.)

Skott ("dela") isolerar tjänstefel från att påverka hela systemet. Till exempel är tjänst B trasig och en annan tjänst (tjänst B:s klient) gör en begäran till tjänst B, vilket får den att tömma sin trådpool och inte kunna betjäna andra förfrågningar (även om de inte är från tjänst B). (Obs: En mer detaljerad beskrivning av mönstret finns t.ex. här.)

Jag kommer att utelämna implementeringsdetaljerna för dessa mönster eftersom de är lätta att hitta i officiell dokumentation, och jag vill också verkligen visa autentisering och auktorisering, vilket kommer att diskuteras i nästa del av artikeln.

PS från översättaren

Läs även på vår blogg:

Källa: will.com

Lägg en kommentar