Un cluster Kubernetes tout juste installé laisse par défaut tous les pods se parler entre eux, sans aucune restriction. Un attaquant qui compromet un seul microservice via une dépendance vérolée peut donc, en théorie, atteindre n’importe quel autre pod du cluster, y compris la base de données ou les secrets applicatifs. C’est exactement ce que corrige la microsegmentation réseau : cloisonner chaque service pour qu’il ne parle qu’à ce dont il a réellement besoin.

En 2026, ce chantier n’est plus optionnel en Europe. La directive NIS2 et le règlement DORA poussent les DSI à documenter et prouver la segmentation de leurs environnements critiques, cloud compris. Ce tutoriel vous montre comment déployer une microsegmentation Zero Trust sur Kubernetes avec Cilium et Calico, les deux CNI (Container Network Interface) les plus utilisés pour ce cas d’usage, du premier kubectl apply jusqu’à l’intégration dans votre pipeline CI/CD. Comptez environ 60 minutes pour suivre l’ensemble des 11 étapes sur un cluster de test.

Ce guide s’adresse aux équipes SRE, plateforme et sécurité qui gèrent déjà un cluster Kubernetes en production ou en préproduction, avec des connaissances de base en YAML et en kubectl. Vous n’avez pas besoin d’être expert eBPF pour suivre les étapes : chaque commande est expliquée et chaque manifeste est commenté pour que vous puissiez l’adapter à votre propre topologie de services.

Pourquoi la microsegmentation Kubernetes devient incontournable en 2026

Un cluster Kubernetes sans Network Policy fonctionne en mode “tout ouvert” : chaque pod peut initier une connexion vers n’importe quel autre pod, quel que soit le namespace. Ce comportement, hérité des débuts de Kubernetes où la priorité allait à la simplicité de déploiement, pose un problème de sécurité de fond dès que le cluster héberge plusieurs équipes ou plusieurs niveaux de sensibilité de données.

La microsegmentation consiste à appliquer le principe du moindre privilège au réseau : chaque service ne peut communiquer qu’avec les services qu’il est censé appeler, dans les deux sens (entrant et sortant). C’est la traduction concrète du modèle Zero Trust au niveau réseau Kubernetes : on ne fait confiance à aucun flux par défaut, on autorise explicitement ce qui est légitime.

Cette approche limite fortement les mouvements latéraux en cas de compromission. Si un attaquant obtient un accès à un pod frontend via une faille applicative, une politique réseau bien construite l’empêche d’atteindre directement la base de données ou les services d’administration internes. C’est également un point de contrôle que les auditeurs recherchent de plus en plus, notamment dans le cadre de la mise en conformité NIS2 pour les entités essentielles et importantes en France et dans l’Union européenne.

Sur le plan technique, deux projets dominent ce terrain en 2026 : Cilium, porté par eBPF et adopté par Google, AWS et de nombreux fournisseurs de Kubernetes managé, et Calico, historiquement très implanté en entreprise pour ses politiques réseau avancées. Ce tutoriel couvre les deux, avec un focus pratique sur Cilium pour le fil conducteur des 11 étapes.

Le coût d’un mouvement latéral non maîtrisé se mesure aussi en temps de détection. Sans segmentation, un attaquant qui a pris pied sur un pod peu sensible peut scanner silencieusement le reste du cluster pendant des jours avant qu’une alerte ne se déclenche, faute de journal de connexions bloquées à examiner. Avec une politique default-deny couplée à l’observabilité Hubble, chaque tentative de connexion hors périmètre autorisé génère un événement DROPPED immédiatement visible, ce qui raccourcit mécaniquement le temps de détection d’une intrusion en cours.

Les Network Policies Kubernetes : les fondamentaux

Avant de manipuler Cilium ou Calico, il faut comprendre le modèle natif de Kubernetes. Une NetworkPolicy est une ressource qui cible un ensemble de pods via un podSelector, puis définit des règles ingress (trafic entrant) et egress (trafic sortant) autorisées vers ou depuis ce groupe de pods.

Le point le plus mal compris par les équipes qui débutent : le modèle est additif, jamais restrictif par défaut. Tant qu’aucune NetworkPolicy ne cible un pod, ce pod reste totalement ouvert. Dès qu’une politique le cible pour l’ingress, seul le trafic explicitement autorisé passe, tout le reste est rejeté. C’est ce comportement qui permet de construire un modèle “default deny” : on crée une politique qui cible tous les pods d’un namespace sans autoriser aucun flux, puis on ajoute des règles d’exception une par une.

Trois éléments structurent chaque politique :

  • podSelector : quels pods sont concernés par la règle (via des labels)
  • policyTypes : Ingress, Egress, ou les deux
  • from / to : les sources ou destinations autorisées, via podSelector, namespaceSelector ou ipBlock (plages CIDR)

Le CNI standard de Kubernetes ne suffit pas toujours : Flannel, par exemple, n’applique pas les NetworkPolicy du tout. C’est pour cela que le choix du CNI est la première décision technique à prendre avant de se lancer dans la microsegmentation.

Un autre piège de vocabulaire mérite d’être clarifié tout de suite : un namespaceSelector vide ({}) cible tous les namespaces du cluster, tandis qu’un podSelector vide au sein d’un bloc from ou to cible tous les pods du namespace concerné. Combiner les deux dans une seule règle revient donc à autoriser littéralement tout le trafic entrant, ce qui annule l’effet recherché. Relisez toujours vos manifestes en vous demandant “quel est le sous-ensemble réel de pods concerné” avant de les appliquer.

Cilium vs Calico : quel CNI choisir pour le Zero Trust

Cilium s’appuie sur eBPF pour appliquer les politiques réseau directement dans le noyau Linux, sans passer par iptables. Cette architecture réduit la latence et permet des fonctionnalités que le modèle NetworkPolicy standard n’offre pas : règles au niveau L7 (HTTP, gRPC, Kafka), chiffrement transparent des flux (WireGuard ou IPsec), et observabilité fine via Hubble, son module de visualisation des flux.

Calico, de son côté, reste une valeur sûre côté entreprise. Son CRD GlobalNetworkPolicy permet de définir des règles qui s’appliquent à l’ensemble du cluster sans devoir dupliquer une NetworkPolicy dans chaque namespace, un gain de temps réel en environnement multi-équipes. Calico propose aussi des logs de flux exploitables pour l’audit, un point apprécié des équipes conformité.

En pratique, les deux projets savent appliquer les NetworkPolicy Kubernetes natives. La différence se joue sur les besoins avancés : si vous visez du filtrage applicatif (L7) et du chiffrement de bout en bout, Cilium a l’avantage grâce à eBPF. Si votre priorité est la gestion centralisée de politiques à l’échelle d’un grand cluster multi-tenant avec des outils d’audit matures, Calico reste très compétitif.

Sachez aussi que Calico existe en deux déclinaisons : la version open source (Calico OSS), suffisante pour appliquer les GlobalNetworkPolicy présentées dans ce tutoriel, et une offre Calico Enterprise portée par Tigera, qui ajoute un tableau de bord graphique, des recommandations de politiques générées automatiquement et un moteur de conformité prêt à l’emploi. Pour un premier déploiement de microsegmentation, la version OSS couvre déjà largement les besoins décrits ici. Migrer vers l’offre payante ne devient pertinent que lorsque le nombre de politiques à gérer dépasse ce qu’une équipe peut maintenir à la main en YAML brut.

CritèreCiliumCalico
Moteur réseaueBPF (noyau Linux)iptables / eBPF (mode optionnel)
NetworkPolicy native K8sOuiOui
Filtrage L7 (HTTP, gRPC, Kafka)Oui (CiliumNetworkPolicy)Limité
Politiques cluster-wideCiliumClusterwideNetworkPolicyGlobalNetworkPolicy
Observabilité intégréeHubble (flux en temps réel)Calico Flow Logs
Chiffrement inter-podsWireGuard / IPsec natifWireGuard (add-on)
Version stable (août 2026)1.20.1Dernière branche stable Tigera Calico

La documentation officielle de Cilium 1.20.1 détaille l’ensemble des mécanismes d’import de politiques, en CLI comme via l’API Kubernetes. Une branche de développement, 1.21.0-dev, introduit un support préliminaire pour k8sClusterNetworkPolicy, activable via le flag --enable-k8s-cluster-network-policy=true. Cette branche n’est pas destinée à la production : gardez Cilium 1.20.x pour un déploiement stable.

Prérequis : outils et versions pour ce tutoriel

Ce tutoriel part du principe que vous disposez déjà d’un cluster Kubernetes fonctionnel, en local ou dans le cloud. Si ce n’est pas le cas, notre guide Minikube en 12 étapes vous permet de monter un cluster de test en une demi-heure. Vérifiez les versions suivantes avant de démarrer :

OutilVersion utilisée dans ce guideRôle
Kubernetes1.30 ou supérieurCluster cible (local ou managé)
Cilium1.20.1 (stable)CNI et moteur de politiques eBPF
Helm3.xInstallation de Cilium
cilium-cliDernière versionDiagnostic et statut du CNI
Hubble CLIDernière versionObservation des flux réseau
kubectlCompatible avec votre version de clusterApplication des manifestes
calicoctlDernière version (si vous testez Calico)Gestion des GlobalNetworkPolicy

Un accès administrateur au cluster est nécessaire pour installer un CNI. Sur un cluster managé (EKS, AKS, GKE), vérifiez au préalable que le CNI par défaut peut être remplacé par Cilium sans perturber les nœuds existants : chaque fournisseur documente sa procédure de migration. Sur un cluster de test local, partez d’une base propre pour éviter les conflits entre deux CNI actifs.

Prévoyez également la capacité machine nécessaire à l’agent Cilium lui-même : comptez environ 100 à 200 Mo de RAM et un cœur CPU partagé par nœud pour le DaemonSet Cilium en fonctionnement standard, un peu plus si vous activez le chiffrement WireGuard ou le filtrage L7 sur un volume de trafic important. Sur un cluster de test à trois nœuds, ces besoins restent négligeables face aux ressources déjà allouées à vos workloads applicatifs.

Étapes 1 à 3 : préparer le cluster et observer les flux

Étape 1 : Installer Cilium avec Helm

Ajoutez le dépôt Helm officiel puis déployez Cilium 1.20.1 sur votre cluster :

helm repo add cilium https://helm.cilium.io/
helm repo update

helm install cilium cilium/cilium \
  --version 1.20.1 \
  --namespace kube-system \
  --set kubeProxyReplacement=true \
  --set hubble.enabled=true \
  --set hubble.relay.enabled=true \
  --set hubble.ui.enabled=true

Une fois le déploiement lancé, vérifiez l’état des pods Cilium avec le CLI dédié :

cilium status --wait

Sortie attendue une fois l’installation terminée :

    /¯¯\
 /¯¯\__/¯¯\    Cilium:         OK
 \__/¯¯\__/    Operator:       OK
 /¯¯\__/¯¯\    Envoy DaemonSet: OK
 \__/¯¯\__/    Hubble Relay:   OK
    \__/       ClusterMesh:    disabled

Deployment        cilium-operator    Desired: 2, Ready: 2/2
DaemonSet          cilium             Desired: 3, Ready: 3/3
Containers:        cilium             Running: 3
                    cilium-operator    Running: 2
Cluster Pods:      12/12 managed by Cilium

Si les pods restent en CrashLoopBackOff, direction la section dépannage plus bas : c’est le symptôme le plus courant à ce stade, généralement lié à la version du noyau Linux.

Étape 2 : Activer Hubble pour l’observabilité

Hubble a déjà été activé dans la commande Helm ci-dessus. Exposez son interface pour visualiser les flux réseau en temps réel :

cilium hubble port-forward &
hubble status
hubble observe --namespace production --follow

Cette commande affiche en continu chaque connexion établie entre vos pods : source, destination, port, verdict (FORWARDED ou DROPPED). C’est l’outil qui va vous servir à l’étape suivante pour cartographier les dépendances réelles de vos services, plutôt que de deviner leurs communications à partir de la documentation applicative, souvent incomplète ou obsolète.

Étape 3 : Cartographier les flux existants avant de sévir

C’est l’étape la plus souvent sautée, et celle qui cause le plus d’incidents en production. Avant d’appliquer la moindre restriction, laissez Hubble collecter les flux pendant 7 à 14 jours sur un environnement représentatif du trafic réel (pics de charge, jobs batch nocturnes, synchronisations périodiques inclus). Exportez les résultats pour construire un graphe de dépendances :

hubble observe --namespace production \
  --since 168h \
  --output json > flux-production.json

Ce fichier devient votre référence pour écrire les règles d’autorisation aux étapes suivantes. Sans cette cartographie, le risque de casser un flux légitime (un job de sauvegarde mensuel, par exemple) est élevé, et il ne se révèle souvent qu’au pire moment.

Un script simple permet de transformer ce JSON en une liste de paires source/destination uniques, plus facile à relire qu’un flux brut de milliers de lignes :

cat flux-production.json | jq -r '[.source.pod_name, .destination.pod_name, .destination_port] | @tsv' \
  | sort -u > dependances-uniques.tsv

Le fichier dependances-uniques.tsv obtenu sert directement de base de travail pour rédiger vos NetworkPolicy aux étapes 7 et suivantes : chaque ligne devient potentiellement une règle d’autorisation explicite.

Étapes 4 à 6 : construire la politique default-deny

Étape 4 : Appliquer un default-deny par namespace

La base de toute microsegmentation Zero Trust : une politique qui cible tous les pods d’un namespace sans autoriser aucun flux entrant ni sortant.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress

Notez le podSelector: {} vide : il cible tous les pods du namespace, contrairement à l’absence totale de podSelector qui n’aurait ici aucun sens dans une NetworkPolicy. Appliquez d’abord cette règle sur un namespace de staging, jamais directement en production.

kubectl apply -f default-deny-all.yaml -n staging
kubectl get networkpolicy -n staging

Étape 5 : Autoriser le DNS pour tous les pods

Dès que le default-deny est actif, la résolution DNS cesse de fonctionner pour tous les pods du namespace : c’est l’incident numéro un rencontré par les équipes qui découvrent la microsegmentation. Ajoutez immédiatement une règle d’autorisation vers CoreDNS.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53

Étape 6 : Autoriser les communications avec kube-system

Au-delà du DNS, vos pods ont besoin d’atteindre d’autres services système : metrics-server pour l’autoscaling, les webhooks d’admission, parfois l’API server directement. Listez ces dépendances à partir de votre cartographie Hubble de l’étape 3, puis ajoutez une règle ciblée plutôt qu’une autorisation large vers tout kube-system.

Le label kubernetes.io/metadata.name utilisé dans les manifestes ci-dessus est ajouté automatiquement par Kubernetes depuis la version 1.21 sur chaque namespace, avec pour valeur le nom du namespace lui-même. C’est le moyen le plus fiable de cibler un namespace précis dans un namespaceSelector, plutôt que de dépendre d’un label personnalisé que quelqu’un pourrait supprimer par erreur lors d’un futur nettoyage.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-kube-system-metrics
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
          podSelector:
            matchLabels:
              k8s-app: metrics-server
      ports:
        - protocol: TCP
          port: 443

Étapes 7 à 9 : sécuriser les communications internes et sortantes

Étape 7 : Définir les règles entre microservices

Vient ensuite le cœur du travail : autoriser précisément chaque appel légitime entre vos propres services. Prenons un exemple classique à trois niveaux, frontend, API, base de données. Seule l’API doit pouvoir joindre la base de données, jamais le frontend directement.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-to-database
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: database
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: api-backend
      ports:
        - protocol: TCP
          port: 5432

Répétez ce schéma pour chaque paire de services autorisée à communiquer. C’est fastidieux à écrire manuellement sur un grand cluster, ce qui justifie souvent le passage aux CiliumNetworkPolicy ou GlobalNetworkPolicy pour factoriser les règles communes, abordées plus bas.

Préférez toujours nommer les ports plutôt que de coder en dur un numéro, quand votre définition de service le permet. Un port nommé dans le manifeste du Deployment (name: postgres plutôt que 5432 seul) reste valide même si l’équipe applicative décide de changer le port d’écoute plus tard, ce qui évite une NetworkPolicy silencieusement obsolète après une migration technique mineure.

Étape 8 : Restreindre l’egress vers Internet

