Retour aux microservices avec Istio. Partie 2

Retour aux microservices avec Istio. Partie 2

Note de traduction.: PremiÚre partie Ce cycle a été consacré à la découverte des capacités d'Istio et à leur démonstration en pratique. Maintenant, nous allons aborder des aspects plus complexes de la configuration et de l'utilisation de ce service mesh, notamment la routage finement configurable et la gestion du trafic réseau.

Nous rappelons également que l'article utilise des configurations (manifests pour Kubernetes et Istio) provenant du dépÎt istio-mastery.

Gestion du trafic

Avec Istio, de nouvelles possibilités apparaissent dans le cluster, permettant d'assurer :

  • Une routage dynamique des requĂȘtes: dĂ©ploiements canary, tests A/B ;
  • Un Ă©quilibrage de charge: simple et cohĂ©rent, basĂ© sur des hashes ;
  • Une reprise aprĂšs Ă©chec: timeouts, rĂ©essais, disjoncteurs ;
  • L'injection de fautes: latences, interruptions de requĂȘtes, etc.

Dans la suite de l'article, ces capacitĂ©s seront illustrĂ©es par l'exemple d'une application choisie et de nouveaux concepts seront prĂ©sentĂ©s en parallĂšle. Le premier de ces concepts sera DestinationRules (c'est-Ă -dire des rĂšgles concernant le destinataire du trafic/requĂȘtes — note du traducteur), Ă  l'aide desquelles nous activons les tests A/B.

Tests A/B :  DestinationRules en pratique

Les tests A/B sont appliqués lorsque deux versions d'une application existent (elles diffÚrent généralement visuellement) et que nous ne sommes pas totalement sûrs de celle qui améliorera l'interaction avec l'utilisateur. Nous lançons donc simultanément les deux versions et collectons des métriques.

Pour déployer la seconde version du frontend, nécessaire à la démonstration des tests A/B, exécutez la commande suivante :

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

Le manifest du déploiement pour la « version verte » diffÚre à deux endroits :

  1. L'image est basĂ©e sur un autre tag — istio-green,
  2. Les Pods ont un label version : green.

Comme les deux dĂ©ploiements ont le label app : sa-frontend, les requĂȘtes, routĂ©es par le service virtuel sa-external-services vers le service sa-frontend, seront redirigĂ©es vers tous ses instances et la charge sera rĂ©partie selon l'algorithme round-robin, ce qui aboutira Ă  la situation suivante :

Retour aux microservices avec Istio. Partie 2
Les fichiers demandés sont introuvables

Ces fichiers n'ont pas été trouvés car ils sont nommés différemment dans les différentes versions de l'application. Vérifions cela :

$ 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

Cela signifie que index.html, demandant une version des fichiers statiques, peut ĂȘtre envoyĂ© par le rĂ©partiteur de charge vers des pods ayant une autre version, oĂč, pour des raisons Ă©videntes, ces fichiers n'existent pas. Par consĂ©quent, pour que l'application fonctionne, nous devons mettre en place une restriction : «la mĂȘme version de l'application qui a renvoyĂ© index.html doit servir Ă©galement les requĂȘtes suivantes».

Nous atteindrons notre objectif grĂące Ă  une rĂ©partition de charge cohĂ©rente basĂ©e sur des hachages (RĂ©partition de charge par hachage cohĂ©rent). Dans ce cas les requĂȘtes d'un mĂȘme client sont envoyĂ©es au mĂȘme instance de backend, pour cela, une propriĂ©tĂ© prĂ©dĂ©finie est utilisĂ©e — par exemple, un en-tĂȘte HTTP. Cela s'implĂ©mente avec DestinationRules.

DestinationRules

AprĂšs que VirtualService a dirigĂ© la requĂȘte vers le service appropriĂ©, Ă  l'aide de DestinationRules nous pouvons dĂ©finir des politiques qui seront appliquĂ©es au trafic destinĂ© aux instances de ce service :

Retour aux microservices avec Istio. Partie 2
Gestion du trafic avec les ressources Istio

Remarque: L'impact des ressources Istio sur le trafic rĂ©seau est prĂ©sentĂ© ici de maniĂšre simplifiĂ©e. Pour ĂȘtre prĂ©cis, la dĂ©cision sur quelle instance envoyer la requĂȘte est prise par Envoy dans le Ingress Gateway, configurĂ© dans le CRD.

Avec les Destination Rules, nous pouvons configurer la rĂ©partition de charge pour utiliser des hachages cohĂ©rents et garantir que les rĂ©ponses de la mĂȘme instance de service vont Ă  un mĂȘme utilisateur. La configuration suivante permet d'atteindre cet objectif (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 — le hachage sera gĂ©nĂ©rĂ© sur la base du contenu de l'en-tĂȘte HTTP version.

Appliquez la configuration avec la commande suivante :

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

Maintenant, exĂ©cutez la commande ci-dessous et assurez-vous que vous obtenez les fichiers souhaitĂ©s lorsque vous spĂ©cifiez l'en-tĂȘte version:

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

