Par défaut, le trafic entre Pods Kubernetes circule en clair. N’importe quel Pod dans le cluster peut intercepter les communications d’un autre Pod — il suffit d’un accès réseau. Le mTLS (mutual TLS) résout ce problème en chiffrant automatiquement tout le trafic inter-services et en vérifiant l’identité de chaque extrémité. Un service mesh comme Istio gère cette couche de sécurité de façon transparente : pas de modification du code applicatif, rotation automatique des certificats, et contrôle d’accès basé sur l’identité du service. Ce guide vous montre comment activer et vérifier le mTLS dans un cluster Kubernetes, avec les ressources PeerAuthentication et AuthorizationPolicy attendues à l’examen CKS.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Pourquoi le trafic en clair entre Pods est un risque de sécurité
- Comment le mTLS fonctionne (identité SPIFFE, certificats X.509, handshake)
- Configurer Istio pour imposer le mTLS en mode STRICT
- Vérifier que le chiffrement est actif entre deux services
- Contrôler les accès avec AuthorizationPolicy et les principals mTLS
- Choisir entre les approches sidecar et ambient (ztunnel)
Prérequis
Section intitulée « Prérequis »- Cluster Kubernetes avec accès administrateur
- Familiarité avec les Pods et les Network Policies
- Compréhension des concepts de service mesh (data plane, control plane)
- istioctl installé (ligne de commande Istio)
Pourquoi chiffrer le trafic entre Pods
Section intitulée « Pourquoi chiffrer le trafic entre Pods »Dans un cluster Kubernetes, le réseau est plat par défaut : chaque Pod peut communiquer avec tous les autres Pods sans restriction. Ce modèle simplifie le déploiement, mais crée un risque majeur : si un attaquant compromet un seul Pod, il peut intercepter (sniffing), modifier (man-in-the-middle) ou usurper le trafic des autres services.
Analogie : un réseau Kubernetes sans mTLS, c’est comme un open space où tout le monde parle à voix haute. N’importe qui peut écouter les conversations des autres. Le mTLS transforme chaque échange en conversation privée où les deux interlocuteurs vérifient leur identité avant de parler, et où tout le contenu est chiffré.
Les Network Policies résolvent une partie du problème en filtrant le trafic au niveau L3/L4 (IPs et ports), mais elles ne font ni chiffrement ni authentification. Le tableau ci-dessous clarifie la complémentarité :
| Mécanisme | Couche | Chiffrement | Authentification | Ce qu’il contrôle |
|---|---|---|---|---|
| NetworkPolicy | L3/L4 | Non | Non | Quels Pods peuvent se parler (IP/port) |
| mTLS | L4/L7 | Oui (TLS 1.2+) | Oui (certificats X.509) | Qui parle à qui (identité cryptographique) |
En combinant les deux, vous obtenez un modèle défense en profondeur : les NetworkPolicies limitent les flux autorisés, et le mTLS garantit que chaque flux est chiffré et que les deux extrémités sont bien qui elles prétendent être.
Comment fonctionne le mTLS
Section intitulée « Comment fonctionne le mTLS »Le TLS classique (celui de HTTPS) est unilatéral : seul le client vérifie l’identité du serveur. Le mutual TLS (mTLS) ajoute une étape : le serveur vérifie aussi l’identité du client. Les deux parties présentent un certificat X.509.
Le handshake mTLS, étape par étape
Section intitulée « Le handshake mTLS, étape par étape »-
Le client initie la connexion TLS : il envoie un “ClientHello” avec les suites de chiffrement qu’il supporte.
-
Le serveur présente son certificat : le client vérifie que le certificat est signé par une autorité de confiance (CA) et que l’identité correspond au service attendu.
-
Le serveur demande le certificat du client : c’est l’étape supplémentaire par rapport au TLS classique. Le client présente son propre certificat.
-
Le serveur vérifie le certificat du client : il confirme que le client est bien un service autorisé, signé par la même CA.
-
La session chiffrée est établie : les deux parties échangent une clé de session symétrique. Tout le trafic suivant est chiffré et authentifié.
Identité SPIFFE
Section intitulée « Identité SPIFFE »Dans un cluster Kubernetes, l’identité de chaque service est encodée dans le certificat sous la forme d’un SPIFFE ID (Secure Production Identity Framework For Everyone). Le format standard est :
spiffe://<trust-domain>/ns/<namespace>/sa/<service-account>Par exemple, un service utilisant le ServiceAccount api-server dans le namespace production aura l’identité :
spiffe://cluster.local/ns/production/sa/api-serverCette identité basée sur le ServiceAccount Kubernetes est au cœur du modèle de sécurité mTLS. Elle permet de définir des politiques d’accès granulaires : “seul le service frontend dans le namespace production peut appeler le service api-server”.
Gestion automatique des certificats
Section intitulée « Gestion automatique des certificats »Sans service mesh, vous devriez gérer manuellement les certificats pour chaque service : génération, distribution, rotation, révocation. Avec un service mesh comme Istio, tout est automatisé :
| Étape | Ce qui se passe |
|---|---|
| Génération | Le proxy (Envoy ou ztunnel) génère une clé privée et envoie une CSR (Certificate Signing Request) au control plane |
| Signature | Le control plane (istiod) signe la CSR après avoir vérifié l’identité du Pod via le ServiceAccount |
| Distribution | Le certificat signé est distribué au proxy via l’API SDS (Secret Discovery Service) |
| Rotation | Les certificats sont renouvelés automatiquement avant expiration (durée par défaut : 24h) |
Le code applicatif ne voit rien de tout cela : le proxy gère le mTLS de façon transparente.
Activer le mTLS avec Istio
Section intitulée « Activer le mTLS avec Istio »Istio est le service mesh le plus répandu et le plus fréquemment référencé dans le contexte CKS. Il propose deux modèles de déploiement : le mode sidecar classique et le mode ambient (sans sidecar). Dans les deux cas, le mTLS se configure avec les mêmes ressources Kubernetes.
Installer Istio
Section intitulée « Installer Istio »Pour un cluster de lab, l’installation minimale avec le profil demo :
# Télécharger istioctlcurl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.29.1 sh -cd istio-1.29.1export PATH=$PWD/bin:$PATH
# Installer avec le profil demo (inclut ingress + egress gateways)istioctl install --set profile=demo -yVérification :
kubectl get pods -n istio-systemRésultat attendu — istiod et les gateways doivent être Running :
NAME READY STATUS RESTARTS AGEistio-egressgateway-6bbb4c99b5-69jw8 1/1 Running 0 80sistio-ingressgateway-8574598487-pjhrq 1/1 Running 0 79sistiod-857888d8dd-6zt2t 1/1 Running 0 92sInjecter les proxies sidecar
Section intitulée « Injecter les proxies sidecar »En mode sidecar, Istio injecte un proxy Envoy dans chaque Pod. Pour activer l’injection automatique sur un namespace :
kubectl label namespace default istio-injection=enabledTout Pod créé dans ce namespace contiendra désormais deux conteneurs : votre application et le proxy Envoy.
PeerAuthentication : imposer le mTLS
Section intitulée « PeerAuthentication : imposer le mTLS »La ressource PeerAuthentication contrôle le mode mTLS pour un namespace ou un workload spécifique. C’est la ressource clé pour la CKS.
Trois modes sont disponibles :
| Mode | Comportement | Usage |
|---|---|---|
| PERMISSIVE | Accepte le trafic mTLS et en clair | Migration progressive (défaut Istio) |
| STRICT | Accepte uniquement le trafic mTLS | Production sécurisée |
| DISABLE | Désactive le mTLS | Déconseillé sauf cas très spécifique |
mTLS STRICT sur tout le mesh
Section intitulée « mTLS STRICT sur tout le mesh »Pour imposer le chiffrement sur tous les namespaces du cluster :
apiVersion: security.istio.io/v1kind: PeerAuthenticationmetadata: name: default namespace: istio-system # namespace racine = s'applique à tout le meshspec: mtls: mode: STRICTkubectl apply -f - <<EOFapiVersion: security.istio.io/v1kind: PeerAuthenticationmetadata: name: default namespace: istio-systemspec: mtls: mode: STRICTEOFmTLS STRICT sur un namespace
Section intitulée « mTLS STRICT sur un namespace »Pour appliquer le mode STRICT uniquement sur le namespace production :
apiVersion: security.istio.io/v1kind: PeerAuthenticationmetadata: name: default namespace: productionspec: mtls: mode: STRICTmTLS sur un workload spécifique
Section intitulée « mTLS sur un workload spécifique »Pour cibler un workload précis avec un selector :
apiVersion: security.istio.io/v1kind: PeerAuthenticationmetadata: name: api-strict namespace: productionspec: selector: matchLabels: app: api-server mtls: mode: STRICTAuthorizationPolicy : contrôle d’accès basé sur l’identité
Section intitulée « AuthorizationPolicy : contrôle d’accès basé sur l’identité »Le mTLS en mode STRICT garantit que tout le trafic est chiffré et authentifié. Mais il ne contrôle pas qui peut appeler quoi. C’est le rôle de l’AuthorizationPolicy.
Grâce au mTLS, Istio connaît l’identité SPIFFE de chaque requête. Vous pouvez exploiter cette information pour définir des règles d’accès granulaires.
Autoriser uniquement certains services
Section intitulée « Autoriser uniquement certains services »L’exemple suivant autorise uniquement le service frontend (via son ServiceAccount) à accéder au service api-server :
apiVersion: security.istio.io/v1kind: AuthorizationPolicymetadata: name: api-server-access namespace: productionspec: selector: matchLabels: app: api-server action: ALLOW rules: - from: - source: principals: - "cluster.local/ns/production/sa/frontend"Le champ principals utilise le SPIFFE ID du service source. Sans mTLS en mode STRICT, ce champ ne fonctionne pas (Istio ne peut pas extraire l’identité d’un flux en clair).
Politique deny-by-default
Section intitulée « Politique deny-by-default »Pour un namespace en mode “zero trust”, commencez par refuser tout le trafic, puis ouvrez explicitement les flux autorisés :
# Étape 1 : refuser tout par défautapiVersion: security.istio.io/v1kind: AuthorizationPolicymetadata: name: deny-all namespace: productionspec: action: ALLOW # Pas de rules → ne match jamais → tout est refuséUn service qui tente d’appeler api-server reçoit désormais une erreur HTTP 403 :
RBAC: access denied# Étape 2 : autoriser explicitement le flux frontend → api-serverapiVersion: security.istio.io/v1kind: AuthorizationPolicymetadata: name: allow-frontend-to-api namespace: productionspec: selector: matchLabels: app: api-server action: ALLOW rules: - from: - source: principals: - "cluster.local/ns/production/sa/frontend" to: - operation: methods: ["GET", "POST"] paths: ["/api/*"]Vérifier que le mTLS est actif
Section intitulée « Vérifier que le mTLS est actif »Après avoir configuré le mTLS, vous devez pouvoir vérifier qu’il fonctionne réellement. Istio fournit plusieurs méthodes de vérification.
Vérifier la configuration avec istioctl
Section intitulée « Vérifier la configuration avec istioctl »# Voir la politique mTLS effective pour un workloadistioctl x describe pod <pod-name> -n <namespace>Exemple de sortie :
Pod: api-server-5b7c5fd757-4jmtj Pod Revision: default Pod Ports: 80 (nginx)--------------------Service: api-server Port: 8080/auto-detect targets pod port 80--------------------Effective PeerAuthentication: Workload mTLS mode: STRICTApplied PeerAuthentication: default.productionLa sortie indique les politiques PeerAuthentication appliquées et le mode mTLS effectif sur le workload.
Vérifier le certificat d’un proxy
Section intitulée « Vérifier le certificat d’un proxy »# Inspecter le certificat utilisé par le proxy Envoy d'un Podistioctl proxy-config secret <pod-name> -n <namespace>La sortie affiche les certificats actifs, leur validité et leur numéro de série :
RESOURCE NAME TYPE STATUS VALID CERT SERIAL NUMBER NOT AFTER NOT BEFOREdefault Cert Chain ACTIVE true a082e25c3b111ace6e53f6b9891ab30d 2026-03-28T09:14:48Z 2026-03-27T09:12:48ZROOTCA CA ACTIVE true c253fd7d7a186f43c1e200c5c8513835 2036-03-24T09:12:25Z 2026-03-27T09:12:25ZLa ligne default (Cert Chain) est le certificat mTLS du workload avec le SPIFFE ID intégré. La ligne ROOTCA est l’autorité de certification racine d’Istio.
Tester le rejet du trafic en clair
Section intitulée « Tester le rejet du trafic en clair »Pour confirmer que le mode STRICT fonctionne, tentez d’envoyer du trafic en clair depuis un Pod sans proxy vers un service protégé :
# Depuis un namespace sans injection sidecarkubectl create namespace no-meshkubectl run test-clear --image=curlimages/curl:8.12.1 --rm -it --restart=Never -n no-mesh \ -- curl -s -o /dev/null -w "HTTP %{http_code}\n" --max-time 5 http://api-server.production.svc.cluster.local:8080Résultat attendu avec mTLS STRICT :
HTTP 000pod "test-clear" deletedpod no-mesh/test-clear terminated (Error)Le code HTTP 000 et l’exit code curl 56 (connection reset by peer) confirment que le proxy côté serveur rejette tout trafic non-mTLS. La connexion TCP s’établit mais le handshake TLS échoue.
Vérifier dans les métriques
Section intitulée « Vérifier dans les métriques »# Les métriques Istio indiquent le type de connexionistioctl dashboard prometheusLa métrique istio_tcp_connections_opened_total avec le label connection_security_policy="mutual_tls" confirme que les connexions sont chiffrées.
Migration progressive : PERMISSIVE vers STRICT
Section intitulée « Migration progressive : PERMISSIVE vers STRICT »Activer le mTLS STRICT d’un coup sur un cluster existant risque de casser les services qui n’ont pas encore de proxy. La migration recommandée se fait en trois étapes :
-
Vérifier l’injection des proxies : assurez-vous que tous les namespaces applicatifs ont l’injection sidecar activée et que tous les Pods ont redémarré avec leur proxy.
Fenêtre de terminal # Vérifier que tous les Pods ont 2/2 conteneurs (app + proxy)kubectl get pods -n production -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.containerStatuses[*].name}{"\n"}{end}' -
Activer le mode PERMISSIVE (défaut) : ce mode accepte le trafic mTLS et en clair. Les services avec proxy communiquent déjà en mTLS entre eux, et les services sans proxy continuent de fonctionner.
Fenêtre de terminal istioctl x describe pod <pod-name> -n productionVérifiez que les connexions entre Pods avec proxy utilisent bien mTLS.
-
Passer en mode STRICT : une fois que tous les Pods ont un proxy, basculez en STRICT. Surveillez les erreurs de connexion dans les logs.
Fenêtre de terminal kubectl apply -f - <<EOFapiVersion: security.istio.io/v1kind: PeerAuthenticationmetadata:name: defaultnamespace: productionspec:mtls:mode: STRICTEOF
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Solution |
|---|---|---|
connection reset by peer depuis un Pod sans proxy | Le service cible est en mTLS STRICT et rejette le trafic en clair | Injecter le sidecar Istio dans le Pod source, ou passer temporairement en PERMISSIVE |
upstream connect error or disconnect | Le proxy n’a pas encore reçu son certificat | Vérifier les logs d’istiod : kubectl logs -n istio-system deploy/istiod | grep -i error |
| AuthorizationPolicy refuse des requêtes légitimes | Le principal SPIFFE dans la règle ne correspond pas au ServiceAccount réel | Vérifier l’identité : istioctl proxy-config secret <pod> et comparer avec le champ principals |
Les métriques ne montrent pas mutual_tls | L’injection sidecar n’est pas active sur le namespace | Vérifier le label : kubectl get ns <ns> --show-labels | grep istio |
| Latence élevée après activation du mTLS | Le handshake TLS ajoute de la latence sur les premières requêtes | Normal pour les connexions courtes. Les connexions persistantes (keep-alive) amortissent le coût. Envisager le mode ambient (ztunnel) pour une empreinte plus légère |
À retenir
Section intitulée « À retenir »- Le trafic entre Pods est en clair par défaut dans Kubernetes — le mTLS est indispensable pour le chiffrer et authentifier.
- Le mTLS vérifie l’identité des deux extrémités via des certificats X.509, contrairement au TLS classique qui ne vérifie que le serveur.
- L’identité est basée sur le SPIFFE ID (
spiffe://cluster.local/ns/<namespace>/sa/<service-account>), liée au ServiceAccount Kubernetes. - PeerAuthentication contrôle le mode mTLS (PERMISSIVE, STRICT, DISABLE). Le mode STRICT est requis en production.
- AuthorizationPolicy avec des principals SPIFFE permet un contrôle d’accès granulaire basé sur l’identité cryptographique des services.
- Le mTLS et les NetworkPolicies sont complémentaires : l’un chiffre et authentifie, l’autre filtre les flux réseau.
- La rotation des certificats est automatique avec un service mesh — aucune intervention manuelle nécessaire.
- Pour la CKS, maîtrisez la chaîne : injection proxy → PeerAuthentication STRICT → AuthorizationPolicy → principals SPIFFE.