Terug naar microservices met Istio. Deel 2

Terug naar microservices met Istio. Deel 2

Opmerking vertaler.: Eerste deel van deze cyclus was gewijd aan het kennismaken met de mogelijkheden van Istio en hun demonstratie in de praktijk. Nu gaan we het hebben over complexere aspecten van configuratie en gebruik van dit service mesh, met name over fijn afstelbare routering en netwerkverkeer beheer.

We herinneren u eraan dat in het artikel configuraties (manifests voor Kubernetes en Istio) uit de repository worden gebruikt istio-mastery.

Verkeersbeheer

Met Istio komen er nieuwe mogelijkheden in de cluster, waarmee kan worden verzekerd:

  • Dynamische routering van verzoeken: canary releases, A/B-testen;
  • Lastbalancering: eenvoudig en consistent, gebaseerd op hashes;
  • Herstel na uitval: time-outs, herhalingspogingen, circuit breakers;
  • Fouteninjectie: vertragingen, verzoekonderbrekingen, enz.

In de voortzetting van het artikel zullen deze mogelijkheden worden getoond aan de hand van een gekozen applicatie en tegelijkertijd nieuwe concepten worden gepresenteerd. Het eerste dergelijke concept zal zijn DestinationRules (d.w.z. regels voor het bestemmingsverkeer/ verzoeken - opmerking vertaler.), waarmee we A/B-testen activeren.

A/B-testen:  DestinationRules in de praktijk

A/B-testen wordt toegepast in gevallen waarin er twee versies van de applicatie bestaan (meestal verschillen ze visueel) en we niet 100% zeker zijn welke versie de gebruikerservaring verbetert. Daarom draaien we beide versies gelijktijdig en verzamelen we metrics.

Voor de deploy van de tweede versie van de frontend, die nodig is voor de demonstratie van A/B-testen, voert u de volgende opdracht uit:

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

Het manifest van de deployment voor de "groene versie" verschilt op twee plaatsen:

  1. Het image is gebaseerd op een andere tag - istio-green,
  2. Pods hebben een label version: green.

Aangezien beide deployments een label hebben app: sa-frontend, worden verzoeken die worden gerouteerd via de virtuele service sa-external-services naar de service sa-frontend, worden omgeleid naar al zijn instanties en wordt de belasting verdeeld via het round-robin algoritme, wat zal leiden tot de volgende situatie:

Terug naar microservices met Istio. Deel 2
Opgevraagde bestanden niet gevonden

Deze bestanden zijn niet gevonden omdat ze verschillende namen hebben in verschillende versies van de applicatie. Laten we dat bevestigen:

$ 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

Dit betekent dat index.html, die een versie van statische bestanden aanvraagt, kan door de load balancer naar pods worden gestuurd die een andere versie hebben, waar om begrijpelijke redenen dergelijke bestanden niet bestaan. Daarom moeten we om de applicatie te laten werken een beperking stellen: “dezelfde versie van de applicatie die index.html heeft teruggegeven, moet ook latere aanvragen afhandelen».

We zullen ons doel bereiken met behulp van consistente load balancing op basis van hashes (Consistente Hash Loadbalancing). In dit geval worden aanvragen van dezelfde cliënt naar dezelfde backend-instantie gestuurd, waarvoor een vooraf gedefinieerde eigenschap wordt gebruikt — bijvoorbeeld een HTTP-header. Dit wordt geïmplementeerd met behulp van DestinationRules.

DestinationRules

Nadat VirtualService de aanvraag naar de juiste service heeft gestuurd, kunnen we met behulp van DestinationRules beleidsregels bepalen die van toepassing zijn op het verkeer dat is bedoeld voor de instanties van deze service:

Terug naar microservices met Istio. Deel 2
Trafficmanagement met Istio-resources

Opmerking: De invloed van Istio-resources op netwerkverkeer wordt hier in een vereenvoudigde weergave gepresenteerd. Om precies te zijn, wordt de beslissing over naar welke instantie de aanvraag moet worden verzonden, genomen door Envoy in de Ingress Gateway, die is geconfigureerd in CRD.