Un pod compromis qui garde un accès sortant illimité vers Internet peut exfiltrer des données ou récupérer un second payload d’attaque. Limitez l’egress externe aux seules destinations nécessaires, et bloquez explicitement l’accès au point de métadonnées cloud 169.254.169.254, une cible classique pour l’élévation de privilèges via les credentials d’instance.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: restrict-egress-internet
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: api-backend
  policyTypes:
    - Egress
  egress:
    - to:
        - ipBlock:
            cidr: 0.0.0.0/0
            except:
              - 169.254.169.254/32
      ports:
        - protocol: TCP
          port: 443

Étape 9 : Tester en staging avant la bascule

Appliquez l’ensemble de vos politiques sur staging, puis laissez tourner le trafic normal pendant au moins 48 heures en surveillant les métriques d’erreur applicatives et les logs Hubble pour repérer les flux rejetés à tort.

hubble observe --namespace staging --verdict DROPPED --follow

Chaque ligne DROPPED correspond à un flux bloqué par vos politiques. Si vous en voyez apparaître pour des connexions attendues, ajustez la règle concernée avant de passer à la production. Cette phase de validation est ce qui différencie un déploiement réussi d’un incident de disponibilité en pleine nuit.

Étapes 10 et 11 : intégrer au CI/CD et basculer en production

Étape 10 : Imposer les Network Policies avec Kyverno

Une fois le modèle validé, évitez qu’un futur déploiement crée un namespace sans politique associée. Kyverno permet d’imposer cette règle directement dans le pipeline CI/CD, en rejetant toute création de namespace applicatif dépourvu de default-deny.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-default-deny-networkpolicy
spec:
  validationFailureAction: Enforce
  rules:
    - name: check-default-deny-exists
      match:
        any:
          - resources:
              kinds:
                - Namespace
              selector:
                matchLabels:
                  environment: production
      validate:
        message: "Un namespace de production doit avoir une NetworkPolicy default-deny."
        deny:
          conditions:
            - key: "{{ request.object.metadata.name }}"
              operator: NotIn
              value: "{{ networkpolicies.production.[?spec.podSelector == `{}`].metadata.namespace }}"

Une alternative plus simple à démarrer : OPA Gatekeeper permet le même type de garde-fou via des contraintes déclaratives, si votre organisation utilise déjà Rego pour ses autres politiques de conformité.

Étape 11 : Bascule en production avec rollback automatique

Déployez d’abord en mode observation (Cilium le permet via l’annotation audit-mode sur certaines versions, ou en surveillant Hubble sans bloquer), puis basculez au mode enforce namespace par namespace, jamais en une seule fois sur tout le cluster. Gardez sous la main la commande de retrait immédiat :

kubectl delete networkpolicy default-deny-all -n production
kubectl get networkpolicy -n production

Configurez une alerte sur le taux de connexions DROPPED observées par Hubble juste après la bascule : un pic soudain signale une règle manquante et déclenche le rollback avant que les utilisateurs ne le remarquent.

Procédez par vagues : un premier namespace à faible criticité pendant 24 heures, puis les namespaces suivants un par un sur plusieurs jours plutôt qu’en une seule fenêtre de maintenance. Cette approche progressive limite le rayon d’impact d’une règle mal écrite à un seul service plutôt qu’à l’ensemble de votre plateforme, et donne à l’équipe d’astreinte le temps de repérer un problème avant qu’il ne s’accumule sur plusieurs namespaces en parallèle.

Calico : les GlobalNetworkPolicy pour aller plus loin

Si votre cluster tourne sous Calico plutôt que Cilium, le principe reste identique mais la ressource change. Le CRD GlobalNetworkPolicy de Calico permet d’appliquer une règle à l’ensemble du cluster sans la dupliquer dans chaque namespace, un vrai gain de maintenance sur un cluster multi-équipes.

apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
  name: deny-metadata-endpoint
spec:
  selector: all()
  types:
    - Egress
  egress:
    - action: Deny
      destination:
        nets:
          - 169.254.169.254/32
    - action: Allow

Pour auditer les politiques déjà en place sur un cluster Calico existant, la commande suivante liste l’ensemble des règles actives sur un namespace donné :

calicoctl get networkpolicy -n production -o yaml

Calico expose aussi des logs de flux exportables vers un SIEM externe, un atout pour les équipes qui doivent produire des preuves d’audit régulières dans le cadre de NIS2 ou d’une certification C5 côté hébergeurs allemands.

