Aller au contenu principal
KubernetesNetworkingService Mesh

CNI et networking K8s en détail

30 min de lecture Apprendre Kubernetes — Chapitre 9

Comprends le modèle réseau Kubernetes, les plugins CNI et les Network Policies en profondeur.

Kubernetes te promet un truc simple : chaque Pod a sa propre IP, et n’importe quel Pod peut parler à n’importe quel autre sans NAT ni bidouille réseau. C’est le modèle réseau plat. Sauf que K8s ne l’implémente pas lui-même — il délègue ce boulot à un plugin CNI (Container Network Interface). C’est ce plugin qui crée les interfaces réseau, assigne les IPs et gère le routage inter-nodes.

Ce cours te donne les clés pour comprendre comment tes Pods communiquent réellement, choisir le bon CNI et verrouiller les flux avec les Network Policies. Si tu gères un cluster en production, chaque section ici va t’éviter des heures de debug et des failles de sécurité.

Pourquoi le networking K8s est critique

Imagine un cluster de 50 nodes avec 400 Pods. Par défaut, chaque Pod peut joindre n’importe quel autre Pod du cluster. C’est pratique pour développer, mais c’est un cauchemar en production — un seul container compromis a accès à tout : ta base de données, ton cache Redis, tes APIs internes.

🔥 Cas réel : une startup fintech a subi une fuite de données parce qu’un Pod de monitoring mal configuré avait accès direct à PostgreSQL en production. Aucune Network Policy en place. Le Pod compromis a aspiré 200 000 lignes de données clients en 4 minutes.

Trois risques concrets si tu ne maîtrises pas le réseau K8s :

  • Sécurité : sans isolation, un container compromis devient une porte ouverte sur l’ensemble du cluster.
  • Performance : un mauvais choix de CNI peut ajouter 2 à 5 ms de latence par hop réseau. Dans une archi microservices avec 10 appels chaînés, ça se cumule vite.
  • Debug aveugle : sans comprendre les couches réseau (veth pairs, bridges, overlays), tu ne sais pas où chercher quand un service ne répond plus.

💡 Tip DevOps : le choix du CNI se fait avant le déploiement du cluster. Changer de CNI en production, c’est comme changer le moteur d’un avion en vol — faisable, mais tu ne veux vraiment pas y être contraint.

Comprendre le modèle réseau Kubernetes

Kubernetes impose quatre règles fondamentales :

  1. Chaque Pod a sa propre adresse IP — les containers d’un même Pod partagent cette IP et communiquent via localhost.
  2. Tout Pod peut joindre tout autre Pod sans NAT, quel que soit le node.
  3. Les agents du node (kubelet, kube-proxy) peuvent communiquer avec tous les Pods du node.
  4. L’implémentation est déléguée au plugin CNI — Kubernetes définit les règles, le CNI les applique.

Concrètement, quand un Pod est créé, le kubelet appelle le plugin CNI qui crée un network namespace isolé, une paire d’interfaces veth (un bout dans le Pod, l’autre sur le bridge du node) et assigne une IP depuis le CIDR du node.

Les chemins de communication varient selon le scénario :

  • Container ↔ Container dans le même Pod → localhost
  • Pod ↔ Pod sur le même node → bridge virtuel et veth pairs
  • Pod ↔ Pod sur des nodes différents → overlay VXLAN ou routage BGP (selon le CNI)
  • Pod ↔ Service → kube-proxy via iptables ou IPVS
  • Externe → Pod → Ingress controller ou LoadBalancer

Le choix du CNI détermine comment le trafic inter-nodes circule. Flannel crée un overlay VXLAN — simple mais avec un coût d’encapsulation. Calico utilise BGP pour du routage L3 natif, plus performant. Cilium va encore plus loin en exploitant eBPF directement dans le kernel, remplaçant même kube-proxy.

🧠 À retenir : le DNS interne suit le format <service>.<namespace>.svc.cluster.local. Tes Pods se trouvent par nom, jamais par IP — les IPs changent à chaque redéploiement.

Commandes essentielles pour diagnostiquer

Avant de configurer quoi que ce soit, tu dois savoir observer. Voici les commandes réseau indispensables pour comprendre et débugger ton cluster.

Pour identifier le CNI actif et vérifier la topologie réseau du cluster :

# Quel CNI est installé ?
ls /etc/cni/net.d/
kubectl get pods -A | grep -E "calico|cilium|flannel|weave"

# CIDR attribué à chaque node
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.podCIDR}{"\n"}{end}'

Pour tester la connectivité entre Pods, le container netshoot est ton couteau suisse. Il embarque tous les outils réseau dont tu as besoin :

# Lancer un Pod de debug réseau
kubectl run netshoot --rm -it --image=nicolaka/netshoot -- /bin/bash

# Depuis le Pod netshoot :
nslookup mon-service.production.svc.cluster.local
curl -v http://backend-svc.production:8080/health
traceroute 10.244.2.15
tcpdump -i eth0 -n port 53   # Capturer le trafic DNS

⚠️ Attention : ping ne fonctionne pas toujours entre Pods. Certains CNI (Calico en mode eBPF, Cilium) bloquent ICMP par défaut. Teste toujours avec curl ou wget sur le port applicatif — c’est ce qui compte en prod.

Pour installer Cilium, le CNI le plus avancé, avec son outil d’observabilité Hubble :

helm repo add cilium https://helm.cilium.io/
helm install cilium cilium/cilium \
  --namespace kube-system \
  --set kubeProxyReplacement=true \
  --set hubble.enabled=true \
  --set hubble.relay.enabled=true \
  --set hubble.ui.enabled=true

# Vérifier l'installation
cilium status
cilium connectivity test

💡 Tip DevOps : si tu débutes, pars sur Calico — c’est le standard entreprise, bien documenté, il supporte les Network Policies nativement. Cilium est le bon choix quand tu veux du filtrage L7 ou de l’observabilité poussée. Flannel, c’est pour le lab uniquement.

Cas concret : sécuriser une app 3-tiers

Tu gères une application classique en production : Frontend → Backend → PostgreSQL. Sans Network Policy, le frontend peut taper directement dans la base de données — c’est une faille béante.

La stratégie est simple : default deny + whitelist explicite. On commence par tout bloquer, puis on ouvre uniquement les flux légitimes.

Étape 1 — Bloque tout le trafic entrant dans le namespace :

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

Étape 2 — Autorise uniquement les flux nécessaires. Le backend n’accepte que le frontend sur le port 8080, la DB n’accepte que le backend sur le port 5432 :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: backend-ingress
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - port: 8080
          protocol: TCP
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-ingress
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: postgresql
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: backend
      ports:
        - port: 5432
          protocol: TCP

Étape 3 — Contrôle le trafic sortant. La DB ne doit accéder qu’au DNS interne, rien d’autre :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-egress
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: postgresql
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector: {}
      ports:
        - port: 53
          protocol: UDP
        - port: 53
          protocol: TCP

🔥 Cas réel : chez un client e-commerce, cette stratégie a bloqué une tentative de reverse shell. Un container compromis essayait d’ouvrir une connexion sortante sur le port 4444 — l’egress policy l’a stoppé net. Le SOC a été alerté, l’incident contenu en minutes.

Pièges fréquents

Ces erreurs font perdre des heures à des équipes expérimentées. Apprends-les ici plutôt qu’en astreinte à 3h du matin.

  • Oublier le DNS dans les egress policies : tu bloques tout le trafic sortant et plus rien ne fonctionne. Tes Pods ne résolvent plus aucun nom de service. Toujours autoriser le port 53 UDP et TCP en egress — c’est le piège numéro un.

  • Network Policies sans CNI compatible : tu appliques des policies YAML, kubectl get netpol les affiche… mais rien n’est réellement filtré. Flannel seul ne supporte pas les Network Policies. Il faut un CNI qui les implémente (Calico, Cilium, Weave Net).

  • Confondre namespaceSelector et podSelector : sans namespaceSelector, ta policy ne matche que les Pods du même namespace. Pour autoriser du trafic cross-namespace (ex: monitoring → production), tu as besoin des deux sélecteurs combinés.

  • Tester avec ping au lieu de curl : ICMP et TCP sont deux protocoles différents. Une policy qui autorise le port 8080/TCP ne laisse pas passer le ping. Utilise toujours l’outil qui correspond au protocole applicatif.

⚠️ Attention : les Network Policies sont additives. Tu ne peux pas créer une policy qui annule une autre. Si deux policies s’appliquent au même Pod, c’est l’union des règles qui s’applique. Pense “whitelist qui s’empile”, pas “firewall avec priorités”.

Exercice pratique

Mets en place l’isolation réseau d’une app 3-tiers dans un namespace tp-network :

  1. Crée le namespace et déploie trois Pods : frontend (nginx), backend (httpd) et db (postgres).
  2. Expose chaque Pod via un Service ClusterIP.
  3. Applique un default deny ingress sur le namespace.
  4. Crée les Network Policies pour que seul le frontend joigne le backend (port 80) et seul le backend joigne la db (port 5432).
  5. Valide avec un Pod netshoot que le frontend ne peut pas joindre la db directement.

Pour valider ton travail, lance ces commandes :

# Ceci doit ÉCHOUER (timeout) — frontend ne joue pas directement avec la db
kubectl exec -it netshoot-frontend -- curl --connect-timeout 3 db-svc:5432

# Ceci doit FONCTIONNER — le frontend atteint le backend
kubectl exec -it netshoot-frontend -- curl --connect-timeout 3 backend-svc:80

Si le premier timeout et le second répond, ton isolation fonctionne. Tu as reproduit un pattern de sécurité réseau utilisé en production chez la majorité des entreprises qui tournent sur Kubernetes.

🧠 À retenir : le networking Kubernetes repose sur trois piliers — un modèle réseau plat sans NAT, un plugin CNI qui implémente ce modèle, et des Network Policies qui restreignent les flux. En production, la règle d’or est toujours la même : default deny + whitelist explicite. Commence par tout bloquer, puis ouvre uniquement ce qui est nécessaire. Pas l’inverse.


➡️ La suite : dans le prochain chapitre, on plonge dans les Service Mesh avec Istio et Linkerd pour aller encore plus loin dans le contrôle du trafic. 🚀

🖥️ Pratique sur ton propre serveur

Pour suivre Apprendre Kubernetes en conditions réelles, tu as besoin d'un VPS. DigitalOcean offre 200$ de crédit gratuit pour démarrer.

Obtenir 200$

Articles liés