Met behulp van Destination Rules kunnen we de load balancing zo configureren dat consistente hashes worden gebruikt en dat dezelfde instantie van de service antwoorden garandeert aan dezelfde gebruiker. De volgende configuratie stelt ons in staat om dit te bereiken (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 — de hash wordt gegenereerd op basis van de inhoud van de HTTP-header version.

Pas de configuratie toe met de volgende opdracht:

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

Voer nu de onderstaande opdracht uit en zorg ervoor dat je de gewenste bestanden ontvangt wanneer je de header opgeeft version:

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

Opmerking: Om verschillende waarden aan de header toe te voegen en resultaten direct in de browser te testen, kun je gebruik maken van deze extensie voor Chrome (of deze voor Firefox — red. vert.).

In feite hebben DestinationRules meer mogelijkheden op het gebied van load balancing — voor details, neem contact op met de officiële documentatie.

Voordat we verder gaan met het bestuderen van VirtualService, verwijderen we de 'groene versie' van de applicatie en de bijbehorende verkeersregel door de volgende commando's uit te voeren:

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

Shadowing: Virtual Services in de praktijk

Shadowing (“afscherming”) of Mirroring (“reflectie”) wordt toegepast in situaties waarin we een wijziging in productie willen testen zonder eindgebruikers te beïnvloeden: hiervoor dupliceren we (”reflecteren“) verzoeken naar een tweede instantie waar de noodzakelijke wijzigingen zijn aangebracht en observeren we de gevolgen. Simpel gezegd, dit is wanneer je collegae de meest kritieke issue selecteert en een pull request doet in de vorm van een enorme rommel, zodat niemand werkelijk een review kan uitvoeren.

Om dit scenario in actie te controleren, zullen we een tweede instantie van SA-Logic met bugs creëren (buggy), door het volgende commando uit te voeren:

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

En nu zullen we het commando uitvoeren om te controleren of alle instanties met app=sa-logic ook labels hebben met de bijbehorende versies:

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

Dienst sa-logic gericht op pods met het label app=sa-logic, daarom zullen alle verzoeken worden verdeeld over alle instanties:

Terug naar microservices met Istio. Deel 2

… maar we willen dat de verzoeken worden gericht op instanties met versie v1 en worden gereflecteerd op instanties met versie v2:

Terug naar microservices met Istio. Deel 2

Dit bereiken we via VirtualService in combinatie met DestinationRule, waar de regels subsets en routes van VirtualService naar een specifieke subset definiëren.

Definitie van subsets in Destination Rules

Subsets (subsets) worden gedefinieerd door de volgende configuratie (sa-logic-subsets-destinationrule.yaml):

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

  1. De host (host) definieert dat deze regel alleen van toepassing is wanneer de route naar de service gaat sa-logic;
  2. De namen (naam) van de subsets worden gebruikt bij het routeren naar de instanties van de subset;
  3. Het label (label) bepaalt de sleutel-waardeparen waaraan de instanties moeten voldoen om deel uit te maken van een subset.

Pas de configuratie toe met de volgende opdracht:

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

Nu de subsets zijn gedefinieerd, kunnen we verder gaan met het instellen van de VirtualService om regels toe te passen op verzoeken aan sa-logic, zodat ze:

  1. worden gerouteerd naar de subset v1,
  2. worden gespiegeld naar de subset v2.

De volgende manifest maakt het mogelijk om het gewenste resultaat te bereiken (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

Hier zijn geen verdere uitleggen nodig, laten we gewoon eens kijken hoe het werkt:

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

Laten we de belasting introduceren met de volgende opdracht:

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

Laten we de resultaten bekijken in Grafana, waar we kunnen zien dat de versie met bugs (buggy) leidt tot fouten voor ~60% van de verzoeken, maar geen van deze fouten beïnvloedt de eindgebruikers, omdat zij antwoorden ontvangen van de werkende service.

Terug naar microservices met Istio. Deel 2
De succesratio van de verschillende versies van de sa-logic service

Hier hebben we voor het eerst gezien hoe de VirtualService wordt toegepast op de Envoy’s van onze services: wanneer sa-web-app een verzoek doet aan sa-logic, gaat dit via de sidecar Envoy, die - via de VirtualService - is ingesteld om het verzoek te routeren naar de subset v1 en het verzoek te spiegelen naar de subset v2 van de service sa-logic.

Ik weet dat je al hebt gedacht dat Virtual Services eenvoudig zijn. In het volgende deel zullen we deze opvatting uitbreiden door aan te tonen dat ze ook werkelijk geweldig zijn.

Canary-releases

Canary Deployment is het proces van het uitrollen van een nieuwe versie van een applicatie naar een klein aantal gebruikers. Dit wordt gebruikt om ervoor te zorgen dat er geen problemen zijn met de release, en pas daarna, als men zeker is van de kwaliteit van de release, deze uit te rollen naar eengroter publiek.Voor de demonstratie van canary-releases zullen we doorwerken met de subset

Laten we grootser denken en meteen 20% van de gebruikers naar de buggy versie sturen (dit zal onze canary-release zijn), terwijl de overige 80% naar de normale service gaan. Hiervoor zullen we de volgende VirtualService toepassen ( buggy ‘ sa-logic.

sa-logic-subsets-canary-vs.yamlsa-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 — dit is het gewicht (gewicht), dat het percentage aanvragen bepaalt, die naar de ontvanger of de subset van de ontvanger worden gestuurd.

Laten we de vorige VirtualService-configuratie bijwerken met sa-logic het volgende commando:

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

… en we zien meteen dat een aantal aanvragen faalt:

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

VirtualServices activeren canary-releases: in dit geval hebben we de potentiële gevolgen van problemen beperkt tot 20% van onze gebruikersbasis. Geweldig! Nu, elke keer dat we niet zeker zijn van onze code (met andere woorden — altijd…), kunnen we mirroring en canary-releases gebruiken.

Timeouts en herhalingen

Maar niet alle bugs zitten in de code. Op de lijst van "8 misvattingen in gedistribueerde computing" staat ten eerste de foutieve overtuiging dat "netwerk is betrouwbaar". In werkelijkheid is het netwerk niet betrouwbaar, en daarom hebben we timeouts (timeouts) en herhalingen (retries).

Voor de demonstratie blijven we dezelfde probleemversie gebruiken, sa-logic (buggy), terwijl we de onbetrouwbaarheid van het netwerk simuleren met willekeurige storingen.

Laten we zeggen dat onze service met bugs een kans van 1/3 heeft op een te lange respons, 1/3 op een Internal Server Error, en 1/3 op een succesvolle paginaweergave.

Om de gevolgen van dergelijke problemen te verzachten en het leven van gebruikers beter te maken, kunnen we:

  1. een timeout toevoegen als de service langer dan 8 seconden reageert,
  2. en een herhaling uitvoeren als er een fout optreedt bij de aanvraag.

Voor de implementatie zullen we deze resource-definitie gebruiken (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. De timeout voor de aanvraag is ingesteld op 8 seconden;
  2. De aanvragen worden 3 keer opnieuw geprobeerd;
  3. En elke poging wordt als onsuccesvol beschouwd als de reactietijd meer dan 3 seconden bedraagt.

Zo hebben we optimalisatie bereikt, omdat de gebruiker niet langer dan 8 seconden hoeft te wachten en we drie nieuwe pogingen ondernemen om een reactie te ontvangen in geval van storingen, waardoor de kans op een succesvolle reactie toeneemt.

Pas de bijgewerkte configuratie toe met de volgende opdracht:

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

En controleer in de Grafana-diagrammen of het aantal succesvolle reacties is gestegen boven:

Terug naar microservices met Istio. Deel 2
Verbeteringen in de statistieken van succesvolle reacties na het toevoegen van time-outs en herhalingen

Voordat we naar de volgende sectie gaan (of beter gezegd – al naar het volgende deel van het artikel, aangezien er verder geen praktische experimenten meer zullen zijn – opmerking van de vertaler), verwijder sa-logic-buggy en VirtualService door de volgende opdrachten uit te voeren:

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

Circuit Breaker en Bulkhead Patronen

Dit betreft twee belangrijke patronen in microservices-architectuur die zelfherstel mogelijk maken (self-healing) van diensten.

Circuit Breaker («automatische schakelaar») wordt gebruikt om verzoeken te stoppen die worden gestuurd naar een dienstinstantie die als ongezond wordt beschouwd, en deze te herstellen terwijl cliëntverzoeken worden omgeleid naar gezonde instanties van deze dienst (wat het percentage succesvolle reacties verhoogt). (Opmerking van de vertaler: Een gedetailleerdere beschrijving van het patroon is te vinden, bijvoorbeeld, hier.)

Bulkhead («wand») isoleert storingen in diensten van het verlammen van het hele systeem. Bijvoorbeeld, dienst B is kapot, en een andere dienst (de cliënt van dienst B) doet een verzoek aan dienst B, waardoor deze zijn thread pool uitput en geen andere verzoeken meer kan verwerken (zelfs als deze niet betrekking hebben op dienst B). (Opmerking van de vertaler: Een gedetailleerdere beschrijving van het patroon is te vinden, bijvoorbeeld, hier.)

Ik zal de details van de implementatie van deze patronen weglaten, omdat ze gemakkelijk te vinden zijn in de officiële documentatie, en ik wil ook echt de authenticatie en autorisatie laten zien, waar het in het volgende deel van het artikel over zal gaan.

P.S. van de vertaler

Lees ook op onze blog:

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers 🔥 Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster