Intro
Cette version française explique Kubernetes networking troubleshooting with practical examples avec le même objectif pratique que l article source : aider le lecteur à comprendre le contexte, les décisions à prendre et les points à vérifier avant de passer à l action.
Le réseau Kubernetes est puissant mais composé de plusieurs couches : résolution de noms, routage des Services, overlays de pods, iptables ou IPVS sur les nœuds, DNS de cluster, NetworkPolicy, pare-feux cloud ou on-prem. Chacune influence le trajet des paquets. Quand ça casse, deviner est lent et risqué. Ce guide propose une méthode sûre et reproductible pour isoler les pannes, valider les résultats attendus et restaurer rapidement avec un minimum de perturbations. Vous y trouverez des commandes concrètes, des workloads de test contrôlés et des options de rollback.
Ce que vous allez obtenir :
- Un court inventaire déployable une fois et réutilisable.
- Un namespace de test sûrisant et un écho HTTP minimal pour sonder les chemins courants.
- Une séquence de diagnostic du DNS jusquà pod, Service, nœud et egress.
- Des sorties attendues, modes défaillants et actions de restauration ciblées.
- Une checklist opérationnelle pour un usage régulier.
Portée : on se concentre sur le dépannage, sans imposer un CNI précis (Calico, Cilium, Flannel, etc.). Les exemples montrent comment interroger celui que vous exécutez.
Version et inventaire d'environnement
Avant tout changement, capturez l'état courant. Cela prévient les erreurs de diagnostic et facilite un rollback rapide.
Prérequis :
- Accès kubectl en lecture sur tous les namespaces et kube-system.
- Accès SSH optionnel aux nœuds pour des vérifications en lecture seule (listes iptables, routes). Si vous n'y avez pas accès, ignorez ces étapes.
Capture des versions et modes :
kubectl version -o yaml | sed -n '1,80p'
kubectl cluster-info
kubectl get nodes -o wide
kubectl get pods -A -o wide
kubectl -n kube-system get cm kube-proxy -o yaml | grep -i mode -n || true
kubectl -n kube-system get pods -l k8s-app=kube-dns
kubectl -n kube-system get svc -l k8s-app=kube-dns -o wide || kubectl -n kube-system get svc -l k8s-app=coredns -o wide
Si vous avez un accès nœud, capturez routes et pare-feu en mode lecture seule :
# Sur un nœud (lecture seule)
sudo ip route
sudo iptables -S | head -n 50
sudo iptables -L -n | head -n 50
# Si IPVS est utilisé
sudo ipvsadm -Ln 2>/dev/null | head -n 50 || true
Enregistrez le CNI et son statut :
kubectl -n kube-system get pods -o wide | egrep -i 'calico|cilium|flannel|weave|antrea' || true
kubectl -n kube-system logs deploy/coredns --tail=100 || kubectl -n kube-system logs -l k8s-app=kube-dns --tail=100
Astuce : notez les MTU (interfaces nœud et config CNI). Un mauvais alignement MTU cause souvent des échecs intermittents ou sur gros paquets.
Chemin de configuration sûrisé
Utilisez un namespace temporaire et des workloads minimaux supprimables rapidement.
Principes :
- Regroupez tous les tests dans un namespace, par exemple net-test.
- Privilégiez dababord les commandes non intrusives.
- Si vous ajoutez des politiques ou routes pour tester, documentez et prévoyez leur retrait.
Créez le namespace de test et deux apps écho : un HTTP, plus un pod client pour les tests.
kubectl create namespace net-test
# Serveur HTTP écho et Service (exemple construit)
cat <<'YAML' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: echo-a
namespace: net-test
labels:
app: echo-a
spec:
containers:
- name: http-echo
image: hashicorp/http-echo:0.2.3
args: ['-text=hello-from-echo-a']
ports:
- containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
name: echo-a
namespace: net-test
spec:
selector:
app: echo-a
ports:
- name: http
port: 80
targetPort: 5678
YAML
# Pod de test busybox pour curl, nslookup, ping
kubectl -n net-test run net-debug --image=busybox:1.36 --restart=Never -- sleep 36000
kubectl -n net-test wait --for=condition=ready pod/echo-a --timeout=90s || true
kubectl -n net-test get pods -o wide
Résultats attendus :
- Le pod echo-a est Running et Ready ; le Service a une ClusterIP.
- Le pod net-debug est Running.
Rollback : pour tout retirer : kubectl delete ns net-test.
Vérifications et diagnostics
Progressez du plus simple au plus exigeant. Arrêtez-vous au premier saut en panne.
1) Basiques DNS dans le cluster
Depuis net-debug, testez la découverte de Service et le DNS de cluster.
# Entrer dans le pod
kubectl -n net-test exec -it net-debug -- sh
# Dans le pod
nslookup kubernetes.default.svc.cluster.local
nslookup echo-a.net-test.svc.cluster.local
Attendus : les deux noms résolvent en ClusterIP. En cas défaut : vérifiez l'état et les logs de CoreDNS, et le resolv.conf du pod.
# Hors du pod
kubectl -n kube-system get pods -l k8s-app=kube-dns -o wide || kubectl -n kube-system get pods -l k8s-app=coredns -o wide
kubectl -n kube-system logs -l k8s-app=kube-dns --tail=200 || kubectl -n kube-system logs -l k8s-app=coredns --tail=200
kubectl -n net-test exec net-debug -- cat /etc/resolv.conf
Signaux typiques : SERVFAIL ou timeout : service DNS injoignable ou plugins CoreDNS mal configurés. NXDOMAIN pour des Services : suffixes de recherche ou plugin Kubernetes.
2) Chemin Pod vers Service (ClusterIP)
Depuis net-debug, testez via DNS puis via l'IP du Service.
wget -qO- http://echo-a
wget -qO- http://<ECHO_A_CLUSTER_IP>
Attendus : réponse texte : hello-from-echo-a. Si DNS ok mais IP échoue : règles kube-proxy ou routage CNI potentiellement rompus.
kubectl -n kube-system get cm kube-proxy -o yaml | grep -i mode -n || true
# Sur un nœud (lecture seule)
sudo iptables-save | egrep 'KUBE-SVC|KUBE-SEP' | head -n 20 || true
sudo ipvsadm -Ln | head -n 20 || true
3) Connectivité Pod à Pod (même nœud et inter-nœuds)
Récupérez l'IP du pod echo-a puis ping et HTTP direct.
kubectl -n net-test get pod -o wide -l app=echo-a
# Dans net-debug
PING_IP=$(kubectl -n net-test get pod -l app=echo-a -o jsonpath='{.items[0].status.podIP}')
ping -c2 $PING_IP || true
wget -qO- http://$PING_IP:5678
Attendus : ICMP peut être bloqué, donc l'échec de ping n'est pas conclusif. L'HTTP doit réussir ; sinon, suspectez CNI, NetworkPolicy ou routes.
4) Contrôle des NetworkPolicy
kubectl -n net-test get networkpolicy
Pour valider l'effet d'une politique, appliquez une default-deny puis une autorisation ciblée, puis revenez en arrière.
# Default deny ingress (exemple construit)
cat <<'YAML' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: net-test
spec:
podSelector: {}
policyTypes:
- Ingress
YAML
# Autoriser net-debug vers echo-a
cat <<'YAML' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-debug-to-echo
namespace: net-test
spec:
podSelector:
matchLabels:
app: echo-a
ingress:
- from:
- podSelector:
matchLabels:
run: net-debug
YAML
Attendus : avec default-deny, l'HTTP depuis net-debug vers echo-a doit expirer. Avec la règle d'autorisation, ça réussit à nouveau.
Rollback :
kubectl -n net-test delete networkpolicy default-deny allow-debug-to-echo --ignore-not-found
5) NodePort et accès externe
Exposez en NodePort et testez depuis l'extérieur du cluster.
kubectl -n net-test expose pod echo-a --type=NodePort --name=echo-a-nodeport --port=80 --target-port=5678
kubectl -n net-test get svc echo-a-nodeport -o wide
Depuis un poste ou un autre nœud :
curl -sS http://NODE_IP:NODEPORT
Si ça échoue alors que ClusterIP fonctionne : vérifiez le pare-feu nœud ou les security groups pour la plage NodePort par défaut 30000-32767 en TCP.
6) Egress vers Internet
Depuis net-debug, testez DNS externe et HTTP.
nslookup example.com
wget -qO- https://ifconfig.me || wget -qO- http://ifconfig.me || true
Si le DNS Internet échoue mais le DNS de cluster fonctionne : forwarders CoreDNS ou résolveurs upstream bloqués. Si l'HTTP sortant échoue : contrôlez NAT, passerelles egress ou tables de routage cloud.
7) MTU et fragmentation
Un MTU inadéquat entre overlay et hôtes cause des pertes silencieuses sur gros paquets.
# Choisissez une IP externe joignable, ex. 1.1.1.1
ping -s 1472 -M do -c 2 1.1.1.1 || true
ping -s 1200 -M do -c 2 1.1.1.1 || true
Attendus : un gros payload peut échouer alors qu'un plus petit passe. Alignez la MTU entre interfaces nœud et overlay CNI.
8) Sanity check de la configuration CoreDNS
kubectl -n kube-system get configmap coredns -o yaml
Cherchez : boucles ou réécritures lourdes, résolveurs upstream injoignables, cache trop agressif.
9) Observabilité par événements et logs
kubectl get events -A --sort-by=.lastTimestamp | tail -n 30
kubectl -n kube-system logs -l k8s-app=kube-proxy --tail=200
# Pour votre CNI, exemples de sélecteurs (peuvent différer)
kubectl -n kube-system logs -l k8s-app=calico-node --tail=200 || true
kubectl -n kube-system logs -l k8s-app=cilium --tail=200 || true
Chemins réseau courants et points de contrôle
| Chemin | Point de sonde | Composants principaux | Zone de correctif typique |
|---|---|---|---|
| Pod -> Service ClusterIP | Pod de test | kube-proxy, routage CNI | Règles kube-proxy, disponibilité CNI |
| Pod -> Pod (même nœud) | Pod de test | veth/bridge CNI | Sandbox de pod, CNI, policy |
| Pod -> Pod (inter-nœuds) | Pod de test | Overlay CNI, routes nœuds | Routage nœud, MTU, démon CNI |
| Pod -> Internet (egress) | Pod de test | NAT/egress GW, routes | Passerelles NAT, pare-feu, egress policy |
| Externe -> NodePort | Poste externe | Pare-feu nœud, kube-proxy | Pare-feu nœud, security groups |
Modes de panne et restauration
Associez symptômes, cause probable, vérification, action et rollback. Exemples typiques :
| Symptôme | Cause probable | Vérification | Restauration | Rollback |
|---|---|---|---|---|
| DNS de Service en timeout | CoreDNS down ou injoignable | kubectl -n kube-system get pods -l k8s-app=coredns | Redémarrer ou scaler CoreDNS ; vérifier l'IP du Service DNS | Rétablir la ConfigMap précédente |
| NXDOMAIN sur nom de Service | Suffixes ou plugin | kubectl -n net-test exec net-debug -- cat /etc/resolv.conf | Corriger le suffixe de recherche ; plugins CoreDNS | Restaurer la ConfigMap |
| ClusterIP échoue, IP du pod OK | Tables kube-proxy cassées | iptables-save | grep KUBE-SVC ou ipvsadm -Ln | Redémarrer le DaemonSet kube-proxy ; réconcilier la config | Annuler le changement kube-proxy | | Pod inter-nœuds KO | CNI non prêt ou MTU | Logs du démon CNI ; test MTU | Redémarrer le CNI ; aligner la MTU | Restaurer la config CNI | | NodePort injoignable | Pare-feu ou SG | Test externe curl NODE_IP:NODEPORT | Ouvrir la plage NodePort | Revenir sur la règle si inutile | | DNS egress OK, HTTP KO | NAT ou routes egress | wget -qO- ifconfig.me échoue | Corriger NAT/SNAT ; routes | Annuler si sans effet | | Pertes sur gros paquets | Fragmentation/MTU | ping -M do -s 1472 échoue | Baisser l'MTU overlay ; activer PMTUD | Revenir si inefficace |
Notes de rollback et sûreté
- Testez dabord dans le namespace net-test ou hors production.
- Sauvegardez ConfigMaps et iptables/IPVS avant édition :
kubectl -n kube-system get cm coredns -o yaml > coredns.bak.yaml
sudo iptables-save > iptables-$(date +%s).bak
- Pour les NetworkPolicy, supprimez-les pour revenir au comportement précédent :
kubectl -n net-test delete networkpolicy --all
- Pour les changements CNI, prévoyez drain et uncordon progressifs des nœuds, avec capacité à revenir à l'image ou la config précédente.
Ports et composants à connaeetre
Référentiel rapide pour firewall entre nœuds, plan de contrôle et pods (exemples à adapter) :
| Composant | Protocole/Port | Usage |
|---|---|---|
| kube-apiserver | TCP/6443 | API du plan de contrôle |
| kubelet | TCP/10250 | API kubelet nœud |
| CoreDNS | UDP/53, TCP/53 | DNS du cluster |
| Plage NodePort | TCP/30000-32767 | Accès externe aux Services |
| etcd (si géré soi-même) | TCP/2379-2380 | Stockage du plan de contrôle |
Récapitulatif de vérification
Après chaque correctif, rejouez les tests minimaux pour éviter les régressions :
- DNS dans les pods :
kubectl -n net-test exec net-debug -- nslookup echo-a.net-test.svc.cluster.local
- Routage ClusterIP :
kubectl -n net-test exec net-debug -- wget -qO- http://echo-a
- IP du pod en direct :
ECHO_IP=$(kubectl -n net-test get pod -l app=echo-a -o jsonpath='{.items[0].status.podIP}')
kubectl -n net-test exec net-debug -- wget -qO- http://$ECHO_IP:5678
- Optionnel externe :
curl -sS http://NODE_IP:NODEPORT || true
Attendu : toutes les étapes préalablement fautives passent.
Checklist d'exploitation
- Capturer l'inventaire
- kubectl version, cluster-info, nodes -o wide
- Mode kube-proxy ; pods et logs du CNI
- IP du Service DNS et statut CoreDNS
- Préparer un cadre sûrisé
- Créer le namespace net-test
- Déployer echo-a et net-debug
- Confirmer la readiness
- Exécuter les diagnostics dans l'ordre
- DNS in-pod : nslookup kubernetes et echo-a
- HTTP Service via DNS et ClusterIP
- Accès direct à l'IP du pod
- Présence et effet des NetworkPolicy
- NodePort depuis l'externe (si pertinent)
- DNS et HTTP egress
- MTU si les symptômes s'y prêtent
- Identifier le domaine de panne
- DNS vs proxy / routage vs policy vs firewall vs MTU
- Appliquer le correctif ciblé
- Éditer ConfigMap, policy, firewall ou CNI / kube-proxy selon besoin
- Vérifier et revenir si nécessaire
- Rejouer les tests cfaur
- Sans amélioration, annuler proprement le dernier changement
- Nettoyer
- Supprimer le namespace net-test
- Archiver logs et commandes pour retour d'expérience
Conclusion
Les problèmes de réseau Kubernetes sont maeetrisables avec une approche méthodique. Commencez par inventorier versions, modes et état du CNI. Utilisez un namespace temporaire et un workload minimal pour sonder DNS, routage de Service, chemins pod, NodePort et egress. Comparez aux résultats attendus pour repérer la couche fautive. Limitez et rendez réversibles vos changements, vérifiez immédiatement et revenez en arrière si nécessaire. Avec ces commandes, exemples et checklists, vous pourrez diagnostiquer et rétablir la connectivité Kubernetes avec confiance et répétabilité. Intégrez ce processus dans vos pratiques d'exploitation aux côtés d'outils comme Docker, Helm, GitLab CI/CD, Nginx, Ceph ou Prometheus selon votre contexte.