Mesh Arena : Istio par l’exemple

Magazine
Marque
GNU/Linux Magazine
Numéro
224
Mois de parution
mars 2019
Spécialité(s)


Résumé

Service Mesh, Envoy Proxy, Linkerd, Istio… Ces noms vous parlent ? Ils affolent le buzzomètre dans le monde du DevOps depuis plus d’un an. Et ce n’est certainement pas près de s’arrêter en 2019.


Body

C’est sur Istio que je souhaite m’attarder avec vous. En novembre dernier, Nicolas Muller, Software Engineer chez Treeptik, et moi-même présentions une démo d’Istio et Kiali au Devops D-Day dans le stade Vélodrome de Marseille. La réception par l’auditoire fut très positive, témoignant de la curiosité sinon de l’intérêt que suscite actuellement Istio et m’a encouragé à écrire cet article dans GNU/Linux Mag’. L’idée est de présenter Istio principalement par le biais de quelques exemples, portés par une démo que vous pouvez rejouer chez vous.

Le code présenté dans cet article a été testé sur Fedora 29, avec Kubernetes 1.10.0, Minikube 0.31.0 et Istio 1.0.5.

1. Mais avant tout, Istio, qu’est-ce donc ?

Istio est un logiciel open source développé principalement par Google, IBM et Lyft [1]. Dans la majorité des cas, on le verra tourner sur Kubernetes. Il se compose de plusieurs services et proxies, dont le but principal est de gérer, via un ensemble de règles et de définitions, les communications entre les services de l’application cliente. Typiquement, cela s’adresse aux architectures en microservices, mais pas uniquement : Istio peut notamment se révéler très utile pour une migration progressive d’un monolithe en plusieurs services.

Plus généralement, Istio fournit un Service Mesh : littéralement un maillage de services. Comme on peut le voir en figure 1, le concept repose sur l’utilisation d’un proxy associé à chaque service d’une application, qui sera capable d’appliquer les règles que l’on a définies sur chaque requête entrante ou sortante. Parmi toute la panoplie de règles disponibles, citons la possibilité de sécuriser les échanges (Mutual TLS), de définir des règles de routage (par exemple, pour mettre en place un Canary Deployment ou de l’A/B Testing), de définir des stratégies de résilience (Retries, Circuit Breaking), etc.

istio_mesh_arena_01

Fig. 1 : Avec Istio, ce sont des proxies Envoy qui captent tout le trafic entrant et sortant de nos services, et appliquent les règles que l’on aura définies ; le tout orchestré par un « control plane » qui propage les configurations, collecte les métriques, authentifie les services, etc. (source : https://istio.io/).

L’un des principes fondamentaux d’Istio est de ne nécessiter aucun changement dans votre code source : toutes les règles ne sont que configurations, ou plus exactement des Custom Resources de Kubernetes. Comme toute ressource de ce type, on les manipule sous forme d’objets JSON ou YAML que l’on peut créer, modifier ou supprimer à tout moment, sans provoquer de coupure de service. Istio définit de nombreux types de ressources : les Gateways sont une sorte de porte d’entrée au Service Mesh, les Service Entries permettent d’accéder à des services externes au mesh, et d’autres moins connues existent, mais nous nous focaliserons ici sur les deux probablement les plus importantes : les Virtual Services et les Destination Rules. Ce sont elles qui, combinées, permettent de définir les règles de routage entre les services du mesh.

2. Voir ou ne pas voir

Ces différents objets permettent donc d’interférer sur les communications entre les services. Mais Istio ne se limite pas à cela, il amène avec lui un élément crucial pour les microservices : une bonne observabilité.

Puisque chaque requête au sein du Service Mesh est interceptée par un proxy, pourquoi ne pas alimenter quelques métriques bien utiles sur la volumétrie, les temps de réponse, la taille des requêtes et des réponses ? Istio ne s’en prive pas. Et Envoy ajoute en prime des métriques sur la santé des services. Elles sont stockées dans Prometheus [2], le Timeseries Database (TSDB) très en vogue dans l’écosystème Kubernetes, entre autres.

Cependant, lorsqu’on parle de microservices, on comprend aisément que le monitoring peut représenter certains challenges. Les microservices peuvent être très nombreux, chaque service étant potentiellement mis à l’échelle en plusieurs instances, chacune produisant son lot de métriques. Ajoutons à cela le principe du Pets versus Cattle qui veut qu’un conteneur soit considéré comme une ressource jetable, potentiellement à courte durée de vie et que l’on redémarrera au moindre pépin… On comprend vite que le système de monitoring devra jongler avec une multiplicité de sources. Cela pourrait promettre quelques crises de nerfs à nos ops.

Heureusement, Prometheus va nous simplifier la vie. D’abord, parce que contrairement à d’autres comme Influx, Prometheus fonctionne en pull et non en push, c’est-à-dire que le système monitoré se contentera d’exposer des métriques sans avoir à se soucier de la présence ou non du TSDB, sans avoir à en connaître l’adresse ou les détails de connexion. Et c’est avec le Kubernetes service discovery de Prometheus que la magie opèrera, puisque via l’API de Kubernetes, Prometheus sera non seulement capable d’identifier et interroger l’ensemble des pods susceptibles d’exposer des métriques, mais aussi d’indexer celles-ci selon leur source. Cette indexation permettra ensuite d’effectuer des filtrages et des agrégations pour un ensemble de pods, un workload, un groupe arbitraire de workloads, un namespace… On parle là de la dimensionnalité d’une métrique. Ce principe vaut aussi bien pour les métriques d’Istio, que pour vos propres métriques applicatives qui pourront bénéficier des mêmes possibilités d’agrégation, si vous choisissez de les exposer au format Prometheus.

Istio propose par défaut quelques dashboards Grafana pour visualiser ces métriques. Mais aussi Kiali [3], logiciel développé chez Red Hat et auquel je contribue, qui tire entièrement partie des métriques d’Istio pour afficher un graphe animé du Service Mesh, des informations détaillées sur les objets le composant, sur leur santé, ainsi que d’autres dashboards de métriques. En outre, Kiali est aussi capable d’effectuer une validation des ressources Istio (par exemple : l’hôte déclaré dans un Virtual Service existe-t-il bel et bien ? La somme des poids attribués à des routes vaut-elle bien 100 ? etc.).

3. Ouvrez les terminaux

Passons aux choses sérieuses. Nous allons déployer quelques microservices et jouer avec Istio pour en explorer certaines possibilités.

Pour cela, il faut bien sûr avoir un cluster Kubernetes à disposition, ce qui peut se faire sans trop de difficulté sur une machine personnelle avec Minikube, pour peu que cette machine soit assez puissante. Oui, Istio et Kubernetes sont gourmands ; Istio recommande d’allouer au minimum 4 cœurs et 8 GB de mémoire, mais j’utilise sans difficulté un peu moins pour cette démo : 3 cœurs (Intel i5-6500) et 6 GB – il est certainement possible de diminuer encore les exigences. Plus d’informations sur l’installation de Minikube : https://kubernetes.io/docs/setup/minikube/.

3.1 Installer Istio et Kiali

Actuellement, la méthode la plus simple pour installer Istio est certainement via Helm [4], je vous propose donc cette option (pour les utilisateurs d’OpenShift, il existe une solution pré-packagée avec Istio et Kiali, nommée Maistra [5]).

Il faut commencer par télécharger une release d’Istio, par exemple la 1.0.5 (https://github.com/istio/istio/releases), dézipper l’archive et installer :

$ tar -zxvf istio-1.0.5-linux.tar.gz

$ cd istio-1.0.5/

$ helm template install/kubernetes/helm/istio --name istio --namespace istio-system --set kiali.enabled=true > $HOME/istio.yaml

$ kubectl apply -f install/kubernetes/helm/istio/templates/crds.yaml

$ kubectl create namespace istio-system

$ kubectl apply -f $HOME/istio.yaml

$ export PATH=$PATH:`pwd`/bin

Il faudra attendre un peu que l’ensemble des images Docker se télécharge et que les pods soient prêts. Pour vérifier la progression, exécutez :

$ kubectl get pods -n istio-system

 

Ou alors :

$ kubectl get pods -n istio-system --watch)

 

Lorsque tous les pods sont en statut Running ou Completed, nous pouvons poursuivre.

Pour accéder à Kiali, le plus simple est de faire un port-forwarding sur localhost (ouvrons un nouveau terminal pour cela) :

$ kubectl port-forward svc/kiali 20001:20001 -n istio-system

 

Kiali est alors accessible à l’adresse http://localhost:20001 (login : admin/admin).

3.2 Cloner demo-mesh-arena

Il s’agit du dépôt contenant les exemples qui vont suivre, hébergé sur GitHub. Il contient également le code source des microservices (en Java / Vert.x). Il n’est pas nécessaire de le compiler pour la démo, celle-ci se basant sur des images Docker publiquement accessibles (mais rien ne vous empêche de les reconstruire vous-même, les Dockerfiles sont également fournis). Seuls quelques fichiers YAML seront utilisés ici.

$ git clone https://github.com/jotak/demo-mesh-arena.git

$ cd demo-mesh-arena

Il s’agit d’une mini « simulation » de football aux règles très élastiques, non jouable, malheureusement, mais vous pourrez voir quelques « intelligences » artificielles (à l’intelligence toute relative, vous pourrez le constater) s’activer sur le terrain et marquer quelques buts. Au-delà de l’aspect ludique, cette démo présente plusieurs avantages pour montrer les possibilités d’Istio :

  • Elle est architecturée en microservices : l’interface graphique en est un, de même que le terrain, le ballon, le joueur visiteur et le joueur local (voir figure 2). Ces services peuvent être répliqués en plusieurs instances, particulièrement les joueurs (pour former une équipe) et le ballon… ce qui ne manquera pas de causer quelques soucis de routage qu’il nous faudra régler, vous l’avez deviné, avec Istio.
istio_mesh_arena_02

Fig. 2 : Diagramme des principales interactions entre les services : connaissance des dimensions du terrain, collisions balle-terrain, interactions des joueurs avec le ballon, et requêtes d’affichage auprès de l’interface graphique.

  • L’application est vivante, elle génère d’elle-même du trafic, ce qui nous permettra de constater à chaud et presque instantanément les effets de telle ou telle règle Istio injectée, sans devoir recourir à un générateur de trafic externe.

3.3 Lancer l’interface graphique

$ kubectl apply -f <(istioctl kube-inject -f ./services/ui/Deployment.yml)

$ kubectl create -f ./services/ui/Service.yml

Remarquons ici l’utilisation du binaire istioctl que nous avons exporté dans notre PATH précédemment. Avec la commande kube-inject, Istio va intégrer le proxy Envoy en tant que sidecar container (voir encadré) dans le déploiement de notre service, et donc dans chaque pod issu de ce déploiement. Il est à noter que notre fichier de déploiement ne présente en lui-même aucune spécificité propre à Istio. Il aurait pu être utilisé tel quel, via un kubectl apply -f ./services/ui/Deployment.yml, ce qui aurait été tout à fait valide. Mais il n’aurait alors pas reçu son injection de proxy, et serait donc exclu du Service Mesh.

Un pod peut contenir plusieurs conteneurs. Dans le jargon de Kubernetes, un sidecar container est un conteneur secondaire, souvent ne faisant pas partie de l’application au sens métier du terme, mais apportant une plus-value technique, comme ici un Proxy. Il fait partie intégrante du pod, garantissant une exécution sur le même nœud.

La seconde ligne concerne la création d’un Service Kubernetes associé au déploiement, tout ce qu’il y a de plus classique, afin d’exposer un port et une API.

Dans Kiali, cliquons sur le menu Graph et sélectionnons le namespace default. Nous voyons notre service ui, pour le moment isolé (figure 3).

istio_mesh_arena_03

Fig. 3 : Le graphe de Kiali encore quasiment vide.

Comme nous l’avons fait précédemment pour Kiali, ouvrons un port local relié à ce service :

$ kubectl port-forward svc/ui 8080:8080

Ceci nous permet d’ouvrir un navigateur à l’adresse http://localhost:8080 pour voir la page presque blanche de l’interface graphique.

3.4 Un stade, un ballon, des joueurs

Étoffons un peu le graphe :

$ kubectl apply -f <(istioctl kube-inject -f ./services/stadium/Deployment-Smaller.yml)

$ kubectl create -f ./services/stadium/Service.yml

$ kubectl apply -f <(istioctl kube-inject -f ./services/ball/Deployment.yml)

$ kubectl create -f ./services/ball/Service.yml

Dès que Kiali se rafraîchit, les deux nouveaux nœuds apparaissent dans le graphe. Et si l’on patiente encore quelques instants, le temps que Prometheus récupère les métriques, on pourra voir le trafic apparaître entre le Stade et l’UI, ainsi qu’entre le Ballon et l’UI, correspondant aux requêtes d’affichage (figure 4).

istio_mesh_arena_04

Fig. 4 : Le graphe incluant Stade et Ballon.

L’écran de jeu voit également apparaître ces éléments (figure 5).

istio_mesh_arena_05

Fig. 5 : Le stade est prêt !

Pour mieux visualiser les requêtes dans Kiali, nous pouvons activer l’animation du trafic depuis le menu Display.

Passons aux joueurs :

$ kubectl apply -f <(istioctl kube-inject -f ./services/ai/Deployment-2-locals.yml)

$ kubectl create -f ./services/ai/Service-locals.yml

$ kubectl apply -f <(istioctl kube-inject -f ./services/ai/Deployment-2-visitors.yml)

$ kubectl create -f ./services/ai/Service-visitors.yml

Nous déployons ici deux joueurs pour chaque équipe. Après quelques instants, vous devriez les voir surgir sur le terrain et s’emparer du ballon. Cliquer sur Start game positionnera le ballon au centre et mettra les compteurs à zéro.

Côté Kiali, les interactions se matérialisent entre les joueurs et le ballon. Chaque joueur cherche à connaître la position du ballon et, si possible, taper dedans – le ballon lui-même décidera s’il y parvient ou non. Si vous explorez les autres écrans de Kiali, vous pourrez voir l’inventaire des Services et Workloads Kubernetes, la santé de ces éléments, ou encore les métriques.

Le graphe, quant à lui, prend de l’ampleur. Plus on ajoute des services, plus il risque de devenir confus. Pour pallier à cela, nous pouvons double-cliquer sur un nœud pour restreindre la vue à ses relations directes, obtenant ainsi un sous-ensemble du graphe global. Faisons cela sur ai-visitors-basic (figure 6).

istio_mesh_arena_06

Fig. 6 : Vue partielle du graphe.

À ce stade nous n’avons tiré parti, indirectement, que d’une seule fonctionnalité d’Istio : la télémétrie, par le biais de Kiali. Mais tout est en place pour aller plus loin.

3.5 Deux ballons ? Arbitre, qu’est-ce qu’on fait ?

Introduisons un second ballon :

$ kubectl apply -f <(istioctl kube-inject -f ./services/ball/Deployment-v2.yml)

Nul besoin ici de créer un service, puisque nous avons déjà un service ball qui couvre notre nouveau pod via le label Kubernetes app:ball.

Pour pouvoir le distinguer sur le terrain, celui-ci sera rose.

Dans la réalité, il y a fort à parier que les joueurs sauront d’eux-mêmes vers quel ballon se tourner, même s’il y a parfois quelques ratés [6]. Malheureusement, nos IA n’ont pas toute l’intelligence d’un joueur de foot, et nous pouvons déjà anticiper ce qui va se passer.

istio_mesh_arena_07

Fig. 7 : Load-balancing classique, sans Istio.

Lorsqu’ils souhaiteront rejoindre un ballon, les joueurs interrogeront le service ball pour se déplacer. Comme deux pods sont susceptibles de recevoir la requête, elle sera load-balancée par Kubernetes, en round-robin : une fois l’un, une fois l’autre (figure 7).

Et de fait, sur le terrain, nous voyons que l’indécision gagne tous les joueurs : ils ne savent plus vers quel ballon se tourner (figure 8).

istio_mesh_arena_08

Fig. 8 : Les IA restent vaguement plantées entre les deux ballons.

Kiali matérialise également cela : dans le graphe, nous pouvons activer le label Requests percent of total (menu Edge Labels) pour afficher sur chaque liaison le pourcentage que représente son trafic par rapport au trafic total sortant du nœud source. On constate que le trafic se partage équitablement vers chacun des ballons (figure 9).

istio_mesh_arena_09

Fig. 9 : Répartition équitable, 24 % pour chacun des ballons.

3.6 Istio à la rescousse

Une première expérience peut se faire en appliquant une pondération pour chaque ballon. Pour que cela soit possible, nous devons être capables de discriminer les deux ballons. Si vous examinez les fichiers de déploiement que nous avons utilisés précédemment, vous verrez que chacun est labellisé différemment : nous avons un ballon version:v1 et un autre version:v2. Voilà notre discriminant – nous aurions pu en choisir un autre, mais les configurations par défaut d’Istio et de Kiali exploitent celui-ci en particulier pour la télémétrie. D’une manière générale, l’utilisation des labels app et version, sans être indispensable, est recommandée.

Nous pouvons dès lors utiliser une Destination Rule qui va déclarer ces labels comme subsets dans le fichier destrule.yml :

apiVersion: networking.istio.io/v1alpha3

kind: DestinationRule

metadata:

name: ball-dr

spec:

host: ball

subsets:

- name: ball-v1

labels:

version: v1

- name: ball-v2

labels:

version: v2

Puis un Virtual Service qui applique une pondération pour les requêtes à destination du service ball, de 75 % vers la version v1 et 25 % vers la v2, dans virtualservice-75-25.yml :

apiVersion: networking.istio.io/v1alpha3

kind: VirtualService

metadata:

name: ball-vs

spec:

hosts:

- ball

http:

- route:

- destination:

host: ball

subset: ball-v1

weight: 75

- destination:

host: ball

subset: ball-v2

weight: 25

Créons ces ressources :

$ istioctl create -f ./services/ball/destrule.yml

$ istioctl create -f ./services/ball/virtualservice-75-25.yml

Presque immédiatement, nous allons constater le changement de comportement des joueurs : ils parviennent à jouer essentiellement avec le premier ballon, quoiqu’encore un peu hésitants et reculant parfois vers le second.

Dans Kiali, comme le montre la figure 10, la répartition du trafic entre les ballons tend vers 1/4 – 3/4 (le changement est progressif, car Kiali base ses calculs sur la télémétrie agrégée de la minute passée, par défaut).

istio_mesh_arena_10

Fig. 10 : Trois fois plus de trafic vers v1 que vers v2.

La figure 11 montre l’impact du Virtual Service sur le traitement d’une requête.

istio_mesh_arena_11

Fig. 11 : Par l’utilisation d’un Virtual Service, Istio et Envoy se substituent au routeur de Kubernetes et son load-balancer : le sidecar client établit les routes sortantes et fait jouer son propre load-balancer, ici nommé « weighted least request » pour les routes pondérées.

3.7 Un match dans le match

Puisque nous avons deux ballons, pourquoi ne pas faire deux matchs ? Oui, sur le même terrain.

Faisons déjà entrer deux nouveaux joueurs, Messi et Mbappé :

$ kubectl apply -f <(istioctl kube-inject -f ./services/ai/Deployment-Messi.yml)

$ kubectl apply -f <(istioctl kube-inject -f ./services/ai/Deployment-Mbappe.yml)

Ceux-là ressemblent à peu près aux joueurs existants, si ce n’est qu’ils sont labellisés avec une version différente… et sont accessoirement bien meilleurs, ils ne vont d’ailleurs pas tarder à monopoliser le ballon.

Tout en conservant la Destination Rule existante, nous allons remplacer le précédent Virtual Service par celui-ci, contenu dans virtualservice-by-label.yml :

apiVersion: networking.istio.io/v1alpha3

kind: VirtualService

metadata:

name: ball-vs

spec:

hosts:

- ball

http:

- match:

- sourceLabels:

version: basic

route:

- destination:

host: ball

subset: ball-v1

- route:

- destination:

host: ball

subset: ball-v2

Ici, nous redirigeons chaque requête vers une version du ballon en fonction des labels de la source (des joueurs donc, mais également du terrain ou tout autre microservice qui interagirait avec le ballon).

$ istioctl replace -f ./services/ball/virtualservice-by-label.yml

Quasiment instantanément nous voyons le changement de comportement : Messi et Mbappé jouant l’un contre l’autre avec le ballon rose, et les autres joueurs avec le blanc.

3.8 Ballon crevé et Traffic Shadowing

Le Traffic Shadowing (ou mirroring) est un pattern très utile pour tester une nouvelle version d’un service en situation de production tout en évitant d’altérer celle-ci. Le principe est de dupliquer chaque requête à destination du service existant pour la rejouer vers la version à tester. Seule la réponse de la « vraie » requête sera perçue par le client. Bien entendu, cela suppose de ne pas brancher la version de test, en aval, sur des services tels que la base de données de prod [7].

Mais tout d’abord, faisons un peu de nettoyage…

$ kubectl delete -f ./services/ai/Deployment-Messi.yml

$ kubectl delete -f ./services/ai/Deployment-Mbappe.yml

$ istioctl delete -f ./services/ball/virtualservice-by-label.yml

Nous allons déployer un nouveau ballon « crevé », remplaçant notre ballon rose : celui-ci est programmé pour renvoyer un certain pourcentage d’erreurs sur les requêtes entrantes. Par ailleurs, des effets graphiques inclus dans la démo permettent de mieux visualiser les requêtes reçues par les ballons :

  • lorsqu’un ballon ne reçoit aucune requête, il s’assombrit ;
  • lorsqu’un ballon renvoie des erreurs, il rougit.

Nous créons aussi pour le moment un Virtual Service dont le rôle est d’envoyer tout le trafic des ballons vers la v1, afin de garder notre ballon crevé inactif.

$ istioctl create -f ./services/ball/virtualservice-all-to-v1.yml

$ kubectl apply -f <(istioctl kube-inject -f ./services/ball/Deployment-burst.yml)

Comme prévu, les joueurs ne jouent qu’avec la v1. L’autre ballon, ne recevant pas de requête, s’est assombri. Passons au shadowing. Istio permet d’activer ce mode de façon extrêmement simple sur un service (fichier virtualservice-mirrored.yml) :

apiVersion: networking.istio.io/v1alpha3

kind: VirtualService

metadata:

name: ball-vs

spec:

hosts:

- ball

http:

- route:

- destination:

host: ball

subset: ball-v1

mirror:

host: ball

subset: ball-v2

Puis :

$ istioctl replace -f ./services/ball/virtualservice-mirrored.yml

À ce moment, nous voyons que le second ballon sur le terrain vire du gris sombre au rouge (figure 12), ce qui signifie qu’il reçoit des requêtes et provoque des erreurs. Pour autant, les joueurs continuent de jouer exclusivement avec la v1 : preuve qu’ils ne reçoivent pas les réponses de la v2, grâce au shadowing. Il peut arriver parfois, si un joueur passe par hasard près du second ballon, qu’il tape vraiment dedans. C’est logique : il reçoit réellement les requêtes des joueurs même si ceux-ci n’en savent rien, et peut alors considérer qu’un joueur est parvenu à tirer.

istio_mesh_arena_12

Fig. 12 : Le ballon crevé est inactif, délaissé par les joueurs, mais reçoit tout de même des requêtes et renvoie des erreurs, preuve en est sa couleur rouge.

Côté Kiali, nous pouvons également voir les implications du shadowing, bien que ce soit un peu délicat. Lorsque nous avons affiché le sous-graphe du nœud ai-visitors-basic, nous nous sommes focalisés sur le point de vue de ce workload. De ce fait, nous ne voyons aucune requête en direction du ballon v2 : de la perspective du joueur, seule la v1 est contactée (figure 13).

istio_mesh_arena_13

Fig. 13 : Le ballon v1 capte l’ensemble du trafic.

En revanche, nous pouvons voir que la santé du ballon v2 n’est pas bonne (le contour orange signifiant « santé dégradée »). En passant le curseur sur l’icône de santé, le détail apparaît (figure 14) : le taux d’erreurs dépasse les 10 %. Cela correspond aux erreurs que le microservice génère intentionnellement. Mais surtout, cela signifie qu’il traite bel et bien des requêtes entrantes. Kiali nous informe donc correctement de la santé d’un déploiement en mode miroir, ce qui tombe bien puisque c’est exactement ce que l’on cherche à vérifier avec ce pattern.

istio_mesh_arena_14

Fig. 14 : L’infobulle de santé affiche plus de détails.

En complément de cela, nous pouvons double-cliquer sur le nœud v2 pour en adopter le point de vue. De là, les liaisons entrantes s’affichent en rouge, témoignant du trafic et des erreurs (figure 15).

istio_mesh_arena_15

Fig. 15 : Sous-graphe centré sur ball-v2.

La représentation du shadowing dans Kiali n’est peut-être pas des plus évidentes, mais avec un peu d’entraînement tout finit par prendre son sens.

3.9 Circuit breaking

Une dernière pour la route ? Istio / Envoy implémentent deux types de circuit-breaking, l’un basé sur une limite maximale de connexions ou requêtes concurrentes autorisées, l’autre basé sur le nombre d’erreurs HTTP consécutives émises. C’est ce dernier que nous abordons ici. Nommé outlier detection, il permet d’exclure temporairement un pod du pool de load-balancing d’Envoy lorsqu’il émet trop d’erreurs. Périodiquement, suivant un temps configurable, il sera remis dans le pool, lui donnant une nouvelle chance au cas où il se serait stabilisé. L’outlier detection se configure non pas dans un Virtual Service, mais dans la Destination Rule (destrule-outlier.yml) :

apiVersion: networking.istio.io/v1alpha3

kind: DestinationRule

metadata:

name: ball-dr

spec:

host: ball

subsets:

- name: ball-v1

labels:

version: v1

- name: ball-v2

labels:

version: v2

trafficPolicy:

outlierDetection:

consecutiveErrors: 1

baseEjectionTime: 10s

maxEjectionPercent: 50

Avant tout, supprimons le Virtual Service existant :

$ istioctl delete -f ./services/ball/virtualservice-mirrored.yml

En son absence, nous retrouvons la situation initiale où chaque joueur hésite entre les deux ballons.

Puis configurons le circuit-breaker :

$ istioctl replace -f ./services/ball/destrule-outlier.yml

Rapidement, le ballon v2 va s’assombrir : générant trop d’erreur, il a été évincé du pool de load-balancing et ne reçoit donc plus de requête (figure 16). Périodiquement, il redevient rouge : Envoy l’a replacé dans le pool… avant de le rééjecter presque aussitôt.

istio_mesh_arena_16

Fig. 16 : Le ballon gris est évincé du load-balancing.

Kiali montre également ces erreurs sur les requêtes parvenant au ballon v2. Lorsqu’on compare le volume de requête avec la v1, on constate qu’il est bien inférieur, comme attendu (figure 17).

istio_mesh_arena_17

Fig. 17 : Seulement 1 % des requêtes parviennent à la v2.

Conclusion

J’espère que cette introduction à Istio vous aura éclairé sur les possibilités offertes. Bien entendu, nous n’en avons gratté que la surface et de nombreux autres sujets demandent à être explorés : quid du mTLS, du tracing ? Istio couvre également ces domaines dont le tracing par le biais de Jaeger.

Et qu’en est-il des performances ? Les proxies Envoy ont beau être plébiscités dans le monde des conteneurs, le principe même de Service Mesh induit forcément un overhead sur la latence, la mémoire, la charge CPU – et ce proportionnellement au nombre de services dans le mesh. C’est un compromis demandé au regard des fonctionnalités offertes. Il est certain que le sujet est pris très au sérieux dans les équipes de Google, Lyft et IBM. Si cela vous intéresse, certains rapports et guides sont disponibles [8]. L’outil Fortio [9], en outre, a été spécifiquement conçu pour les tests en charge sur Istio.

Références

[1] Site officiel d’Istio : https://istio.io/ - GitHub : https://github.com/istio/istio

[2] Prometheus, Timeseries Database : https://prometheus.io/

[3] Site officiel de Kiali : https://kiali.io/

[4] Helm, Kubernetes package manager : https://helm.sh/ et S. BEURET, « Highway to Helm ! », GNU/Linux Magazine n°221, décembre 2018 : https://connect.ed-diamond.com/GNU-Linux-Magazine/GLMF-221/Highway-to-Helm

[5] Maistra : https://maistra.io/

[6] Le même scénario « in real life » : https://www.koreus.com/video/match-football-2-ballons.html

[7] Une lecture vivement recommandée pour plus d’informations sur le trafic shadowing : http://blog.christianposta.com/microservices/advanced-traffic-shadowing-patterns-for-microservices-with-istio-service-mesh/

[8] Rapport « Performances and Scalability » : https://istio.io/docs/concepts/performance-and-scalability/

[9] Fortio, tests de charge pour Istio : https://fortio.org/

 



Article rédigé par

Les derniers articles Premiums

Les derniers articles Premium

Sécurisez vos applications web : comment Symfony vous protège des menaces courantes

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Les frameworks tels que Symfony ont bouleversé le développement web en apportant une structure solide et des outils performants. Malgré ces qualités, nous pouvons découvrir d’innombrables vulnérabilités. Cet article met le doigt sur les failles de sécurité les plus fréquentes qui affectent même les environnements les plus robustes. De l’injection de requêtes à distance à l’exécution de scripts malveillants, découvrez comment ces failles peuvent mettre en péril vos applications et, surtout, comment vous en prémunir.

Bash des temps modernes

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Les scripts Shell, et Bash spécifiquement, demeurent un standard, de facto, de notre industrie. Ils forment un composant primordial de toute distribution Linux, mais c’est aussi un outil de prédilection pour implémenter de nombreuses tâches d’automatisation, en particulier dans le « Cloud », par eux-mêmes ou conjointement à des solutions telles que Ansible. Pour toutes ces raisons et bien d’autres encore, savoir les concevoir de manière robuste et idempotente est crucial.

Présentation de Kafka Connect

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Un cluster Apache Kafka est déjà, à lui seul, une puissante infrastructure pour faire de l’event streaming… Et si nous pouvions, d’un coup de baguette magique, lui permettre de consommer des informations issues de systèmes de données plus traditionnels, tels que les bases de données ? C’est là qu’intervient Kafka Connect, un autre composant de l’écosystème du projet.

Le combo gagnant de la virtualisation : QEMU et KVM

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

C’est un fait : la virtualisation est partout ! Que ce soit pour la flexibilité des systèmes ou bien leur sécurité, l’adoption de la virtualisation augmente dans toutes les organisations depuis des années. Dans cet article, nous allons nous focaliser sur deux technologies : QEMU et KVM. En combinant les deux, il est possible de créer des environnements de virtualisation très robustes.

Les listes de lecture

9 article(s) - ajoutée le 01/07/2020
Vous désirez apprendre le langage Python, mais ne savez pas trop par où commencer ? Cette liste de lecture vous permettra de faire vos premiers pas en découvrant l'écosystème de Python et en écrivant de petits scripts.
11 article(s) - ajoutée le 01/07/2020
La base de tout programme effectuant une tâche un tant soit peu complexe est un algorithme, une méthode permettant de manipuler des données pour obtenir un résultat attendu. Dans cette liste, vous pourrez découvrir quelques spécimens d'algorithmes.
10 article(s) - ajoutée le 01/07/2020
À quoi bon se targuer de posséder des pétaoctets de données si l'on est incapable d'analyser ces dernières ? Cette liste vous aidera à "faire parler" vos données.
Voir les 125 listes de lecture

Abonnez-vous maintenant

et profitez de tous les contenus en illimité

Je découvre les offres

Déjà abonné ? Connectez-vous