Remarque: Pour ajouter diffĂ©rentes valeurs dans l'en-tĂȘte et tester les rĂ©sultats directement dans le navigateur, vous pouvez utiliser cette extension pour Chrome ou celle-ci pour Firefox — note du traducteur.).

En gĂ©nĂ©ral, les DestinationRules possĂšdent plus de fonctionnalitĂ©s en matiĂšre de rĂ©partition de charge — pour plus de dĂ©tails, veuillez vous renseigner dans la documentation officielle.

Avant de continuer à étudier VirtualService, supprimons la « version verte » de l'application et la rÚgle associée de redirection du trafic en exécutant les commandes suivantes :

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

Miroir : les Virtual Services en pratique

Shadowing (« masquage ») ou Mirroring (« miroir ») est utilisĂ© dans les cas oĂč nous voulons tester un changement en production sans toucher les utilisateurs finaux : pour cela, nous dupliquons (« miroir ») les requĂȘtes vers une seconde instance, oĂč les modifications nĂ©cessaires ont Ă©tĂ© apportĂ©es, et observons les consĂ©quences. En d'autres termes, c'est quand votre collĂšgue choisit le problĂšme le plus critique et fait une demande de tirage sous la forme d'un Ă©norme tas de boue, que personne ne peut rĂ©ellement rĂ©viser.

Pour vérifier ce scénario en action, créons une seconde instance de SA-Logic avec des bogues (buggy), en exécutant la commande suivante :

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

Et maintenant, exécutons la commande pour nous assurer que toutes les instances avec app=sa-logic ont également des étiquettes avec les versions correspondantes :

$ kubectl get pods -l app=sa-logic --show-labels
NOM                              PRÊT   ÉTIQUETTES
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 vise les pods avec l'Ă©tiquette app=sa-logic, donc toutes les requĂȘtes seront rĂ©parties entre toutes les instances :

Retour aux microservices avec Istio. Partie 2


 mais nous voulons que les requĂȘtes soient dirigĂ©es vers les instances avec la version v1 et soient reflĂ©tĂ©es sur les instances avec la version v2 :

Retour aux microservices avec Istio. Partie 2

Nous y parviendrons grĂące Ă  VirtualService en combinaison avec DestinationRule, oĂč les rĂšgles dĂ©termineront les sous-ensembles et les itinĂ©raires de VirtualService vers un sous-ensemble spĂ©cifique.

Définition des sous-ensembles dans les rÚgles de destination

