By Pascal LIBENZI.
Istio est certainement le service Mesh le plus réputé. Sa maturité n’a cessé de croitre depuis sa création en 2018 par IBM et Google. Il a très vite été très apprécié et adopté par les utilisateurs pour bien des raisons, et a été « donné » à la CNCF environ un an après sa création.
Ensemble nous allons balayer les différentes fonctionnalités proposées par ce service Mesh, et comprendre ce que cela peut nous apporter rapidement ou sur le plus long terme.
L’installation peut se faire de plusieurs manières, en utilisant:
istioctl
, que nous conseillons non pas pour l’installation définitive, mais peut-être plus pour expérimenter dans un premier temps, si vous souhaitez faire un poc rapide par exemple.istioctl
)istioctl
.On note que la documentation fournit les étapes pour différents modes d’installation:
Notons que la documentation ne nous laisse pas seuls face à notre choix du type d’installation, et qu’on peut trouver sur la page dédiée en lien en bas de la page de documentation de l’installation pourquoi utiliser une méthode plutôt qu’une autre.
Prenons l’exemple classique lors de la mise en place d’un POC: on cherche à aller au plus vite pour démontrer que tout fonctionne comme on le souhaite, et être en capacité rapidement de montrer à notre public les fonctionnalités offertes. On choisit donc d’installer [istioctl] (https://istio.io/latest/docs/setup/install/istioctl/) et de l’utiliser pour réaliser notre setup de démonstration.
Pour le téléchargement du binaire nous sommes renvoyés sur la documentation getting-started qui elle aussi présente rapidement comment installer Istio à la suite du téléchargement du CLI.
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.18.2 TARGET_ARCH=x86_64 sh -
cd istio-1.18.2
export PATH=$PWD/bin:$PATH
On constate pendant l’installation le message suivant:
En lançant cette commande istioctl x precheck
, vous pouvez vérifier que les prérequis à l’installation d’Istio sont bien respectés (i.e. que vos noeuds kubernetes ont bien les packages nécessaires au fonctionnement d’Istio installés)
Puis comme nous voulons être prêts au plus vite et faire une démonstration, nous allons installer Istio avec le profil « démo », c’est à dire que toutes les fonctionnalités core (démon istio, ingress gateway, egress gateway) seront activées:
istioctl install --set profile=demo
Notons que la documentation explique comment fonctionnent les profils et comment nous pouvons personnaliser notre installation.
Nous constatons que le profil Ambient (qui est d’ores et déjà disponible) n’est pas présent dans le tableau car cette nouvelle architecture – sur laquelle nous revenons plus tard dans cette article en détails – est encore très jeune et en version alpha, susceptible de changer du tout au tout.
Revenons à notre installation, qu’est-ce qui a été installé ? en continuant de suivre la documentation on voit qu’Istio a créé des déploiements dans un namespace dédié: istio-system
Nous pouvons aussi vérifier la liste des composants configurés d’Istio en observant le YAML de l’opérateur Istio qui a été installé par istioctl
:
kubectl -n istio-system get IstioOperator installed-state -o yaml > installed-state.yaml
On constate qu’avec une installation de ce type, cela ne prend pas plus de 5 minutes pour installer Istio et ses composants (téléchargement du cli inclus).
Il va de soi que selon nos besoins, et surtout si nous ne sommes plus en phase de POC, il nous faudra à minima changer de profil, ou encore choisir une méthode d’installation plus appropriée à notre besoin, selon les personnalisations que nous voulons apporter à notre déploiement d’Istio.
La désinstallation se fait très simplement en utilisant le cli:
istioctl uninstall --purge
Afin de tester votre installation, et avant d’aller plus loin, il vous faut une application décomposée en microservices, pour que l’installation du service Mesh prenne tout son sens.
Istio fournit énormément d’exemples, la plupart basés sur une application type: [BookInfo] (https://istio.io/latest/docs/examples/bookinfo/)
Il s’agit d’une application très simple qui permet de connaitre les notes et les détails sur une liste de livres. L’application comporte 4 microservices tous écrits dans des langages différents.
Installons l’application qui nous servira de base pour parcourir les différentes possibilités d’Istio
kubectl create ns bookinfo
kubectl apply -n bookinfo -f https://raw.githubusercontent.com/istio/istio/release-1.18/samples/bookinfo/platform/kube/bookinfo.yaml
Nous voyons alors que, malgré le fait que nous soyons sur une installation classique (avec des conteneurs sidecar), nous n’avons pas ces conteneurs :
Nous savons bien entendu pourquoi, mais cela nous permet d’illustrer un exemple de l’utilisation d’istioctl
.
Imaginons que sur un cluster nous détections que le service Mesh ne gère pas un namespace, et que nous ne sachions pas pourquoi.
C’est le moment de vous présenter un outil de debug proposé par Istio au sein du CLI : istioctl analyze
.
Cette commande est définie par namespace, il faut donc l’exécuter avec le namespace que vous souhaitez débugguer:
En fait, nous n’avons pas précisé à Istio que ce namespace devait être géré dans le service Mesh.
Afin de lui faire prendre en compte notre namespace, nous pouvons le labelliser :
kubectl label namespace bookinfo istio-injection=enabled
Notons trois points :
--overwrite
à la commande pour écraser la valeur de l’annotationistioctl install --set MeshConfig.defaultNamespace=all
Nous supprimons nos pods pour qu’ils soient automatiquement recréés puisque ce sont des déploiements qui ont été déployés:
kubectl delete po -n bookinfo --all
Nous constatons à présent que nos sidecar containers sont bien démarrés:
La documentation, bien que très riche, présente de nombreux chapitres et sous-chapitres, ce qui permet de retrouver assez facilement l’information recherchée.
On trouve les grands chapitres suivants:
L’activation du mTLS est très simple, et la documentation vous fournit toutes les possibilités, en incluant la possibilité que vous ayiez besoin un temps d’être permissif, le temps de gérer une migration pour une application qui ne supporterait pas l’ajout d’un sidecar proxy par exemple.
Tout est basé sur le manifest suivant:
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
spec:
mtls:
mode: STRICT
Le mode peut être PERMISSIVE ou STRICT. Notons que PERMISSIVE est la valeur par défaut lors de l’installation Istio de manière générale, à moins que vous ne précisiez la velur STRICT. Il s’agit alors de permettre la communication même si la PeerAuthentication n’est pas respectée (i.e. un des pods n’a pas de proxy Istio)
Différentes applications de ce manifest sont possibles:
De quelle manière peut-on observer ce qui se passe au sein de notre cluster?
Istio se base pour cela principalement sur Kiali, qui vous permet de visuellement voir les intéractions entre les services dans votre cluster, et potentiellement ce qu’il vous manque.
Installation :
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.18/samples/addons/kiali.yaml
Notons qu’il faut aussi installer prometheus (sur lequel Kiali vient se sourcer):
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.18/samples/addons/prometheus.yaml
Pour rester dans la simplicité nous allons simplement faire un port-forward du service Kiali.
kubectl port-forward -n istio-system svc/kiali 20001:20001
Nous pouvons maintenant nous rendre sur http://localhost:20001
Sur l’overview, nous pouvons voir les namespaces présents sur le cluster, et dans le menu contextuel de ces namespaces, nous pouvons décider d’activer ou désactiver l’injection automatique des sidecar containers.
On peut aussi noter dans l’encadré le plus grand en haut, sur le namespace istio-system, plusieurs informations d’un coup d’oeil:
La configuration Istio, et spécialement les objets spécifiques Istio sont présentés ici; et si une mauvaise configuration est détectée, vous aurez ici l’information sous forme de warning ou d’erreur. Nous avons ici généré une gateway qui ne cible rien et c’est pour cela que nous avons l’icône du warning. Si nous cliquons sur cette icône, nous arrivons directement à la liste des warnings et erreurs sur ces objets, et nous pouvons aller voir le détail :
Nous pouvons aussi basculer sur les différentes pages de Kiali sur un namespace en particulier (raccourci équivalent à aller sur la page puis sélectionner le namespace ciblé en haut à gauche).
Si nous nous rendons dans la partie Applications, Graph, Workloads ou encore Services nous n’avons pour l’instant pas de données sur notre namespace bookinfo.
Ceci est tout à fait normal car nous n’avons pas généré de trafic dans l’application pour le moment. Afin d’en générer, nous allons utiliser un pod qui ira interroger product-page (qui est le frontend de l’application) :
kubectl create ns curling
kubectl run mycurlpod -ti -n curling --image=curlimages/curl -- sh
max=100
for i in `seq 2 $max`
do
curl productpage.bookinfo.svc.cluster.local:9080/productpage?u=normal && sleep 0.1
done
Nous avons généré du traffic, et donc en retournant sur Kiali nous voyons maintenant plus d’informations :
Nous avons ajouté quelques informations grâce à la personnalisation de l’affichage (dans le coin en haut à gauche: Display) :
Maintenant nous passons au Graph avec AppVersion et nous ajoutons la distribution du traffic à la vue, voyant ainsi comment le traffic est distribué entre nos différentes versions du microservice « revues ».
Vous pouvez aller bien plus loin et découvrir par vous-même toutes les fonctionnalités de Kiali. Sa simplicité d’utilisation et son ergonomie en font un outil naturellement facile à appréhender et à comprendre dans son ensemble.
Vous avez sûrement découvert en cliquant sur un service dans la vue graphique que Kiali vous restitue alors les codes d’erreur pour les appels HTTP, vous indiquant aussi le pourcentage de réussite et d’erreur des requêtes.
Kiali est définitevement l’un de vos meilleurs atouts si vous désirer installer Istio sur votre cluster Kubernetes.
L’ingress gateway proposée par Istio est responsable de la distribution du trafic vers les services appropriés, elle est basée sur le proxy Envoy. On peut coupler à cela l’utilisation des VirtualService afin de bénéficier de toute la puissance de l’outillage fourni par Istio.
L’ingress gateway permet notamment aux utilisateurs d’accéder aux services depuis l’extérieur, remplaçant de fait un ingress controller plus « classique ». Elle peut également être utilisée pour appliquer des politiques de sécurité au trafic entrant.
L’ingress gateway est mise en place sous forme de déploiement Kubernetes, ce qui la rend facile à déployer et à gérer.
Voici quelques-une de ses fonctionnalités :
L’ingress gateway peut donc être utilisée pour améliorer la sécurité, la performance et la fiabilité de nos microservices d’un point de vue des utilisateurs qui consomme nos services.
Différents composants d’Istio vous permettent de mettre en place des règles de sécurité réseau ou encore du routage de trafic.
Les principaux objets d’Istio pour ceci sont les suivants :
Istio fournit des fonctionnalités d’authentification variées :
Des règles d’autorisations (Authorization policy) peuvent être mises en place afin d’obliger l’utilisateur à être authentifié et autorisé afin d’accéder aux services.
On peut aussi définir via une extension un fournisseur externe d’autorisations. On couplera oauth2-proxy avec une instance Keycloak par exemple.
Nous pourrions imaginer, afin de sécuriser un service, la mise en place d’un microservice Keycloak par exemple afin de fournir le jeton JWT et que celui-ci soit obligatoire pour accéder à un service:
Ceci peut être très utile lorsqu’on souhaite migrer par exemple notre modèle d’authentification vers du JWT pour tous les accès aux services.
Dans un souci de concision de cet article, nous n’entrons pas dans le détail de l’implémentation des différents mode de déploiement.
Les mode de déploiment standards que l’on peut implémenter avec Istio sont les suivants :
Tout ceci dépendant évidemment de l’implémentation des objets de type VirtualService et de type Destination au sens Istio.
Istio est reconnu comme la référence dans les services Mesh. Initié par Google, IBM et Lyft, le projet dispose maintenant d’une communauté très importante, disponible sur Slack notamment pour répondre à toutes les questions que l’on peut avoir.
La preuve de la maturité d’Istio est tout d’abord le nombre d’entreprises qui l’ont adopté en production.
D’après le rapport de CNCF Service Mesh Landscape 2023, Istio est le service Mesh le plus utilisé, avec une part de marché de 57 %.
Istio est maintenant déjà en version 1.19.0, et toutes les versions disposent de fonctionnalités qui peuvent être promues dans les versions suivantes, en suivant le cycle: alpha, beta, stable. Chaque version à travers le temps a apporté son lot de fonctionnalités et des améliorations au niveau des différentes versions et distribution Kubernetes supportées.
Qui plus est, certain produits sont basés sur Istio (par exemple Gloo), ce qui est la preuve d’une stabilité et d’une confiance quant à l’avenir d’Istio.
Istio doit donc être considéré comme un service Mesh très mature et fiable. Il est très largement utilisé par les entreprises en production, et dispose d’une large communauté d’utilisateurs et de développeurs.
Istio propose un nouveau mode de déploiement sans avoir besoin de sidecar containers. Vous en avez peut-être déjà entendu parlé, il s’agit de la mouture Ambient d’Istio.
Pour comprendre pourquoi nous voudrions nous passer de sidecar dans certains cas, nous vous invitons à lire notre précédent article sur les services Mesh, plus précisément le paragraphe « Architecture no-sidecar ».
Comme évoqué plus tôt, Istio Ambient est encore en version alpha, et il faut donc s’attendre à des changements à venir dans un futur assez proche dans les détails de l’implémentation.
Le concept ne devrait cependant pas changer, en revanche pour l’instant les distributions Kubernetes supportées sont très limitées, et l’intégration avec un CNI classique, comme Calico par exemple, se fait avec beaucoup de difficultés, car n’est pas encore totalement documentée.
Lors de l’écriture de cet article nous avons rencontré plusieurs soucis (sur des distributions non supportées), et nous avons donc fini par nous résoudre à tester cette installation sur un cluster KinD sur une distribution Linux, en suivant la documentation fournie.
Cette installation nécessite plus de ressources que l’installation classique d’Istio, puisque le CNI Istio et les zTunnels sont déployés sur les différents noeuds lors de l’installation (toutefois ceci est largement compensé au runtime sur des clusters avec beaucoup de charge de travail, puisque nous n’avons plus de sidecar container).
Pour ne pas que cet article soit trop long, nous continuons ici dans un contexte de démonstration à utiliser istioctl, et nous ne décrivons pas toutes les étapes qui se trouvent dans la documentation, que vous pouvez aller voir par vous même.
istioctl uninstall --purge
istioctl install --set profile=ambient
Nous constatons de suite une différence au niveau des composants installés: ceci est normal, puisque l’architecture est différente, sans sidecar proxies, nous allons avoir besoin de composants capables de centraliser ce que les sidecar proxies faisaient auparavant :
Si nous regardons les pods créés dans le namespace système d’Istio nous retrouvons les composants de l’architecture Istio Ambient :
Ajoutons maintenant notre namespace bookinfo dans le scope de notre service Mesh « ambient » :
kubectl label namespace bookinfo istio.io/dataplane-mode=ambient
En utilisant la commande kubectl dashboard kiali
, on peut rapidement voir des changements dans Kiali :
Nous allons maintenant rapidement observer les différences entre une AuthorizationPolicy L4 et une L7.
Création d’une policy L4:
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: productpage-viewer
namespace: default
spec:
selector:
matchLabels:
app: productpage
action: ALLOW
rules:
- from:
- source:
principals:
- cluster.local/ns/default/sa/sleep
- cluster.local/$GATEWAY_SERVICE_ACCOUNT
EOF
Les trois commandes suivantes retourneront un résultat sans erreur :
kubectl exec deploy/sleep -- curl -s "http://$GATEWAY_HOST/productpage" | grep -o "<title>.*</title>"
kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>"
kubectl exec deploy/notsleep -- curl -s "http://$GATEWAY_HOST/productpage" | grep -o "<title>.*</title>"
Dans le cas de la dernière commande, nous passons par la gateway donc le service account appelant le service produit est celui de la gateway, et non pas celui du pod notsleep; alors que la commande suivante provoquera une erreur puisque nous essayons de joindre directement sans passer par la gateway le service.
kubectl exec deploy/notsleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>"
Le service account notsleep n’est pas autorisé dans notre AuthorizationPolicy. Il est donc normal qu’il soit rejeté. Le code de l’erreur produite : curl (56) est une erreur du côté serveur, au niveau de la couche transport, donc du type pare-feu bloquant le traffic entrant par exemple.
Logs côté istio-system:
On constate ici facilement que c’est le zTunnel qui a renvoyé une erreur
Créons maintenant une policy L7, il nous faut alors créer un waypoint et l’AuthorizationPolicy L7 qui va avec :
istioctl x waypoint apply --service-account bookinfo-productpage
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: productpage-viewer
namespace: default
spec:
selector:
matchLabels:
istio.io/gateway-name: bookinfo-productpage
action: ALLOW
rules:
- from:
- source:
principals:
- cluster.local/ns/default/sa/sleep
- cluster.local/$GATEWAY_SERVICE_ACCOUNT
to:
- operation:
methods: ["GET"]
EOF
Effectuons la requête suivante :
kubectl exec deploy/sleep -- curl -s "http://$GATEWAY_HOST/productpage" -X DELETE
Le résultat est une erreur RBAC, car la méthode DELETE n’est pas autorisée au niveau L7 grâce à notre policy.
Logs côté istio-system :
Pourquoi avons-nous si peu de logs du côté d’Istio? en réalité l’activation du waypoint a créé un pod, et c’est ce pod qui vient intercepter le traffic au niveau applicatif pour nous renvoyer les erreurs:
Ce qui est indiqué dans ce schéma issu de la documentation sur Ambient :
De par sa nature même, un service Mesh est toujours un point inquiétant quant à l’opérabilité de notre plateforme. Istio propose un grand nombre de fonctionnalités et la courbe d’apprentissage peut être quelque peu difficile à appréhender, parfois plus qu’avec d’autres services Mesh, qui proposent moins de fonctionnalités.
Cependant Istio propose notamment au travers de istioctl
un grand nombre de fonctionnalités de debug.
Lors de la mise en place d’Istio, n’hésitez pas :
istioctl
est l’outil approprié pour déverminer et visualiser les différentes configurations de votre cluster Mesh. Bien souvent lorsque quelque chose ne fonctionne pas, il s’agit d’une mauvaise configuration à corriger, et cet outil va donc nous permettre de gagner du temps, notamment en proposant différentes visualisation des configurations du service Mesh.
istioctl -- help
vous donnera une liste d’utilitaires, dont certains sont très utiles pour du debug.
Nous ne reprenons pas toute la liste ici, le helper est suffisamment clair pour vous guider sur à quoi sert chaque commande d’istioctl
Pour plus d’informations sur comment debugguer votre service Mesh en cas de besoin, vous pouvez vous référer à la documentation Istio sur les outils de diagnostic.
Bien entendu dans le cas où vous rencontrez des problèmes, la première chose à faire est d’observer et analyser les journaux Istio.
Pouvoir logguer en tail tout les pods sur un namespace de votre cluster peut aussi être intéressant à des fins de debug. Nous avons pour habitude de déverser les logs dans différents système de logging, cependant lorsqu’on debug un problème à un instant T, l’outil stern peut être bien utile.
Pour logguer tous nos pods istio-system afin de debugguer quelque chose, nous utiliserons la commande suivante afin de détecter les warnings et erreurs dans les logs :
stern -n istio-system .*
Vous pouvez aussi logguer plus finement lorsque vous utilisez la fonctionnalité d’analyse d’istioctl par exemple.
Nous l’avons vu, l’outillage Prometheus/Kiali est un de vos meilleurs atouts pour observer en temps réel ce qui se passe dans votre cluster.
Notons qu’il existe plétoire d’intégrations entre Istio et les principaux outils d’observabilité connus (Prometheus, Grafana, Kiali, Jaeger, Zipkin, …). Chacune de ces intégrations peut vous permettre d’aller plus loin dans la visualisation de votre service Mesh et de son état de santé, n’hésitez donc pas à chercher dans la documentation officielle l’intégration entre Istio et votre outil favori.
Cet aspect sera abordé dans un article spécifique dédié à l’implémentation d’un service Mesh multi-cluster, car les possibilités architecturales sont nombreuses. Sachez simplement que le support de l’implémentation multi-clusters est bien présent dans Istio et, une fois n’est pas coutûme, est très bien documenté.
Istio est le leader des services Mesh, et propose énormément de fonctionnalités pour nous aider à gérer différents aspects dans notre cluster Kubernetes. Nous n’avons pas abordé certains points ici (comme les injections d’erreurs ou encore les circuit breakers par exemple) dans un souci de concision, mais sachez qu’il y a encore énormément de sujets que vous pouvez explorer autour d’Istio.
Il faut noter que ce service Mesh a gagné énormément en maturité au fil du temps, et présente un outillage et une documentation très complets pour la mise en place, la maintenance et la gestion au travers du temps de votre configuration Mesh.
Il ne fait pas vraiment de doute que tout problème rencontré avec ce produit saura être résolu, et que nous trouverons toujours un support de qualité en nous appuyant sur la communauté autour d’Istio.
Si vous songez à la mise en place d’un service Mesh, que vous pensez qu’Istio est le bon candidat, et que vous désirez plus d’informations, n’hésite pas à contacter SoKube, nous nous ferons un plaisir de vous apporter des réponses concrètes par rapport à vos cas d’utilisation.