L’agent responsable de l’application des règles côté Calico s’appelle Felix : il tourne en DaemonSet sur chaque nœud et traduit les GlobalNetworkPolicy en règles iptables ou eBPF selon le mode choisi à l’installation. Si une politique semble ne pas s’appliquer, un premier réflexe consiste à vérifier les logs de ce composant plutôt que ceux du contrôleur central, car c’est Felix qui exécute concrètement le filtrage sur chaque nœud.

Projet complet : sécuriser une application 3 tiers de bout en bout

Pour ancrer l’ensemble du tutoriel, voici l’arborescence d’un projet de démonstration complet, déployable tel quel sur un cluster de test, qui applique toutes les politiques vues plus haut à une application frontend / API / base de données :

zero-trust-demo/
├── namespace.yaml
├── deployments/
│   ├── frontend.yaml
│   ├── api-backend.yaml
│   └── database.yaml
├── network-policies/
│   ├── 00-default-deny-all.yaml
│   ├── 01-allow-dns.yaml
│   ├── 02-allow-kube-system.yaml
│   ├── 03-frontend-to-api.yaml
│   ├── 04-api-to-database.yaml
│   └── 05-restrict-egress-internet.yaml
└── kyverno/
    └── require-default-deny.yaml

L’ordre de déploiement compte : appliquez d’abord les workloads, puis le default-deny, puis chaque règle d’autorisation une par une en vérifiant les flux Hubble entre chaque application. Un script minimal automatise l’ensemble :

kubectl apply -f namespace.yaml
kubectl apply -f deployments/
kubectl apply -f network-policies/00-default-deny-all.yaml
sleep 5 && hubble observe --namespace production --verdict DROPPED --last 20
kubectl apply -f network-policies/01-allow-dns.yaml
kubectl apply -f network-policies/02-allow-kube-system.yaml
kubectl apply -f network-policies/03-frontend-to-api.yaml
kubectl apply -f network-policies/04-api-to-database.yaml
kubectl apply -f network-policies/05-restrict-egress-internet.yaml
kubectl apply -f kyverno/require-default-deny.yaml

Ce squelette couvre déjà la majorité des cas rencontrés en environnement de production : frontend public, API interne, base de données isolée, et garde-fou CI/CD pour empêcher toute régression future.

Pour valider que le projet fonctionne comme prévu, ajoutez un pod de test temporaire qui tente de joindre la base de données directement depuis le namespace frontend, en contournant l’API. Cette connexion doit échouer si vos politiques sont correctement écrites :

kubectl run test-frontend --rm -it --image=busybox -n production \
  --labels="app=frontend" -- sh -c "nc -zv -w 3 database 5432"

Une sortie du type nc: database (10.0.0.12:5432): Connection timed out confirme que la politique api-to-database bloque bien l’accès direct depuis le frontend, alors que le même test lancé depuis un pod labellisé app: api-backend doit réussir. Ce test croisé, simple à automatiser dans une étape de pipeline, constitue une bonne validation de non-régression à chaque modification future des politiques réseau.

Erreurs courantes à éviter

Ces erreurs reviennent systématiquement dans les retours d’expérience des équipes qui déploient leur première microsegmentation Kubernetes :

  • Appliquer le default-deny directement en production, sans être passé par staging ni avoir cartographié les flux : c’est la cause numéro un des incidents liés aux Network Policies.
  • Oublier la règle DNS juste après le default-deny : sans elle, tous les pods perdent instantanément la résolution de noms, y compris vers les services internes.
  • Confondre podSelector: {} et l’absence de podSelector : le premier cible tous les pods du namespace, le second est syntaxiquement invalide dans une NetworkPolicy.
  • Négliger l’egress en ne filtrant que l’ingress : un pod compromis avec un egress libre peut exfiltrer des données sans qu’aucune règle ne s’y oppose.
  • Ne jamais tester en staging, ou tester sur un trafic non représentatif (pas de jobs batch, pas de pics de charge).
  • Ignorer l’accès au endpoint de métadonnées cloud (169.254.169.254), une cible privilégiée pour voler des credentials d’instance depuis un pod compromis.
  • Mélanger CiliumNetworkPolicy (CRD) et NetworkPolicy standard sans comprendre que la première offre des capacités L7 que la seconde ne gère pas, ce qui crée des incohérences de compréhension dans les équipes.

Dépannage : les problèmes les plus fréquents

Voici les incidents les plus signalés lors du déploiement d’une microsegmentation Cilium ou Calico, avec leur cause probable et la correction à appliquer. Gardez cette liste ouverte pendant votre bascule en production : la plupart de ces situations se règlent en quelques minutes une fois la cause identifiée, mais elles paraissent alarmantes la première fois qu’on les rencontre sans référence sous la main.

SymptômeCause probableCorrection
Les pods ne résolvent plus les noms de domaine après default-denyRègle allow-dns manquanteAppliquer la NetworkPolicy DNS de l’étape 5 avant toute autre restriction
Les health checks du kubelet échouent après application des politiquesLe podSelector ne couvre pas le trafic issu du nœud (kubelet)Ajouter une règle ipBlock ciblant le CIDR interne des nœuds
cilium status affiche CrashLoopBackOff sur le DaemonSetVersion de noyau Linux incompatible avec eBPF requis par CiliumVérifier le noyau (5.4+ recommandé) et les modules eBPF chargés
Hubble UI inaccessible après port-forwardLe pod hubble-relay n’est pas prêt ou le port est déjà utilisé localementVérifier kubectl get pods -n kube-system et changer de port local
Les NetworkPolicy semblent totalement ignoréesLe CNI en place (ex. Flannel) n’implémente pas l’application des NetworkPolicyMigrer vers un CNI qui applique les politiques, comme Cilium ou Calico
Les pulls d’images depuis un registre externe échouent après restriction egressLa règle egress ne couvre pas l’IP ou le port du registre d’imagesAjouter le registre dans les destinations autorisées avant d’activer la restriction
calicoctl renvoie une erreur de connexion au datastoreMauvais mode de datastore configuré (etcd vs Kubernetes API)Vérifier la variable DATASTORE_TYPE dans la configuration calicoctl
Un sidecar de service mesh (Istio) perd la connectivité après une politique CiliumLe podSelector ne prend pas en compte le port du proxy sidecarAjouter explicitement les ports du sidecar dans les règles ingress et egress
Une politique appliquée en staging ne produit aucun effet visibleLe CNI applique la politique correctement mais aucun trafic ne la teste réellementGénérer du trafic de test avec un pod temporaire (kubectl run –rm -it) avant de conclure

Si un incident survient malgré ces vérifications, la commande la plus rapide pour reprendre la main reste de lister toutes les politiques actives sur le namespace concerné, puis de les retirer une par une jusqu’à identifier la règle fautive :

kubectl get networkpolicy -n production -o name
kubectl describe networkpolicy NOM_DE_LA_POLITIQUE -n production

Astuces avancées : multi-cluster, service mesh et FinOps

Une fois le socle en place sur un cluster unique, plusieurs extensions valent le détour. Cilium ClusterMesh permet d’étendre les politiques réseau à plusieurs clusters, utile pour les architectures multi-région fréquentes chez les entreprises européennes soumises à des contraintes de résidence des données. Les règles CiliumNetworkPolicy s’appliquent alors de façon cohérente entre un cluster en France et un cluster en Allemagne, par exemple.

Côté service mesh, Cilium propose un mode sans sidecar (via eBPF directement) qui réduit la surcharge par rapport à un mesh classique type Istio avec proxy Envoy sur chaque pod. Si votre organisation utilise déjà Istio, les CiliumNetworkPolicy et les politiques d’autorisation Istio peuvent coexister, mais testez soigneusement les interactions entre les deux couches avant la bascule en production.

Sur le filtrage L7, Cilium permet d’aller plus loin que le simple blocage par port. Une CiliumNetworkPolicy peut, par exemple, n’autoriser qu’un sous-ensemble de méthodes HTTP vers un chemin précis d’une API interne, ce qui revient à faire une partie du travail habituellement dévolu à une passerelle API, directement au niveau réseau. C’est particulièrement utile pour des services legacy dont vous ne pouvez pas modifier le code applicatif, mais dont vous voulez tout de même restreindre les endpoints exposés en interne.

Enfin, un angle souvent négligé : le lien entre microsegmentation et FinOps. Cartographier précisément les flux réseau, comme à l’étape 3, révèle souvent des communications inter-zones ou inter-régions inutiles, facturées au gigaoctet par les fournisseurs cloud. Réduire ces flux via des politiques bien pensées a un effet direct sur la facture, en plus du bénéfice sécurité. Les benchmarks IT 2026 sur les solutions de FinOps évoquent des gains de 20 à 40 % sur la facture cloud grâce à une meilleure visibilité et à l’élimination des ressources et flux inutiles.

Foire aux questions

Une NetworkPolicy Kubernetes standard suffit-elle sans Cilium ni Calico ?

Non. La ressource NetworkPolicy fait partie de l’API Kubernetes, mais son application dépend entièrement du CNI installé. Sans un CNI qui l’implémente, comme Cilium ou Calico, les règles sont acceptées par l’API server mais n’ont aucun effet réel sur le trafic.

Peut-on migrer un cluster de Calico vers Cilium sans interruption ?

C’est possible mais délicat, car deux CNI actifs en parallèle créent des conflits réseau. La méthode la plus sûre consiste à migrer nœud par nœud avec un cordon/drain progressif, ou à reconstruire le cluster si votre infrastructure le permet facilement (cluster éphémère, Infrastructure as Code).

Combien de temps faut-il pour sécuriser un cluster de production existant ?

Comptez au minimum deux à trois semaines pour un cluster de taille moyenne : une à deux semaines de collecte des flux via Hubble, puis une phase de tests en staging avant la bascule progressive en production, namespace par namespace.

La microsegmentation ralentit-elle les performances réseau ?

Avec Cilium et son moteur eBPF, l’impact est marginal comparé à une approche iptables classique, car les vérifications se font directement dans le noyau sans passer par de longues chaînes de règles. C’est justement l’un des arguments techniques qui a poussé de nombreux fournisseurs de Kubernetes managé à proposer Cilium par défaut.

Faut-il une NetworkPolicy par pod ou peut-on grouper par label ?

Toujours grouper par label via le podSelector plutôt que cibler des pods individuels. C’est le principe même de Kubernetes : les pods sont éphémères, les règles doivent s’appliquer à des groupes logiques (par exemple app: api-backend) qui survivent aux redéploiements.

Les Network Policies suffisent-elles pour la conformité NIS2 ?

Elles constituent un élément de preuve important pour la segmentation réseau exigée par NIS2, mais ne couvrent pas à elles seules l’ensemble des obligations (gestion des vulnérabilités, réponse à incident, gouvernance). Consultez la directive NIS2 officielle pour le périmètre complet applicable à votre secteur.

Que se passe-t-il si deux NetworkPolicy contradictoires ciblent le même pod ?

Il n’y a pas de conflit possible au sens strict, car le modèle est additif : Kubernetes fusionne les règles de toutes les politiques qui ciblent un pod donné. Si une politique autorise un flux et qu’une autre ne mentionne pas ce flux, il reste autorisé. Le seul moyen de bloquer un flux est de ne l’inclure dans aucune règle d’autorisation une fois le default-deny actif, jamais de le “refuser” explicitement dans une NetworkPolicy standard.

Quelle est la différence entre CiliumNetworkPolicy et NetworkPolicy standard ?

CiliumNetworkPolicy est un CRD propre à Cilium qui étend le modèle standard avec le filtrage L7 (règles HTTP par chemin ou méthode, par exemple), les politiques cluster-wide via CiliumClusterwideNetworkPolicy, et des capacités DNS-aware pour filtrer l’egress par nom de domaine plutôt que par IP fixe.

Pour approfondir les bonnes pratiques de durcissement Kubernetes au-delà du réseau, consultez également le Kubernetes Security Cheat Sheet de l’OWASP et le dépôt officiel Cilium sur GitHub pour suivre les évolutions du projet.

Pour aller plus loin

La microsegmentation réseau n’est qu’une brique du durcissement Kubernetes global. Elle se combine avec la gestion des secrets, le scan des images, les profils seccomp et le RBAC pour former une défense en profondeur cohérente. Les articles suivants complètent ce tutoriel sur les autres piliers de la sécurité de votre cluster.

Retrouvez l’ensemble de nos guides sur le cloud computing pour suivre les prochaines évolutions de la sécurité Kubernetes en 2026.