
Les NetworkPolicies contrôlent quels Pods peuvent communiquer entre eux et avec l'extérieur au niveau IP et port (L3/L4). Par défaut, Kubernetes n'applique aucune restriction : tous les Pods se parlent librement. Les NetworkPolicies permettent de cloisonner ces flux selon le principe du moindre privilège.
Ce guide couvre la création de policies ingress et egress, les cas critiques comme le DNS, et les techniques de debug indispensables.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Comprendre le modèle : sélection par labels, union des règles, logique source/destination
- Créer des policies : deny par défaut, autorisation ciblée, filtrage par namespace
- Gérer l'egress : ne pas casser le DNS, autoriser les flux nécessaires
- Débugger : diagnostiquer pourquoi un flux est bloqué ou autorisé
À quoi servent les NetworkPolicies
Section intitulée « À quoi servent les NetworkPolicies »En l'absence de restrictions réseau applicables, les Pods peuvent généralement communiquer largement entre eux, y compris entre namespaces. C'est le comportement réseau permissif par défaut de Kubernetes.
Les NetworkPolicies permettent de :
- Restreindre les connexions entrantes vers un Pod (ingress)
- Restreindre les connexions sortantes depuis un Pod (egress)
- Isoler des environnements (production, staging, test)
- Limiter la propagation en cas de compromission d'un Pod
Condition préalable : un CNI compatible
Section intitulée « Condition préalable : un CNI compatible »Kubernetes définit les NetworkPolicies, mais ne les applique pas lui-même. C'est le plugin réseau (CNI) qui doit implémenter cette fonctionnalité.
Avant d'écrire des NetworkPolicies, vérifiez dans la documentation de votre plugin réseau qu'il applique bien les policies Kubernetes.
Parmi les implémentations souvent utilisées qui supportent les NetworkPolicies :
| CNI | Support NetworkPolicy | Notes |
|---|---|---|
| Calico | ✅ Complet | Policies étendues disponibles |
| Cilium | ✅ Complet | Filtrage L7 optionnel |
| Antrea | ✅ Complet | Orienté VMware/vSphere |
| Weave Net | ✅ Complet | Dépôt d'origine archivé en juin 2024, seul un fork communautaire est maintenu |
| Flannel | ❌ Aucun | « For network policy, other projects such as Calico can be used » (README amont) |
Vérifier le CNI installé :
kubectl get pods -n kube-system -l k8s-app=calico-nodekubectl get pods -n kube-system -l k8s-app=ciliumComment fonctionne le modèle
Section intitulée « Comment fonctionne le modèle »Sélection par labels
Section intitulée « Sélection par labels »Une NetworkPolicy cible les Pods via un podSelector basé sur leurs labels.
Sans sélection valide, la policy ne s'applique à aucun Pod.
spec: podSelector: matchLabels: app: backendCette policy s'applique uniquement aux Pods ayant le label app: backend dans
le namespace où elle est déployée.
Sélectionner tous les Pods d'un namespace :
spec: podSelector: {}Ingress et Egress
Section intitulée « Ingress et Egress »Ces deux directions se conçoivent depuis le Pod sélectionné par la policy,
jamais depuis le réseau. Ingress désigne ce qui entre dans ce Pod,
Egress ce qui en sort. La confusion la plus fréquente vient du mot « Ingress »,
qui désigne aussi une ressource Kubernetes de routage HTTP : les deux n'ont
aucun rapport. Retenez aussi que restreindre l'egress est nettement plus
risqué que restreindre l'ingress, parce que c'est la direction qui porte le
DNS.
| Direction | Contrôle | Quand restreindre |
|---|---|---|
| Ingress | Connexions entrantes vers le Pod | Limiter qui peut accéder à un service |
| Egress | Connexions sortantes depuis le Pod | Limiter où un Pod peut se connecter |
Déclarez explicitement policyTypes pour éviter les ambiguïtés :
spec: policyTypes: - Ingress - EgressUnion des règles
Section intitulée « Union des règles »Les NetworkPolicies ne se remplacent pas l'une l'autre. Les connexions autorisées résultent de l'union de toutes les règles applicables au Pod pour la direction concernée.
Exemple : si deux policies autorisent des sources différentes vers le même Pod, les deux sources sont autorisées.
Policy A : autorise frontend → backendPolicy B : autorise monitoring → backendRésultat : frontend ET monitoring peuvent accéder à backendLogique source + destination
Section intitulée « Logique source + destination »Pour qu'une connexion fonctionne, elle doit être autorisée des deux côtés si des restrictions existent :
- L'egress du Pod source doit autoriser la sortie vers la destination
- L'ingress du Pod destination doit autoriser l'entrée depuis la source
Pod A (egress restreint) → Pod B (ingress restreint)
✅ Fonctionne si : - Policy egress de A autorise B - Policy ingress de B autorise A
❌ Échoue si : - L'une des deux policies manque l'autorisationC'est un point fondamental pour le dépannage : vérifiez toujours les policies des deux côtés.
Premier cas : autoriser frontend vers backend
Section intitulée « Premier cas : autoriser frontend vers backend »Commençons par un cas classique : seuls les Pods frontend peuvent accéder
aux Pods backend sur le port 8080.
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: allow-frontend-to-backend namespace: defaultspec: podSelector: matchLabels: app: backend policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: app: frontend ports: - protocol: TCP port: 8080Ce que fait cette policy :
- Sélectionne les Pods
app: backenddans le namespacedefault - Restreint leur trafic ingress (entrées deviennent contrôlées)
- Autorise uniquement les connexions depuis les Pods
app: frontend - Limite au port TCP 8080
Appliquer et tester :
kubectl apply -f allow-frontend-to-backend.yaml
# Depuis un Pod frontendkubectl exec -it deploy/frontend -- curl backend:8080# Résultat : connexion réussie
# Depuis un autre Podkubectl exec -it deploy/autre-app -- curl backend:8080# Résultat : bloquéLa forme exacte du blocage dépend du CNI, ne vous fiez pas à un symptôme
unique. Un CNI qui pose une règle DROP produit un timeout ; le contrôleur
embarqué de k3s renvoie une connexion refusée immédiate. Dans les deux cas
la connexion n'aboutit pas, mais un « connection refused » ne signifie pas que
votre policy est hors sujet.
Default deny ingress
Section intitulée « Default deny ingress »Pour isoler complètement un namespace ou un groupe de Pods, commencez par bloquer tout le trafic entrant :
Pour tout un namespace
Section intitulée « Pour tout un namespace »Le manifeste ci-dessous est le plus court du guide et l'un des plus lourds de
conséquences. Deux détails le rendent bloquant : podSelector: {} qui, loin de
ne rien sélectionner, sélectionne tous les Pods du namespace, et l'absence
totale de clé ingress. Une policy sans règle n'autorise rien, c'est ce qui
transforme une simple déclaration en blocage complet. Appliquez-la sur un
namespace de test avant la production, elle coupe immédiatement l'accès aux
applications existantes.
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: default-deny-ingress namespace: productionspec: podSelector: {} # Tous les Pods du namespace policyTypes: - Ingress # Pas de section ingress = rien n'est autoriséCette policy :
- Sélectionne tous les Pods du namespace
production - Déclare qu'elle contrôle l'ingress
- N'autorise aucune connexion entrante (pas de règle
ingress)
Pour un groupe de Pods spécifique
Section intitulée « Pour un groupe de Pods spécifique »Cette variante limite le blocage aux Pods portant un label précis, ce qui permet
d'isoler un composant sensible sans figer tout le namespace. Notez la différence
d'écriture avec l'exemple précédent : ici la clé ingress: [] est présente mais
vide, alors que plus haut elle était absente. Les deux formes produisent le
même résultat, aucune source autorisée ; ingress: [] a simplement le mérite
de rendre l'intention explicite pour le prochain lecteur du dépôt.
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: deny-ingress-backend namespace: defaultspec: podSelector: matchLabels: app: backend policyTypes: - Ingress ingress: []Default deny egress
Section intitulée « Default deny egress »Restreindre les connexions sortantes est tout aussi important, mais nécessite plus d'attention car cela peut casser des fonctionnalités critiques.
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: default-deny-egress namespace: productionspec: podSelector: {} policyTypes: - Egress # Pas de section egress = rien n'est autoriséAutoriser le DNS
Section intitulée « Autoriser le DNS »C'est le premier réflexe dès que vous restreignez l'egress. Sans DNS,
vos applications ne peuvent plus résoudre mon-service.namespace.svc.cluster.local.
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: allow-dns-egress namespace: productionspec: podSelector: {} # Tous les Pods du namespace policyTypes: - Egress egress: - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system podSelector: matchLabels: k8s-app: kube-dns ports: - protocol: UDP port: 53 - protocol: TCP port: 53Alternative plus simple (moins restrictive) :
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: allow-dns-egress-simple namespace: productionspec: podSelector: {} policyTypes: - Egress egress: - ports: - protocol: UDP port: 53 - protocol: TCP port: 53Cette version autorise le port 53 vers n'importe quelle destination. Plus permissive, mais plus simple à maintenir.
Exemple complet : egress contrôlé
Section intitulée « Exemple complet : egress contrôlé »Voici une policy qui autorise un Pod à :
- Résoudre le DNS
- Accéder à une base de données PostgreSQL interne
- Rien d'autre
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: backend-egress-controlled namespace: productionspec: podSelector: matchLabels: app: backend policyTypes: - Egress egress: # DNS - ports: - protocol: UDP port: 53 - protocol: TCP port: 53 # PostgreSQL interne - to: - podSelector: matchLabels: app: postgresql ports: - protocol: TCP port: 5432Sélection par namespace
Section intitulée « Sélection par namespace »Pour autoriser des flux entre namespaces, utilisez namespaceSelector.
Autoriser depuis un namespace spécifique
Section intitulée « Autoriser depuis un namespace spécifique »Le point à surveiller ici est que namespaceSelector sélectionne des labels de
namespace, pas un nom. Écrire name: monitoring ne fonctionne que si le
namespace porte réellement ce label, ce qui n'est pas automatique. Kubernetes
pose bien un label kubernetes.io/metadata.name sur chaque namespace depuis la
1.21, et c'est souvent le sélecteur le plus fiable parce que personne n'a besoin
de penser à l'ajouter.
Une fois cette règle appliquée, tous les Pods du namespace monitoring
peuvent atteindre le backend, sur n'importe quel port. Pour restreindre à un
Pod précis, il faut combiner les deux sélecteurs, ce que couvre la section
suivante.
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: allow-from-monitoring namespace: productionspec: podSelector: matchLabels: app: backend policyTypes: - Ingress ingress: - from: - namespaceSelector: matchLabels: name: monitoringCombiner namespace et pod selector
Section intitulée « Combiner namespace et pod selector »Pour cibler des Pods spécifiques dans un namespace spécifique :
ingress: - from: - namespaceSelector: matchLabels: name: monitoring podSelector: matchLabels: app: prometheusAttention à la syntaxe : les deux sélecteurs dans le même item - signifie
ET logique. Séparés, c'est OU logique :
# ET logique : namespace monitoring ET pod prometheus- from: - namespaceSelector: matchLabels: name: monitoring podSelector: matchLabels: app: prometheus
# OU logique : namespace monitoring OU pod prometheus (dans le même namespace)- from: - namespaceSelector: matchLabels: name: monitoring - podSelector: matchLabels: app: prometheusUtiliser ipBlock
Section intitulée « Utiliser ipBlock »ipBlock permet d'autoriser des plages d'adresses IP, typiquement pour
des systèmes externes au cluster.
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: allow-external-api namespace: productionspec: podSelector: matchLabels: app: backend policyTypes: - Egress egress: - to: - ipBlock: cidr: 203.0.113.0/24 except: - 203.0.113.128/25 ports: - protocol: TCP port: 443Ce que les NetworkPolicies ne font pas
Section intitulée « Ce que les NetworkPolicies ne font pas »Pour éviter les fausses attentes, voici ce que les NetworkPolicies standard ne peuvent pas faire :
| Fonctionnalité | NetworkPolicy | Alternative |
|---|---|---|
| Filtrer par URL/path HTTP | ❌ Non | Service mesh (Istio, Linkerd) |
| Authentification mutuelle (mTLS) | ❌ Non | Service mesh |
| Filtrer par méthode HTTP (GET, POST) | ❌ Non | Service mesh, API Gateway |
| Inspection de payload | ❌ Non | WAF |
| Logging des connexions bloquées | ❌ Non | CNI spécifique (Cilium, Calico) |
| Policies inter-clusters | ❌ Non | Solutions multi-cluster |
Les NetworkPolicies sont un premier niveau de segmentation réseau, pas une solution de sécurité applicative complète.
Débugger une NetworkPolicy
Section intitulée « Débugger une NetworkPolicy »Quand un flux est bloqué (ou ne l'est pas alors qu'il devrait), suivez cette méthode :
-
Lister les policies du namespace
Fenêtre de terminal kubectl get networkpolicy -n production -
Examiner une policy en détail
Fenêtre de terminal kubectl describe networkpolicy allow-frontend-to-backend -n productionVérifiez :
PodSelector: quels Pods sont ciblés ?Allowing ingress traffic: quelles sources sont autorisées ?Allowing egress traffic: quelles destinations sont autorisées ?
-
Vérifier les labels des Pods
Fenêtre de terminal kubectl get pods -n production --show-labelskubectl get pods -n production -l app=backendUn Pod sans le bon label ne sera pas sélectionné par la policy.
-
Tester la connectivité
Fenêtre de terminal # Depuis le Pod sourcekubectl exec -it deploy/frontend -n production -- nc -vz backend 8080# Test DNSkubectl exec -it deploy/frontend -n production -- nslookup backend -
Vérifier les deux côtés
Si l'egress du source ET l'ingress de la destination sont restreints, vérifiez que les deux autorisent le flux.
Fenêtre de terminal # Policies qui sélectionnent le Pod source (egress)kubectl get networkpolicy -n production -o json | \jq '.items[] | select(.spec.podSelector.matchLabels.app=="frontend")'# Policies qui sélectionnent le Pod destination (ingress)kubectl get networkpolicy -n production -o json | \jq '.items[] | select(.spec.podSelector.matchLabels.app=="backend")'
Outils de debug avancés
Section intitulée « Outils de debug avancés »Un point de méthode avant de lancer ces commandes : un Pod de debug créé avec
kubectl run porte des labels différents de votre application, donc les
policies qui protègent celle-ci ne s'appliquent pas à lui. Vous risquez de
conclure « le flux passe » alors que vous avez simplement testé depuis un Pod
non concerné. Pour un test représentatif, ajoutez les labels de l'application
avec --labels="app=frontend", ou utilisez kubectl debug pour attacher un
conteneur éphémère au Pod réel.
# Pod de debug avec outils réseaukubectl run netshoot --rm -it --image=nicolaka/netshoot -- bash
# Dans le pod netshootnslookup backend.production.svc.cluster.localcurl -v backend.production:8080nc -vz backend.production 8080
# Vérifier si le CNI loggue les drops (Cilium)kubectl logs -n kube-system -l k8s-app=cilium -c cilium-agent | grep -i dropProblèmes courants
Section intitulée « Problèmes courants »Lisez ce tableau en distinguant deux familles de pannes. Les quatre premières
lignes décrivent un flux bloqué à tort : la cause est presque toujours une
autorisation manquante ou un label qui ne correspond pas, et vous la trouverez
en comparant kubectl describe networkpolicy aux labels réels des Pods. La
dernière ligne décrit l'inverse, un flux autorisé à tort, et elle se
diagnostique différemment : il ne s'agit pas de chercher une erreur dans une
policy, mais de lister toutes celles qui sélectionnent le Pod, puisque leurs
autorisations s'additionnent.
| Symptôme | Cause probable | Solution |
|---|---|---|
| Timeout vers un service | Policy ingress manquante côté destination | Ajouter une règle from |
| DNS ne résout plus | Egress deny sans exception DNS | Autoriser le port 53 |
| Policy ignorée | CNI incompatible | Vérifier le support NetworkPolicy |
| Pod non sélectionné | Labels incorrects | Vérifier --show-labels |
| Flux autorisé inattendu | Union de plusieurs policies | Lister toutes les policies applicables |
Documenter vos NetworkPolicies
Section intitulée « Documenter vos NetworkPolicies »Pour maintenir des policies lisibles dans le temps :
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: allow-frontend-to-backend namespace: production annotations: description: "Autorise le frontend à accéder au backend sur le port API" owner: "team-platform" last-review: "2026-03-22"spec: # ...Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Sept questions, avec un seuil volontairement haut à 90 % : sur ce sujet, une règle mal comprise se traduit par une application coupée en production ou, pire, par une isolation que vous croyez active alors qu'elle ne l'est pas. Les deux points qui font le plus trébucher sont l'union des policies et la nécessité d'autoriser le flux des deux côtés.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
Ce qu'il faut savoir pour la CKAD
Section intitulée « Ce qu'il faut savoir pour la CKAD »L'examen étant chronométré, l'enjeu n'est pas de connaître toutes les options
mais de produire un manifeste correct sans réfléchir à la structure. Les cinq
gestes ci-dessous sont ceux qui reviennent ; entraînez-vous à les écrire de
mémoire, puis à les vérifier avec kubectl describe. Rappel utile le jour J :
kubectl explain networkpolicy.spec --recursive est disponible pendant
l'épreuve et vous évite de deviner l'imbrication des champs.
-
Lire une policy existante
Identifiez rapidement : quels Pods sont sélectionnés (
podSelector), quel trafic est contrôlé (policyTypes), quelles règles s'appliquent. -
Créer un default deny ingress
podSelector: {}policyTypes: [Ingress]# Pas de section ingress -
Autoriser un flux spécifique
Frontend vers backend, port 8080 :
ingress:- from:- podSelector:matchLabels:app: frontendports:- port: 8080 -
Autoriser le DNS en egress
Dès que vous restreignez l'egress, autorisez UDP/TCP 53.
-
Diagnostiquer un blocage
kubectl get networkpolicy -n <ns>kubectl describe networkpolicy <name>kubectl get pods --show-labelskubectl exec ... -- nc -vz <service> <port>
À retenir
Section intitulée « À retenir »- Les NetworkPolicies opèrent au niveau L3/L4 (IP/port), pas HTTP
- Le CNI doit supporter l'enforcement des policies, sinon elles sont ignorées
- Un Pod devient isolé (ingress ou egress) dès qu'une policy le sélectionne
- Les règles autorisées sont l'union des policies applicables
- Une connexion doit être autorisée des deux côtés (source egress + destination ingress)
- Dès que l'egress est restreint, pensez au DNS (port 53)
ipBlockest pour les IP externes stables, pas pour cibler des Pods- Déclarez explicitement
policyTypespour éviter les ambiguïtés
Pour aller plus loin
Section intitulée « Pour aller plus loin »- mTLS pod-to-pod : Le chiffrement et l'authentification du trafic que vos règles laissent passer.
- Falco : La détection des comportements suspects qui franchissent malgré tout le filtrage.
- RBAC Kubernetes : Le pendant de l'isolation réseau côté API, pour les droits des utilisateurs et des Pods.