ZurĂŒck zu den Mikrodiensten mit Istio. Teil 2

ZurĂŒck zu den Mikrodiensten mit Istio. Teil 2

Hinweis.: Erster Teil In diesem Abschnitt werden die Möglichkeiten von Istio vorgestellt und deren praktische Anwendung demonstriert. Nun gehen wir auf komplexere Aspekte der Konfiguration und Nutzung dieses Service Mesh ein, insbesondere auf die feinfĂŒhlige Einrichtung der Routing-Strategien und das Management des Netzwerkverkehrs.

Wir erinnern außerdem daran, dass in diesem Artikel Konfigurationen (Manifestdateien fĂŒr Kubernetes und Istio) aus dem Repository verwendet werden. istio-mastery.

Traffic-Management

Mit Istio im Cluster eröffnen sich neue Möglichkeiten, um Folgendes zu gewÀhrleisten:

  • Dynamisches Routing von Anfragen: Canary-Releases, A/B-Tests;
  • Lastverteilung: einfach und konsistent, basierend auf Hashes;
  • Wiederherstellung nach AusfĂ€llen: Timeouts, Wiederholungsversuche, Circuit Breakers;
  • Fehlerbehebung: Verzögerungen, AbbrĂŒche von Anfragen usw.

Im weiteren Verlauf des Artikels werden diese Möglichkeiten anhand einer ausgewĂ€hlten Anwendung gezeigt, wĂ€hrend neue Konzepte vorgestellt werden. Das erste dieser Konzepte wird DestinationRules sein (d.h. Regeln fĂŒr den EmpfĂ€nger des Verkehrs/der Anfragen – Anm. des Übersetzers),mit denen wir A/B-Tests aktivieren.

A/B-Test: DestinationRules in der Praxis

A/B-Tests werden eingesetzt, wenn es zwei Versionen einer Anwendung gibt (hÀufig unterscheiden sie sich visuell) und wir uns nicht sicher sind, welche Version die Benutzerinteraktion verbessert. Daher starten wir beide Versionen gleichzeitig und sammeln die Metriken.

Um die zweite Version des Frontends, die fĂŒr die Demonstration des A/B-Tests erforderlich ist, bereitzustellen, fĂŒhren Sie den folgenden Befehl aus:

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

Das Manifest des Deployments fĂŒr die „grĂŒne Version“ unterscheidet sich an zwei Stellen:

  1. Das Image basiert auf einem anderen Tag — istio-green,
  2. Die Pods haben das Label version: green.

Da beide Deployments das Label app: sa-frontend, Anfragen, die vom virtuellen Dienst sa-external-services an den Dienst sa-frontend, werden an all seine Instanzen weitergeleitet, und die Last wird durch den Round-Robin-Algorithmus, was zu folgender Situation fĂŒhrt:

ZurĂŒck zu den Mikrodiensten mit Istio. Teil 2
Angeforderte Dateien nicht gefunden

Diese Dateien wurden nicht gefunden, da sie in den verschiedenen Versionen der Anwendung unterschiedlich benannt sind. Lassen Sie uns das ĂŒberprĂŒfen:

$ 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

Das bedeutet, dass index.html, der eine Version statischer Dateien anfordert, kann vom Lastenausgleich auf Pods mit einer anderen Version geleitet werden, wo aus verstĂ€ndlichen GrĂŒnden solche Dateien nicht existieren. Daher mĂŒssen wir, damit die Anwendung funktioniert, eine EinschrĂ€nkung festlegen: „die gleiche Version der Anwendung, die index.html geliefert hat, muss auch die nachfolgenden Anfragen bedienen».

. Wir erreichen dies durch konsistente Lastenverteilung basierend auf Hashes (Consistent Hash Loadbalancing). In diesem Fall werden Anfragen eines Clients an dasselbe Backend-Exemplar gesendet, wobei eine vordefinierte Eigenschaft verwendet wird – zum Beispiel ein HTTP-Header. Dies wird durch DestinationRules umgesetzt.

DestinationRules

Sobald VirtualService hat die Anfrage an den gewĂŒnschten Dienst geleitet, mit DestinationRules können wir die Richtlinien definieren, die auf den Verkehr angewandt werden, der an die Exemplare dieses Dienstes gerichtet ist:

ZurĂŒck zu den Mikrodiensten mit Istio. Teil 2
Verkehrsmanagement mit Istio-Ressourcen

Hinweis: Der Einfluss von Istio-Ressourcen auf den Netzwerkverkehr wird hier in einer einfach zu verstehenden Form dargestellt. Genauer gesagt, die Entscheidung, an welches Exemplar die Anfrage gesendet werden soll, wird von Envoy im Ingress Gateway getroffen, das in CRD konfiguriert ist.

Mit Destination Rules können wir das Load Balancing so konfigurieren, dass konsistente Hashes verwendet werden und die Antworten von derselben Serviceinstanz an denselben Benutzer garantiert werden. Die folgende Konfiguration ermöglicht dies (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 — der Hash wird basierend auf dem Inhalt des HTTP-Headers generiert version.

Wenden Sie die Konfiguration mit dem folgenden Befehl an:

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

FĂŒhren Sie jetzt den folgenden Befehl aus und stellen Sie sicher, dass Sie die gewĂŒnschten Dateien erhalten, wenn Sie den Header angeben version:

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

Hinweis: Um verschiedene Werte im Header hinzuzufĂŒgen und die Ergebnisse direkt im Browser zu testen, können Sie diese Erweiterung nutzen fĂŒr Chrome (oder diesen hier fĂŒr Firefox — Anmerkung des Übersetzers).

Generell bieten Destination Rules jedoch mehr Möglichkeiten im Bereich des Load Balancing — fĂŒr weitere Informationen wenden Sie sich bitte an offiziellen Dokumentation.

Bevor wir weiter in VirtualService eintauchen, entfernen wir die „grĂŒne Version“ der Anwendung sowie die entsprechende Verkehrsregel, indem wir die folgenden Befehle ausfĂŒhren:

$ kubectl delete -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions "sa-frontend-green" gelöscht
$ kubectl delete -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io "sa-frontend" gelöscht

Mirroring: Virtual Services in der Praxis

Shadowing („Verdeckung“) oder Mirroring („Spiegelung“) wird verwendet, wenn wir eine Änderung in der Produktion testen möchten, ohne die Endbenutzer zu beeinflussen: Dazu duplizieren wir („spiegeln“) die Anfragen an eine zweite Instanz, in der die erforderlichen Änderungen vorgenommen wurden, und beobachten die Auswirkungen. Einfacher gesagt, das ist, wenn Ihr Kollege das kritischste Problem auswĂ€hlt und einen Pull Request stellt, der so ein großer Haufen Matsch ist, dass niemand ihn tatsĂ€chlich ĂŒberprĂŒfen kann.

Um dieses Szenario in Aktion zu testen, erstellen wir eine zweite Instanz von SA-Logic mit Bugs (buggy), indem wir den folgenden Befehl ausfĂŒhren:

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

Und nun fĂŒhren wir den Befehl aus, um sicherzustellen, dass alle Instanzen mit app=sa-logic verfĂŒgen auch ĂŒber Labels mit entsprechenden Versionen:

$ 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

Dienste sa-logic zielt auf Pods mit dem Label app=sa-logic, daher werden alle Anfragen gleichmĂ€ĂŸig auf alle Instanzen verteilt:

ZurĂŒck zu den Mikrodiensten mit Istio. Teil 2


 aber wir möchten, dass die Anfragen an die Instanzen mit der Version v1 gerichtet und auf die Instanzen mit der Version v2 gespiegelt werden:

ZurĂŒck zu den Mikrodiensten mit Istio. Teil 2

Dies erreichen wir durch VirtualService in Kombination mit DestinationRule, wobei die Regeln Teilmengen und Routen des VirtualService zu einer bestimmten Teilmenge definieren.

Definition der Teilmengen in Destination Rules

Teilmenge (subsets) werden durch die folgende Konfiguration definiert (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. Der Host (host) definiert, dass diese Regel nur auf den Fall angewendet wird, wenn der Pfad zum Dienst fĂŒhrt sa-logic;
  2. Die Namen (name) der Teilmengen werden beim Routing auf die Instanzen der Teilmenge verwendet;
  3. Label (Bezeichnung) definiert SchlĂŒssel-Wert-Paare, denen Instanzen entsprechen mĂŒssen, um Teil eines Teilsets zu werden.

Wenden Sie die Konfiguration mit dem folgenden Befehl an:

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

Jetzt, da die Teilmengen definiert sind, können wir fortfahren und den VirtualService konfigurieren, um Regeln auf Anfragen an sa-logic anzuwenden, damit diese:

  1. An das Teilset weitergeleitet werden v1,
  2. An das Teilset gespiegelt werden v2.

Das nĂ€chste Manifest ermöglicht das gewĂŒnschte Verhalten (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 sind keine ErklÀrungen erforderlich, also schauen wir uns die Action an:

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

Lassen Sie uns eine Last hinzufĂŒgen, indem wir folgenden Befehl ausfĂŒhren:

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

Lassen Sie uns die Ergebnisse in Grafana betrachten, wo wir sehen können, dass die fehlerhafte Version (buggy) fĂŒhrt bei etwa 60 % der Anfragen zu einem Ausfall, aber keiner dieser AusfĂ€lle betrifft Endbenutzer, da ihnen ein funktionierender Dienst antwortet.

ZurĂŒck zu den Mikrodiensten mit Istio. Teil 2
Erfolgsquote der Antworten verschiedener Versionen des Dienstes sa-logic

Hier haben wir zum ersten Mal gesehen, wie VirtualService in Bezug auf die Envoy-Instanzen unserer Dienste angewendet wird: als sa-web-app eine Anfrage an sa-logic, die durch den Sidecar-Envoy geleitet wird, der - ĂŒber VirtualService - so konfiguriert ist, dass er die Anfrage an das Teilset v1 weiterleitet und die Anfrage an das Teilset v2 des Dienstes spiegelt. sa-logic.

Ich weiß: Sie haben bereits gedacht, dass Virtual Services einfach sind. Im nĂ€chsten Abschnitt werden wir diese Ansicht erweitern, indem wir zeigen, dass sie wirklich großartig sind.

Canary Deployments

Canary Deployment ist der Prozess, bei dem eine neue Version einer Anwendung fĂŒr eine kleine Anzahl von Benutzern eingefĂŒhrt wird. Dies wird verwendet, um sicherzustellen, dass im Release keine Probleme auftreten und nur nachdem man sich von der ausreichenden QualitĂ€t des Releases ĂŒberzeugt hat, wird es auf einegrĂ¶ĂŸtengrĂ¶ĂŸere Zielgruppe ausgeweitet.

Zur Demonstration der Canary Deployments setzen wir die Arbeit mit dem Teilset fort. buggy u sa-logic.

Wir machen es uns nicht einfach und leiten gleich 20 % der Nutzer zur fehlerhaften Version (dies wird unser Canary-Deployment sein), wĂ€hrend die ĂŒbrigen 80 % zum stabilen Dienst geleitet werden. Dazu verwenden wir den folgenden 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 — das Gewicht (weight), das den Prozentsatz der Anfragen bestimmt, die an den EmpfĂ€nger oder ein Teilmengen des EmpfĂ€ngers gesendet werden.

Aktualisieren wir die vorherige Konfiguration des VirtualService mit sa-logic dem folgenden Befehl:

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


 und sehen sofort, dass ein Teil der Anfragen zu Fehlern fĂŒhrt:

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

VirtualServices aktivieren Canary-Deployments: In diesem Fall haben wir die potenziellen Auswirkungen von Problemen auf 20 % der Benutzerbasis eingegrenzt. Hervorragend! Jetzt können wir in jedem Fall, in dem wir uns bei unserem Code unsicher sind (anders ausgedrĂŒckt — was immer der Fall ist
), Spiegelungen und Canary-Deployments nutzen.

Timeouts und Wiederholungsversuche

Doch Bugs sind nicht immer im Code zu finden. Auf der Liste der "8 Fehlannahmen in verteilten Systemen" steht an erster Stelle die falsche Annahme, dass "das Netzwerk zuverlÀssig ist". In Wirklichkeit ist das Netzwerk nicht zuverlÀssig, und aus diesem Grund benötigen wir Timeouts (timeouts) und Wiederholungsversuche (retries).

FĂŒr die Demonstration verwenden wir weiterhin dasselbe Problem-Version sa-logic (buggy), wĂ€hrend wir unreliability im Netzwerk mit zufĂ€lligen AusfĂ€llen simulieren.

Lassen Sie unseren fehlerhaften Dienst eine 1/3 Chance fĂŒr eine zu lange Antwort, eine 1/3 Chance fĂŒr einen Abbruch mit Internal Server Error und eine 1/3 Chance fĂŒr die erfolgreiche Auslieferung der Seite haben.

Um die Auswirkungen solcher Probleme zu mildern und das Nutzererlebnis zu verbessern, können wir:

  1. einen Timeout hinzufĂŒgen, wenn der Dienst lĂ€nger als 8 Sekunden antwortet,
  2. einen Wiederholungsversuch unternehmen, wenn ein Fehler bei der Anfrage auftritt.

FĂŒr die Implementierung verwenden wir folgende Ressourcendefinition (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. Die Timeout fĂŒr die Anfrage ist auf 8 Sekunden festgelegt;
  2. Wiederholte Versuche bei Anfragen werden dreimal unternommen;
  3. Und jeder Versuch gilt als fehlgeschlagen, wenn die Antwortzeit 3 Sekunden ĂŒberschreitet.

So haben wir eine Optimierung erreicht, da der Benutzer nicht lÀnger als 8 Sekunden warten muss und wir im Falle von Fehlern drei weitere Versuche unternehmen, um eine Antwort zu erhalten, was die Chancen auf eine erfolgreiche Antwort erhöht.

Wenden Sie die aktualisierte Konfiguration mit folgendem Befehl an:

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

Und ĂŒberprĂŒfen Sie in Grafana, dass die Anzahl der erfolgreichen Antworten gestiegen ist:

ZurĂŒck zu den Mikrodiensten mit Istio. Teil 2
Verbesserungen in den Statistiken der erfolgreichen Antworten nach dem HinzufĂŒgen von Timeouts und Wiederholungen

Bevor wir zum nĂ€chsten Abschnitt ĂŒbergehen (genauer gesagt — bereits zum nĂ€chsten Teil des Artikels, da es in diesem Abschnitt keine praktischen Experimente mehr geben wird — Anmerkung der Übersetzung.), entfernen Sie sa-logic-buggy und VirtualService mit den folgenden Befehlen:

$ kubectl delete deployment sa-logic-buggy
deployment.extensions "sa-logic-buggy" gelöscht
$ kubectl delete virtualservice sa-logic
virtualservice.networking.istio.io "sa-logic" gelöscht

Die Muster Circuit Breaker und Bulkhead

Es handelt sich um zwei wichtige Muster in der Mikrodienstarchitektur, die es ermöglichen, eine selbststÀndige Wiederherstellung zu erreichen (self-healing) der Dienste.

Circuit Breaker („automatischer Aus-Schalter“) wird verwendet, um Anfragen zu stoppen, die an eine Dienstinstanz gesendet werden, die als ungesund angesehen wird, und sie wĂ€hrend der Wiederherstellung umzuleiten, wĂ€hrend die Anfragen der Kunden an gesunde Instanzen dieses Dienstes weitergeleitet werden (was die Erfolgsquote der Antworten erhöht). (Anmerkung der Übersetzung: Eine ausfĂŒhrlichere Beschreibung des Musters finden Sie beispielsweise unter hier.)

Bulkhead („Trennwand“) Isoliert AusfĂ€lle in den Diensten, um das gesamte System nicht zu beeintrĂ€chtigen. Zum Beispiel, wenn Dienst B ausgefallen ist und ein anderer Dienst (der Kunde des Dienstes B) eine Anfrage an diesen Dienst sendet, verbraucht er seinen Pool an Threads und kann keine weiteren Anfragen bedienen (selbst wenn diese nichts mit Dienst B zu tun haben). (Anmerkung der Übersetzung: Eine ausfĂŒhrlichere Beschreibung des Musters finden Sie beispielsweise unter hier.)

Ich werde auf die Details der Implementierung dieser Muster verzichten, da man sie leicht in offiziellen Dokumentationfindet und jetzt ist es wichtig, einen Blick auf Authentifizierung und Autorisierung zu werfen, die im nÀchsten Abschnitt des Artikels behandelt werden.

P.S. vom Übersetzer

Lesen Sie auch in unserem Blog:

Quelle: habr.com

Kaufen Sie zuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz, VPS VDS-Servern đŸ”„ Kaufen Sie zuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz, VPS VDS-Servern | ProHoster