Retour aux microservices avec Istio. 2e partie



Remarque perev. : La première partie de cette série a été consacrée à la présentation d'Istio et à sa démonstration en action. Nous allons maintenant parler d'aspects plus complexes de la configuration et de l'utilisation de ce maillage de service, et en particulier du routage finement réglé et de la gestion du trafic réseau.

Nous vous rappelons également que l'article utilise des configurations (manifestes pour Kubernetes et Istio) du référentiel istio-mastery .

Gestion du trafic


Avec Istio, de nouvelles fonctionnalités apparaissent dans le cluster pour fournir:

  • Routage dynamique des requêtes : déploiements canaries, tests A / B;
  • Équilibrage de charge : simple et cohérent, basé sur des hachages;
  • Récupération en cas de chute : temporisations, tentatives, disjoncteurs;
  • Saisie des défauts : retards, interruption des requêtes, etc.

Dans la suite de l'article, ces fonctionnalités seront présentées comme un exemple de l'application sélectionnée et de nouveaux concepts seront introduits en cours de route. Le premier de ces concepts sera DestinationRules (c'est-à-dire les règles concernant le destinataire du trafic / des demandes - environ Transl.) , Avec lesquelles nous activons les tests A / B.

Test A / B: DestinationRules en pratique


Le test A / B est utilisé dans les cas où il existe deux versions de l'application (généralement elles diffèrent visuellement) et nous ne sommes pas sûrs à 100% de celle qui améliorera l'interaction utilisateur. Par conséquent, nous lançons simultanément les deux versions et collectons des mesures.

Pour déployer la deuxième version du frontend nécessaire pour démontrer les 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 created 

Le manifeste de déploiement pour la "version verte" diffère à deux endroits:

  1. L'image est basée sur une autre balise - istio-green ,
  2. Les pods ont une version: green étiquette version: green .

Étant donné que les deux déploiements ont l'étiquette app: sa-frontend , les demandes acheminées par le service virtuel sa-external-services vers le service sa-frontend seront redirigées vers toutes ses instances et la charge sera distribuée à l' aide de l'algorithme round-robin , ce qui conduira à la situation suivante:


Fichiers demandés introuvables

Ces fichiers sont introuvables car ils sont appelés différemment dans les différentes versions de l'application. Assurons-nous de ceci:

 $ 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 l'équilibreur de charge aux pods qui ont une version différente, où, pour des raisons évidentes, ces fichiers n'existent pas. Par conséquent, pour que l'application fonctionne, nous devons mettre une restriction: " la même version de l'application qui a donné index.html doit également servir les requêtes suivantes ."

Nous atteindrons l'objectif avec un équilibrage de charge cohérent basé sur le hachage (Equilibrage de charge cohérent) . Dans ce cas, les demandes d'un client sont envoyées à la même instance d'arrière-plan , pour laquelle une propriété prédéfinie est utilisée - par exemple, un en-tête HTTP. Implémenté à l'aide de DestinationRules.

DestinationRules


Une fois que VirtualService a envoyé une demande au service souhaité, à l'aide de DestinationRules, nous pouvons déterminer les stratégies qui seront appliquées au trafic destiné aux instances de ce service:


Istio Resource Traffic Management

Remarque : L'effet 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 l'instance à laquelle envoyer la demande est prise par Envoy dans la passerelle d'entrée configurée dans CRD.

À l'aide des règles de destination, nous pouvons configurer l'équilibrage de charge de sorte que des hachages cohérents soient utilisés et que les réponses de la même instance de service soient garanties au même utilisateur. La configuration suivante permet cela ( destinationrule-sa-frontend.yaml ) pour y parvenir:

 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é en fonction du contenu de l'en-tête de la version HTTP.

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 created 

Exécutez maintenant la commande ci-dessous et assurez-vous d'obtenir les fichiers dont vous avez besoin lorsque vous spécifiez l'en-tête de version :

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

Remarque : Pour ajouter différentes valeurs dans le titre et tester les résultats directement dans le navigateur, vous pouvez utiliser cette extension pour Chrome (ou celle-ci pour Firefox - environ Transl.) .

En général, DestinationRules a plus d'options dans le domaine de l'équilibrage de charge - consultez la documentation officielle pour plus de détails.

Avant d'étudier VirtualService, nous supprimerons la «version verte» de l'application et la règle correspondante dans le sens 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” deleted $ kubectl delete -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml destinationrule.networking.istio.io “sa-frontend” deleted 

Mise en miroir: les services virtuels en pratique


L'observation ("blindage") ou la mise en miroir ("mirroring") est utilisée dans les cas où nous voulons tester une modification de la production sans affecter les utilisateurs finaux: pour cela, nous dupliquons ("miroir") les demandes pour la deuxième instance, où les modifications nécessaires sont apportées, et regardez les conséquences. Autrement dit, c'est lorsque votre (a) collègue sélectionne le problème le plus critique et fait une demande de retrait sous la forme d'un énorme tas de saleté que personne ne peut réellement lui faire une revue.

Pour tester ce scénario en action, créez une deuxième instance de SA-Logic avec des bugs ( buggy ) en exécutant la commande suivante:

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

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

 $ 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 

Le service sa-logic cible les pods avec l'étiquette app=sa-logic , donc toutes les demandes seront réparties entre toutes les instances:



... mais nous voulons que les demandes soient dirigées vers les instances avec la version v1 et mises en miroir vers les instances avec la version v2:



Nous y parviendrons grâce au VirtualService en combinaison avec le DestinationRule, où les règles détermineront les sous-ensembles et les routes du VirtualService vers un sous-ensemble particulier.

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


Les 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' host détermine que cette règle s'applique uniquement aux cas où la route va vers le service sa-logic ;
  2. Les noms des sous-ensembles sont utilisés lors du routage vers des instances du sous-ensemble;
  3. Une étiquette 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 created 

Maintenant que les sous-ensembles sont définis, vous pouvez continuer et configurer VirtualService pour appliquer les règles aux requêtes à sa-logic afin qu'elles:

  1. Routé vers un sous-ensemble de v1 ,
  2. Reflété sur un sous-ensemble de v2 .

Le manifeste suivant vous permet de réaliser votre plan ( 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 

Aucune explication n'est requise ici, alors jetez un œil à l'action:

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

Ajoutez la charge en appelant cette commande:

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

Regardons les résultats dans Grafana, où nous pouvons voir que la version buggy bloque pour environ 60% des demandes, mais aucun de ces plantages n'affecte les utilisateurs finaux car ils ont un service qui fonctionne.


Succès des réponses des différentes versions du service sa-logic

Ici, nous avons d'abord vu comment VirtualService est appliqué aux Envoyés de nos services: lorsque l'application sa-web-app fait une demande à sa-logic , elle passe par le sidecar Envoy, qui - via VirtualService - est configuré pour acheminer la demande vers le sous-ensemble v1 et miroir une requête à un sous-ensemble de v2 du sa-logic .

Je sais: vous avez déjà eu le temps de penser que les services virtuels sont simples. Dans la section suivante, nous élargissons cette vue par le fait qu'elles sont également vraiment magnifiques.

Rouleaux de canaris


Canary Deployment 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ème dans la version et seulement après cela, étant déjà confiant dans sa qualité (de sortie) suffisante, pour se propager à un public plus large.

Pour démontrer les déploiements des canaris, nous continuerons de travailler avec un sous-ensemble de buggy en sa-logic .

Ne perdons pas de temps dessus et envoyons immédiatement 20% des utilisateurs à la version avec des bugs (cela représentera notre déploiement canari), et les 80% restants au service normal. Pour ce faire, appliquez le VirtualService suivant ( sa-logic-subsets-canary-vsyaml ):

 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 est le poids, qui détermine le pourcentage de demandes qui seront envoyées au destinataire ou à un sous-ensemble du destinataire.

Mettez à jour la configuration précédente de VirtualService pour sa-logic commande suivante:

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

... et voyez immédiatement qu'une partie des demandes se bloque:

 $ 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 canaries: dans ce cas, nous avons réduit les conséquences potentielles des problèmes à 20% de la base d'utilisateurs. Super! Maintenant, dans chaque cas, lorsque nous ne sommes pas sûrs de notre code (en d'autres termes, toujours ...), nous pouvons utiliser la mise en miroir et les déploiements canaries.

Délais et tentatives


Mais les bogues ne sont pas toujours dans le code. Dans la liste des " 8 erreurs de calcul distribué " apparaît en premier lieu l'opinion erronée selon laquelle "le réseau est fiable". En réalité, le réseau n'est pas fiable, et pour cette raison, nous avons besoin de délais d'attente et de nouvelles tentatives .

Pour la démonstration, nous continuerons à utiliser la même version de sa-logic ( buggy ), et nous simulerons la non-fiabilité du réseau avec des pannes aléatoires.

Laissez notre service avec des bogues avoir 1/3 de chance pour une réponse trop longue, 1/3 pour une exécution avec une erreur de serveur interne et 1/3 pour un retour de page réussi.

Afin d'atténuer les conséquences de tels problèmes et d'améliorer la vie des utilisateurs, nous pouvons:

  1. ajouter un délai d'attente si le service répond pendant plus de 8 secondes,
  2. réessayez si la demande échoue.

Pour l'implémentation, 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 délai d'expiration de la demande est défini sur 8 secondes;
  2. Des tentatives de demande répétées sont effectuées 3 fois;
  3. Et chaque tentative est considérée comme infructueuse si le temps de réponse dépasse 3 secondes.

Nous avons donc atteint l'optimisation, car l'utilisateur n'a pas à attendre plus de 8 secondes et nous ferons trois nouvelles tentatives pour obtenir une réponse en cas d'échecs, augmentant ainsi les chances de réussite.

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 configured 

Et vérifiez dans les graphiques de Grafana que le nombre de réponses réussies est terminé:


Améliorations des statistiques des réponses réussies après l'ajout de délais d'attente et de nouvelles tentatives

Avant de passer à la section suivante (ou plutôt à la partie suivante de l'article, car il n'y aura plus d'expériences dans cette pratique - environ la traduction) , supprimez sa-logic-buggy et VirtualService en exécutant les commandes suivantes:

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

Modèles de disjoncteurs et de cloisons


Nous parlons de deux modèles importants dans l'architecture de microservices qui vous permettent de réaliser des services d' auto-guérison .

Le disjoncteur («disjoncteur») est utilisé pour empêcher les demandes de parvenir à une instance d'un service considéré comme malsain et le restaurer pendant que les demandes des clients sont redirigées vers des instances saines de ce service (ce qui augmente le pourcentage de réponses réussies). (Remarque: une description plus détaillée du modèle peut être trouvée, par exemple, ici .)

La cloison ("partition") isole les pannes de service de la défaite de l'ensemble du système. Par exemple, le service B est rompu et un autre service (le client du service B) fait une demande au service B, à la suite de quoi il utilisera son pool de threads et ne pourra pas répondre à d'autres demandes (même si elles ne sont pas liées au service B). (Remarque: une description plus détaillée du modèle peut être trouvée, par exemple, ici .)

Je vais omettre les détails sur la mise en œuvre de ces modèles, car ils sont faciles à trouver dans la documentation officielle , et je veux vraiment montrer l'authentification et l'autorisation, qui seront discutées dans la prochaine partie de l'article.

PS du traducteur


Lisez aussi dans notre blog:

Source: https://habr.com/ru/post/fr440378/


All Articles