Cet article fait suite à mon précédent billet, dans lequel je partageais mon point de vue sur Istio Ambient Mesh et le comparais au modèle traditionnel de Data Plane reposant sur les sidecars.
Je vais ici vous montrer comment installer et utiliser Istio Ambient Mesh sur un cluster Google Kubernetes Engine déployé sur Google Cloud Platform.
Remarque : Istio Ambient Mesh est encore en alpha et ne doit pas être utilisé en production tant qu'il n'est pas passé en disponibilité générale (GA).
Prérequis
- Le cluster doit exécuter une version prise en charge de Kubernetes (1.25, 1.26, 1.27, 1.28, 1.29).
- Le CNI (Container Network Interface) doit être activé sur le cluster. Les clusters GKE ont GKE CNI activé par défaut. Dataplane v2 n'est pas pris en charge pour le moment.
- Au minimum 3 nœuds et 4 vCPU par nœud. Chaque z-tunnel réserve 500 mCPU et 2 Gi de mémoire, sans compter les autres composants — mieux vaut donc disposer d'une marge confortable de vCPU et de mémoire.
- Prérequis de la plateforme
- Prérequis spécifiques à GKE
Remarque : cette installation ne fonctionnera pas sur les clusters GKE Autopilot, car Dataplane v2 n'y est pas optionnel, même s'il est possible d'activer les capabilities NET_ADMIN et NET_RAW .
Important : problèmes de compatibilité avec DataPlane v2
Istio Ambient Mesh nécessite l'installation du plugin Istio CNI, qui remplace les fonctionnalités du conteneur istio-init (lequel requiert les capabilities NET_ADMIN et NET_RAW) sans imposer aux utilisateurs effectuant le déploiement de disposer de permissions RBAC élevées pour provisionner ce type de conteneurs privilégiés.
La documentation Istio CNI contient l'avertissement suivant.
Remarque : le plugin Istio CNI fonctionne en tant que plugin CNI chaîné et il est conçu pour être utilisé avec un autre plugin CNI tel que PTP ou Calico. Voir compatibilité avec d'autres plugins CNI pour plus de détails.
C'est là que les choses se compliquent. Le Data Plane GKE historique (encore par défaut aujourd'hui) s'appuie sur GKE CNI (Calico CNI si Network Policy est activé) et utilise kube-proxy et iptables pour router le trafic au sein du cluster.
Le tout récent GKE Data Plane v2 (qui s'imposera comme le standard par défaut à l'avenir) est en revanche essentiellement une version managée de Cilium CNI, qui s'appuie sur un Data Plane eBPF remplaçant kube-proxy par des programmes eBPF modernes pour un networking optimisé.
Cet article de Solo.io explique comment configurer Cilium CNI pour ne pas casser Istio. Cela ne s'applique cependant qu'au modèle sidecar d'Istio et ne fonctionnera de toute façon pas avec Dataplane V2, qui est un composant managé par GCP dont la configuration est immuable.
DataPlane V2 utilise bien un dispositif veth, mais il se peut tout simplement que les programmes eBPF ne soient pas compatibles entre eux. Si vous en connaissez la raison, je serais ravi de la lire dans les commentaires.

Nous devons donc désactiver Dataplane v2 dans notre implémentation pour que le composant Istio CNI puisse être installé correctement.
J'espère que Dataplane v2 finira par être pris en charge, puisqu'il deviendra prochainement le mode Data Plane par défaut des clusters GKE.
Mise en place du cluster
Dans cet exemple, je crée un cluster GKE basique avec des nœuds privés et un endpoint master public.
Voici la commande que j'utilise pour déployer le cluster dans le réseau VPC par défaut. Vous pouvez ajuster les variables à votre convenance, en veillant simplement à désactiver Dataplane v2.
En environnement réel, il est judicieux d'utiliser des nœuds plus puissants hébergeant de nombreux pods afin d'en tirer le meilleur parti.
export PROJECT_ID=`gcloud config get-value project` && \
export M_TYPE=e2-standard-4 && \
export ZONE=us-central1-a && \
export CLUSTER_NAME=ambient-mesh-cluster && \
gcloud services enable container.googleapis.com && \
gcloud container clusters create $CLUSTER_NAME \
--project $PROJECT_ID \
--cluster-version "latest" \
--release-channel "regular" \
--location $ZONE \
--machine-type $M_TYPE \
--image-type "COS_CONTAINERD" \
--num-nodes "3" \
--enable-private-nodes \
--master-ipv4-cidr "172.16.0.0/28" \
--enable-ip-alias \
--no-enable-master-authorized-networks \
--network "projects/$PROJECT_ID/global/networks/default" \
--subnetwork "projects/$PROJECT_ID/regions/us-central1/subnetworks/default"
Une fois le cluster créé, GCP met automatiquement en place les règles de pare-feu nécessaires pour permettre au master du control plane de communiquer avec les nœuds.

On constate que les ports TCP 443 (HTTPS) et 10250 (Kubelet) sont autorisés ; cette règle n'ouvre toutefois pas le port 15017, requis par le webhook de validation de découverte de Pilot (composant du Control Plane Istio).
Si vous utilisez un cluster GKE privé (c'est mon cas ici), vous devez créer une règle de pare-feu autorisant le trafic en provenance du master sur le port 15017. Récupérez d'abord la plage IP source du master ainsi que les network tags de la règle de pare-feu :
gcloud compute firewall-rules list --filter="name~gke-${CLUSTER_NAME}-[0-9a-z]*-master" --format="table(targetTags, sourceRanges.list())"
À partir de la plage IP source et des network tags obtenus, créez ensuite une nouvelle règle de pare-feu autorisant le trafic depuis le master sur le port TCP 15017 :
gcloud compute firewall-rules create <firewall-rule-name> --network <VPC-name> --source-ranges=<CIDR_RANGE> --direction=INGRESS --target-tags=<TAG> --allow tcp:15017
Vérifiez également que Cloud NAT est configuré dans le VPC où le cluster est déployé, afin que les pods des nœuds GKE privés disposent d'un accès Internet.
Téléchargement et installation d'Istio en mode Ambient
Téléchargez la dernière version d'Istio :
curl -L https://istio.io/downloadIstio | sh -
Placez-vous dans le répertoire Istio et ajoutez le client istioctl à votre PATH :
cd istio-1.20.3/
export PATH=$PWD/bin:$PATH
Authentifiez-vous et connectez-vous à votre cluster GKE (assurez-vous de disposer des permissions IAM suffisantes pour vous y connecter et y effectuer des déploiements) :
gcloud container clusters get-credentials ${CLUSTER_NAME} --zone ${ZONE} --project ${PROJECT_ID}
Installez les CRD Kubernetes Gateway :
$ kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
{ kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd/experimental?ref=v1.0.0" | kubectl apply -f -; }
Installez Istio en mode ambient :
istioctl install --set profile=ambient --set "components.ingressGateways[0].enabled=true" --set "components.ingressGateways[0].name=istio-ingressgateway" --skip-confirmation
Vous devriez voir les 5 composants suivants installés correctement, en particulier le CNI et le z-tunnel.

Vérifiez que les composants sont installés et opérationnels en inspectant les pods et les DaemonSets dans le namespace istio-system.

kubectl get pod -n istio-system

kubectl get ds -n istio-system

kubectl get ds -n kube-system
Déployer des applications dans Istio Ambient Mesh
L'un des grands atouts d'Istio est qu'il ne nécessite aucune modification de vos applications. Nous allons ici déployer telle quelle l'application bookinfo, exemple classique d'Istio, puis l'ajouter au mesh une fois le déploiement effectué.
Le code de l'application bookinfo se trouve dans le répertoire d'installation d'Istio.
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
Déployez 2 applications supplémentaires (clients curl) qui nous serviront à simuler du trafic vers l'environnement mesh.
kubectl apply -f samples/sleep/sleep.yaml
kubectl apply -f samples/sleep/notsleep.yaml
Déployez un ingress gateway pour accéder à l'application Bookinfo depuis Internet.
kubectl apply -export GATEWAY_HOST=$(kubectl get service/istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}' -n istio-system)l
Récupérez les endpoints internes et externes du service istio-ingressgateway. Nous enverrons du trafic vers ces deux endpoints afin d'observer aussi bien le trafic interne au mesh que celui provenant de l'extérieur du cluster.
export GATEWAY_HOST_EXT=$(kubectl get service/istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}' -n istio-system)
export GATEWAY_HOST_INT=istio-ingressgateway.istio-system

vue depuis un navigateur
Le mesh à l'œuvre
Déployez une installation type de Prometheus et Kiali pour, respectivement, superviser et visualiser le trafic.
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/addons/prometheus.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/addons/kiali.yaml
Modifiez le fichier de service Kiali pour l'exposer sur Internet et pouvoir le consulter depuis votre navigateur.
kubectl patch svc kiali -n istio-system -p '{"spec": {"type": "LoadBalancer"}}'
Ouvrez-le dans le navigateur dès qu'une IP externe a été provisionnée pour le service Kiali. Les données sont pour l'instant limitées, car nos applications ne font pas encore partie du mesh.

Ajoutez les applications Bookinfo du namespace default à l'Ambient Mesh en posant un label sur le namespace.
kubectl label namespace default istio.io/dataplane-mode=ambient
Les applications font désormais partie du mesh de manière transparente, sans la moindre interruption. Envoyons un peu de trafic vers ces applications depuis nos clients curl pour voir le mesh à l'œuvre.
curl http://$GATEWAY_HOST_EXT/productpage
#Trafic de l'utilisateur vers l'endpoint externe du gateway
kubectl exec deploy/sleep -- curl -s "http://$GATEWAY_HOST_INT/productpage"
#Trafic d'un pod vers l'endpoint interne du gateway
kubectl exec deploy/sleep -- curl -s http://productpage:9080/
#Trafic d'un pod vers le service (en direct)
kubectl exec deploy/notsleep -- curl -s http://productpage:9080/
#Trafic d'un pod vers le service (en direct)
Consultez de nouveau le graphe Kiali. Il devrait désormais être alimenté en données et afficher les communications sécurisées par mTLS, ainsi que d'autres informations de télémétrie utiles.

Appliquer des politiques d'autorisation L7
La couche sécurisée (overlay) étant en place, vous pouvez aisément appliquer des politiques d'autorisation L4 comme vous le feriez avec Istio dans sa configuration par défaut.
Cet overlay sécurisé ne permet en revanche pas le filtrage L7. Pour cela, il faut déployer un waypoint proxy basé sur Envoy pour le service productpage.
Le proxy s'applique au compte de service ; pour le service productpage, ce compte de service est bookinfo-productpage.
Déployez un waypoint proxy pour le service productpage :
istioctl x waypoint apply --service-account bookinfo-productpage
Cela déploie un waypoint proxy pour tout service utilisant le compte de service bookinfo-productpage.


Tout trafic destiné au service productpage devra désormais transiter par le proxy L7, qui s'adapte automatiquement à la charge.
Créons une AuthorizationPolicy L7 pour autoriser explicitement les comptes de service sleep et gateway à effectuer des opérations GET sur le service productpage, et aucune autre opération.
export GATEWAY_SERVICE_ACCOUNT=ns/istio-system/sa/istio-ingressgateway-service-account
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: productpage-viewer
namespace: default
spec:
targetRef:
kind: Gateway
group: gateway.networking.k8s.io
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
Testez la politique en action :
# cette requête doit échouer avec une erreur RBAC car ce n'est pas une opération GET
kubectl exec deploy/sleep -- curl -s "http://$GATEWAY_HOST/productpage" -X DELETE
# La sortie attendue est 'RBAC: access denied'
# cette requête doit échouer avec une erreur RBAC car l'identité n'est pas autorisée
kubectl exec deploy/notsleep -- curl -s http://productpage:9080/
# La sortie attendue est 'RBAC: access denied'
# celle-ci doit continuer à fonctionner
kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>"
# La sortie attendue est '<title>Simple Bookstore App</title>'
Nettoyage
Exécutez les commandes suivantes pour désinstaller Istio et ses composants :
istioctl x waypoint delete --all
istioctl uninstall -y --purge
kubectl delete namespace istio-system
Supprimez le cluster GKE :
gcloud container clusters delete $CLUSTER_NAME --zone $ZONE
La modularisation des fonctionnalités L4 et L7 au service de la flexibilité et de l'efficacité est plutôt élégante.
J'ai particulièrement hâte d'en observer les bénéfices à grande échelle et j'aimerais beaucoup voir Ambient Mesh tourner dans un véritable environnement de production.
J'espère que cet article vous aura été utile et instructif. N'hésitez pas à partager vos réflexions et retours dans les commentaires.