Sous-ensembles (sous-ensembles) sont définis par la configuration suivante (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. L'hĂŽte (host) dĂ©finit que cette rĂšgle s'applique uniquement aux cas oĂč le chemin mĂšne au service sa-logic;
  2. Les noms (nom) des sous-ensembles sont utilisés lors de la navigation vers les instances du sous-ensemble ;
  3. L'étiquette (label) définit les paires clé-valeur auxquelles les instances doivent correspondre pour faire partie d'un sous-ensemble.

Appliquez la configuration avec la commande suivante :

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

Maintenant que les sous-ensembles sont définis, nous pouvons passer à la configuration de VirtualService pour appliquer des rÚgles aux demandes à sa-logic, afin qu'elles :

  1. soient routées vers le sous-ensemble v1,
  2. soient mises en miroir vers le sous-ensemble v2.

Le manifeste suivant permet d'atteindre l'objectif (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

Les explications ne sont pas nécessaires ici, alors regardons juste en action :

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

Ajoutons de la charge en appelant cette commande :

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

Regardons les rĂ©sultats dans Grafana, oĂč nous pouvons voir que la version avec des bogues (buggy) entraĂźne un Ă©chec pour ~60 % des demandes, mais aucun de ces Ă©checs n'affecte les utilisateurs finaux, car ils reçoivent des rĂ©ponses du service fonctionnel.

Retour aux microservices avec Istio. Partie 2
Taux de succÚs des réponses des différentes versions du service sa-logic

Ici, nous avons vu pour la premiĂšre fois comment VirtualService s'applique aux Envoys de nos services : lorsque sa-web-app fait une demande Ă  sa-logic, elle passe par le sidecar Envoy, qui — via VirtualService — est configurĂ© pour router la demande vers le sous-ensemble v1 et pour mettre en miroir la demande vers le sous-ensemble v2 du service sa-logic.

Je sais : vous avez déjà pensé que les Virtual Services sont simples. Dans la prochaine section, nous élargirons cet avis en montrant qu'ils sont en fait vraiment formidables.

Déploiements canari

Le déploiement Canary est le processus de déploiement d'une nouvelle version d'une application pour un petit nombre d'utilisateurs. Il est utilisé pour s'assurer qu'il n'y a pas de problÚmes dans la version, et seulement aprÚs cela, déjà sûr de la qualité suffisante de celle-ci (de la version), la diffuser à undeplus grand public.

Pour illustrer les déploiements canaris, nous continuerons à travailler avec le sous-ensemble buggy au sa-logic.

Nous n'allons pas y aller doucement et diriger immédiatement 20 % des utilisateurs vers la version avec des bogues (qui représentera notre déploiement canari), tandis que les 80 % restants iront vers le service normal. Pour cela, nous appliquerons le VirtualService suivant (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 — c'est le poids (poids), qui dĂ©termine le pourcentage de requĂȘtes qui seront dirigĂ©es vers le destinataire ou le sous-ensemble du destinataire.

Nous allons mettre à jour la configuration du VirtualService précédent avec sa-logic la commande suivante :

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


 et nous verrons immĂ©diatement que certaines requĂȘtes Ă©chouent :

$ 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

Les VirtualServices activent les déploiements canary : dans ce cas, nous avons réduit les conséquences potentielles des problÚmes à 20 % de la base d'utilisateurs. Parfait ! Maintenant, chaque fois que nous ne sommes pas sûrs de notre code (en d'autres termes - toujours
), nous pouvons utiliser le mirroring et les déploiements canary.

Timeouts et réessais

Mais les bogues ne se trouvent pas toujours dans le code. Dans la liste des «8 idĂ©es reçues en informatique distribuĂ©e», l'idĂ©e fausse selon laquelle « le rĂ©seau est fiable » figure en tĂȘte. En rĂ©alitĂ©, le rĂ©seau ne est fiable, et c'est pourquoi nous avons besoin de timeouts (timeouts) et de rĂ©essais (retries).

Pour la dĂ©monstration, nous allons continuer Ă  utiliser la mĂȘme version du problĂšme sa-logic (buggy), tandis que l'instabilitĂ© du rĂ©seau sera simulĂ©e par des pannes alĂ©atoires.

Supposons que notre service avec des bogues ait 1/3 de chances d'avoir une réponse trop longue, 1/3 de chances de se terminer par une erreur de serveur interne et 1/3 de chances de retourner une page avec succÚs.

Pour atténuer les conséquences de tels problÚmes et améliorer la vie des utilisateurs, nous pouvons :

  1. ajouter un timeout si le service met plus de 8 secondes à répondre,
  2. effectuer un rĂ©essai si une erreur se produit avec la requĂȘte.

Pour la mise en Ɠuvre, nous utiliserons la dĂ©finition de ressource suivante (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. Le timeout pour la requĂȘte est fixĂ© Ă  8 secondes ;
  2. Les rĂ©essais des requĂȘtes sont effectuĂ©s 3 fois ;
  3. Et chaque tentative est considérée comme un échec si le temps de réponse dépasse 3 secondes.

Ainsi, nous avons optimisé, car l'utilisateur n'aura pas à attendre plus de 8 secondes et nous effectuerons trois nouvelles tentatives pour obtenir une réponse en cas d'échec, augmentant ainsi les chances d'une réponse réussie.

Appliquez la configuration mise Ă  jour avec la commande suivante :

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

Et vérifiez dans les graphiques Grafana que le nombre de réponses réussies a dépassé :

Retour aux microservices avec Istio. Partie 2
Améliorations dans les statistiques de réponses réussies aprÚs l'ajout de délais et de nouvelles tentatives

Avant de passer à la section suivante (plutÎt à la prochaine partie de l'article, car il n'y aura plus d'expériences pratiques dans celui-ci - note du traducteur), supprimez sa-logic-buggy et VirtualService en exécutant les commandes suivantes :

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

Les patterns Circuit Breaker et Bulkhead

Il s'agit de deux patterns importants en architecture microservices qui permettent l'auto-récupération (self-healing) des services.

Circuit Breaker (« disjoncteur ») est utilisĂ© pour arrĂȘter les requĂȘtes envoyĂ©es Ă  une instance de service considĂ©rĂ©e comme non saine, et pour la rĂ©tablir pendant que les requĂȘtes des clients sont redirigĂ©es vers des instances saines de ce service (ce qui augmente le pourcentage de rĂ©ponses rĂ©ussies). (Note du traducteur : Une description plus dĂ©taillĂ©e du pattern peut ĂȘtre trouvĂ©e, par exemple, ici.)

Bulkhead (« cloison ») isole les pannes dans les services pour empĂȘcher l'ensemble du systĂšme d'ĂȘtre affectĂ©. Par exemple, si le service B est en panne, un autre service (client du service B) effectue une demande au service B, ce qui lui fait Ă©puiser son pool de threads et ne peut plus traiter d'autres demandes (mĂȘme si elles ne concernent pas le service B). (Note du traducteur : Une description plus dĂ©taillĂ©e du pattern peut ĂȘtre trouvĂ©e, par exemple, ici.)

Je vais passer les détails de l'implémentation de ces patterns, car il est facile de les trouver dans la documentation officielle, et j'ai également trÚs envie de montrer l'authentification et l'autorisation, qui seront abordées dans la prochaine partie de l'article.

P.S. de l'auteur

Lisez aussi dans notre blog :

Source : habr.com

Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS đŸ”„ Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster