## Introduction Les problèmes réseau des volumes persistants (PV) Kubernetes peuvent se traduire par des réponses d'application lentes, des échecs de montage ou des services inaccessibles. Le dépannage exige une observation méthodique, une compréhension claire des interactions entre composants et des modifications sûres et réversibles. Ce guide fournit des étapes pratiques, illustrées par des exemples, pour diagnostiquer et résoudre les problèmes réseau liés aux volumes persistants dans Kubernetes, en mettant l'accent sur la résolution DNS, la connectivité des ports et le dépannage réseau de bout en bout. Nous allons suivre un scénario réaliste : un pod d'application ne peut pas accéder à un volume persistant servi sur le réseau, ce qui entraîne des échecs d'écriture intermittents. Vous apprendrez à recueillir les informations de version et d'environnement, à vérifier la configuration, à effectuer des diagnostics, à identifier les modes de défaillance et à suivre une liste de contrôle de récupération. Chaque étape inclut des commandes concrètes, les sorties attendues et les points de décision. L'objectif est la confiance opérationnelle : observer avant de changer, limiter le rayon d'impact, utiliser des espaces réservés pour les données sensibles et vérifier les résultats. Ce guide s'adresse aux développeurs, aux consultants DevOps et aux équipes techniques de startups qui gèrent des charges de travail avec état dans Kubernetes. Bien que l'accent soit mis sur le réseau des PV, nous aborderons les Persistent Volume Claims (PVC), les StatefulSets et les StorageClasses uniquement lorsqu'ils affectent la connectivité ou la récupération. ## Inventaire des versions et de l'environnement Avant de vous lancer dans le dépannage, établissez la version et la topologie exactes de votre cluster Kubernetes et du backend de stockage. Cela évite les suppositions erronées et vous aide à comparer avec les problèmes connus. Exécutez ces commandes et enregistrez la sortie avec un horodatage. ### Informations sur le cluster et les nœuds kubectl version --short kubectl get nodes -o wide Une sortie attendue est similaire à : Client Version: v1.28.2 Server Version: v1.28.2 NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME node-1 Ready control-plane 30d v1.28.2 10.0.0.11 Ubuntu 22.04.3 LTS 5.15.0-86-generic containerd://1.7.11 node-2 Ready 30d v1.28.2 10.0.0.12 Ubuntu 22.04.3 LTS 5.15.0-86-generic containerd://1.7.11 Notez la version de Kubernetes (par exemple, 1.28) et le runtime de conteneurs (containerd). Les détails du plugin réseau comptent ; par exemple, avec Calico : kubectl get pods -n kube-system | grep -E 'calico|kube-proxy' Sortie attendue : calico-node-abcde 1/1 Running 0 30d calico-kube-controllers-12345 1/1 Running 0 30d kube-proxy-xyz1 1/1 Running 0 30d ### Informations sur le backend de stockage Identifiez la StorageClass et le fournisseur utilisé par votre PV. Supposons que vous utilisiez NFS pour un réseau de stockage partagé. Listez les StorageClasses : kubectl get storageclass Sortie attendue : NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE nfs-client (default) nfs.csi.k8s.io Delete Immediate true 60d Inspectez ensuite les détails du PV et du PVC : kubectl get pv kubectl get pvc -n application-namespace Exemple de sortie : NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-38b7f2a3-4c5d-4e6f-8a1b-9c0d1e2f3a4b 20Gi RWO Delete Bound app/data-pvc nfs-client 15d NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE data-pvc Bound pvc-38b7f2a3-4c5d-4e6f-8a1b-9c0d1e2f3a4b 20Gi RWO nfs-client 15d Enregistrez le point de terminaison du serveur NFS si vous utilisez NFS : kubectl describe pv pvc-38b7f2a3-4c5d-4e6f-8a1b-9c0d1e2f3a4b | grep -A5 'Source:' Extrait de sortie attendu : Source: Type: NFS (an NFS mount that lasts the lifetime of a pod) Server: 192.168.1.100 Path: /exports/data ReadOnly: false Cela vous indique le point de terminaison réseau que vos pods doivent atteindre. Si l'adresse IP du serveur NFS est erronée ou injoignable, tout le réseau des PV échoue. ### Vue d'ensemble des pods et des charges de travail Vérifiez les pods qui utilisent le PVC : kubectl get pods -n application-namespace -o wide Exemple : NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES app-db-0 1/1 Running 4 15d 10.244.2.55 node-2 app-web-7b9c8d5f6-abcde 1/1 Running 0 15d 10.244.1.89 node-1 Remarquez les redémarrages sur app-db-0 ; cela peut indiquer une connectivité de stockage intermittente. ### Observer sans intervenir À ce stade, n'exécutez que des commandes en lecture seule. Évitez les modifications ou suppressions jusqu'à ce que vous compreniez l'état actuel. Capturez la sortie des commandes suivantes pour une comparaison ultérieure : kubectl describe pod app-db-0 -n application-namespace kubectl logs app-db-0 -n application-namespace --tail=50 Si le pod est en boucle de crash, utilisez --previous : kubectl logs app-db-0 -n application-namespace --previous Cet inventaire vous donne une base de référence. Passons maintenant à des vérifications de configuration sûres.
Question rapide 1 sur 2 Quelle commande affiche le point de terminaison du serveur NFS pour un PersistentVolume ? (En supposant que le PV utilise le type NFS) - kubectl get pv - kubectl describe pv | grep -A5 'Source:' - kubectl get storageclass - kubectl get pvc Valider La commande « kubectl describe pv » avec un grep pour « Source: » affiche les détails du serveur NFS et du chemin pour le PersistentVolume, comme indiqué dans l'extrait de sortie attendu dans la référence. ## Chemin de configuration sûr Le chemin de configuration sûr garantit que vous effectuez des modifications minimales et bien comprises. Pour le réseau des PV, concentrez-vous sur la StorageClass, le PVC et les configurations de montage du pod. ### Inspecter la StorageClass Pour NFS, vous pouvez avoir une StorageClass personnalisée avec des options de montage qui affectent le comportement réseau. Affichez le YAML : kubectl get storageclass nfs-client -o yaml Champs clés : apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-client provisioner: nfs.csi.k8s.io parameters: server: 192.168.1.100 share: /exports mountOptions: - nfsvers=4.1 - hard - timeo=600 - retrans=2 reclaimPolicy: Delete volumeBindingMode: Immediate Vérifiez que nfsvers correspond aux capacités du serveur NFS. Une version incompatible (par exemple, le serveur ne prend en charge que NFSv3, mais le client demande la 4.1) provoque des échecs de montage ou de mauvaises performances. De plus, l'option de montage hard signifie que le pod se bloquera indéfiniment en cas de partition réseau ; soft peut être préférable pour une détection de défaillance plus rapide, mais peut entraîner une corruption des données. Décidez en fonction de la tolérance de la charge de travail. ### Vérification du PVC et du montage du pod Vérifiez que le PVC a les bons modes d'accès et qu'il est lié : kubectl get pvc data-pvc -n application-namespace -o yaml Recherchez accessModes : accessModes: - ReadWriteOnce Si votre application a besoin d'un stockage partagé (par exemple, plusieurs pods en lecture/écriture), vous avez besoin de ReadWriteMany . Utiliser ReadWriteOnce avec plusieurs réplicas peut entraîner qu'un seul nœud monte avec succès, ce qui provoque des erreurs réseau pour les autres. Inspectez le montage de volume du pod et les indicateurs de lecture seule : kubectl get pod app-db-0 -n application-namespace -o yaml | grep -A10 'volumeMounts:' Extrait attendu : volumeMounts: - mountPath: /var/lib/data name: data readOnly: false Assurez-vous que mountPath correspond au chemin attendu par l'application et qu'il n'est pas en lecture seule lorsque des écritures sont nécessaires. ### Plus petite modification justifiée Si vous devez modifier une configuration (par exemple, ajouter l'option de montage soft ou changer la version NFS), mettez à jour la StorageClass avec un patch, mais testez d'abord dans un environnement hors production. Exemple de patch pour changer nfsvers de 4.1 à 4.0 : kubectl patch storageclass nfs-client --type='json' -p='[{"op": "replace", "path": "/mountOptions/0", "value": "nfsvers=4.0"}]' Vérifiez le changement : kubectl get storageclass nfs-client -o yaml | grep -A5 'mountOptions' Les nouveaux pods utiliseront l'option mise à jour. Les pods existants doivent être redémarrés pour prendre en compte les changements ; envisagez un redémarrage progressif du StatefulSet. ### Test local avec port-forward Avant d'impliquer des services réseau externes, testez la connectivité localement. Pour un pod qui sert un protocole de fichier réseau ou une API, utilisez kubectl port-forward : kubectl port-forward pod/app-db-0 -n application-namespace 2049:2049 Ensuite, depuis un autre terminal, testez le montage NFS avec des outils locaux : sudo mount -t nfs -o nfsvers=4.1 localhost:/exports/data /mnt/test Si cela échoue, le problème se situe à l'intérieur du cluster, pas dans le réseau externe. ### Vérification sans LoadBalancer Évitez de créer un service LoadBalancer juste pour tester. Utilisez plutôt un service NodePort temporaire ou port-forward. Cela limite l'exposition et les coûts. ## Vérification et diagnostics Maintenant que la configuration est comprise, effectuez des diagnostics actifs pour isoler le problème réseau. ### Vérifications de la résolution DNS De nombreux problèmes réseau de PV proviennent de défaillances DNS, en particulier lorsque le serveur NFS est référencé par nom d'hôte. Tout d'abord, vérifiez les pods CoreDNS : kubectl get pods -n kube-system -l k8s-app=kube-dns Attendu : NAME READY STATUS RESTARTS AGE coredns-787d4945fb-abcde 1/1 Running 0 30d coredns-787d4945fb-fghij 1/1 Running 0 30d Testez la résolution DNS depuis l'intérieur d'un pod. Exécutez nslookup dans le pod de l'application (ou un pod de débogage) : kubectl exec -it app-db-0 -n application-namespace -- nslookup nfs-server.example.com Sortie attendue : Server: 10.96.0.10 Address: 10.96.0.10#53 Name: nfs-server.example.com Address: 192.168.1.100 Si vous obtenez server can't find nfs-server.example.com: NXDOMAIN , le nom d'hôte n'est pas dans le DNS. Vérifiez si vous devez ajouter une entrée à /etc/hosts via hostAliases dans la spécification du pod ou corriger le DNS externe. ### Tests de connectivité des ports NFS utilise généralement le port TCP/UDP 2049. Testez la connectivité depuis le pod vers le serveur NFS : kubectl exec -it app-db-0 -n application-namespace -- nc -zvw3 192.168.1.100 2049 Si nc n'est pas installé, utilisez bash avec /dev/tcp : kubectl exec -it app-db-0 -n application-namespace -- bash -c 'echo > /dev/tcp/192.168.1.100/2049 && echo open || echo closed' Sortie de succès attendue : open . Si fermé, vérifiez les NetworkPolicies, les règles de pare-feu ou l'état du service du serveur NFS. Vérifiez les NetworkPolicies qui pourraient bloquer la sortie vers le serveur NFS : kubectl get networkpolicies -n application-namespace Si une politique existe, inspectez-la : kubectl describe networkpolicy allow-nfs -n application-namespace Assurez-vous que la politique autorise la sortie vers 192.168.1.100/32 sur le port 2049. ### Vérifications des endpoints et des services Si le stockage est exposé via un Service Kubernetes (par exemple, un serveur NFS exécuté en tant que pod), vérifiez les endpoints : kubectl get endpoints nfs-service -n storage-namespace Attendu : NAME ENDPOINTS AGE nfs-service 10.244.2.10:2049 20d Si les endpoints sont vides, vérifiez que le sélecteur du service correspond aux étiquettes du pod. ### Journaux et événements Vérifiez les événements du pod pour les erreurs de montage : kubectl describe pod app-db-0 -n application-namespace | tail -30 Recherchez des messages comme : Warning FailedMount 2m (x12 over 30m) kubelet MountVolume.SetUp failed for volume "pvc-38b7f2a3..." : mount failed: exit status 32 Mounting command: mount Mounting arguments: -t nfs 192.168.1.100:/exports/data /var/lib/kubelet/pods/.../volumes/kubernetes.io~nfs/pvc-38b7f2a3... Output: mount.nfs: access denied by server while mounting 192.168.1.100:/exports/data Cela indique un problème de permission d'exportation NFS ou une adresse IP client incorrecte dans la configuration d'exportation. Vérifiez les journaux de kubelet sur le nœud où le pod s'exécute (node-2) : journalctl -u kubelet -n 50 --no-pager | grep -i 'nfs\|mount' Cela peut révéler des délais d'attente réseau ou des erreurs RPC. ### Débogage du plugin réseau Si vous utilisez Calico, vérifiez les journaux de calico-node : kubectl logs -n kube-system calico-node-abcde --tail=50 | grep -i 'nfs\|drop\|deny' Recherchez les paquets abandonnés en raison de la politique. Vous pouvez également utiliser calicoctl pour vérifier l'évaluation de la politique réseau. ### Pod de débogage temporaire Exécutez un pod temporaire avec des outils réseau pour isoler si le problème est spécifique au pod ou à l'échelle du cluster : apiVersion: v1 kind: Pod metadata: name: debug-network namespace: application-namespace spec: containers: - name: debug image: nicolaka/netshoot command: ["sleep", "3600"] restartPolicy: Never Créez-le : kubectl apply -f debug-pod.yaml Testez ensuite le montage NFS manuellement dans le pod de débogage : kubectl exec -it debug-network -n application-namespace -- mount -t nfs 192.168.1.100:/exports/data /mnt Si cela fonctionne mais que le pod d'application échoue, le problème peut provenir du contexte de sécurité du pod ou de la configuration du montage de volume.
Question rapide 2 sur 2 Selon l'article, quelle est une pratique recommandée avant d'effectuer des modifications pendant le dépannage ? - Redémarrer immédiatement tous les pods - Effectuer plusieurs modifications à la fois pour accélérer le processus - Observer et capturer l'état actuel avant d'intervenir - Supprimer et recréer le PersistentVolumeClaim
L'article insiste sur « observer avant de modifier » et sur la capture de l'état actuel à l'aide de commandes en lecture seule avant d'effectuer des modifications, comme indiqué dans la section « Observing Without Intervening ».
## Modes de défaillance et récupération Comprendre les modes de défaillance courants accélère la récupération. Voici des scénarios spécifiques et comment les résoudre. ### Mode de défaillance 1 : Serveur NFS injoignable Symptômes : les journaux du pod affichent I/O error , le montage se bloque, ou des événements FailedMount avec connection timed out . Diagnostic : kubectl exec -it app-db-0 -n application-namespace -- ping -c 3 192.168.1.100 Si le ping échoue, vérifiez le routage réseau : les nœuds du cluster peuvent-ils atteindre le sous-réseau du serveur NFS ? Si le serveur NFS est sur un réseau différent, assurez-vous que les tables de routage et les règles de pare-feu autorisent le trafic. Récupération : corrigez la connectivité réseau (par exemple, ajoutez une route ou une règle de pare-feu), puis redémarrez le pod : kubectl delete pod app-db-0 -n application-namespace Attendez que le StatefulSet le recrée. ### Mode de défaillance 2 : Échec de résolution DNS pour le nom d'hôte du serveur NFS Symptômes : erreurs de montage avec Unable to resolve host ou server not found . Si l'adresse IP du serveur NFS a changé mais que le DNS n'est pas mis à jour. Diagnostic : confirmez avec nslookup (voir plus tôt). Récupération : mettez à jour l'enregistrement DNS ou, comme solution immédiate, utilisez l'adresse IP dans la spécification du PV. Pour changer le serveur NFS dans le PV : kubectl patch pv pvc-38b7f2a3-4c5d-4e6f-8a1b-9c0d1e2f3a4b --type='json' -p='[{"op": "replace", "path": "/spec/nfs/server", "value": "192.168.1.101"}]' Supprimez ensuite le pod pour le remonter : kubectl delete pod app-db-0 -n application-namespace ### Mode de défaillance 3 : Permissions d'exportation refusées Symptômes : access denied by server dans la sortie de montage (voir plus tôt). Diagnostic : comparez la configuration d'exportation NFS sur le serveur. L'exportation doit autoriser les adresses IP des nœuds du pod ou la plage CIDR du réseau du cluster (par exemple, 10.244.0.0/16 pour Calico). Exemple d'exportation sur le serveur NFS /etc/exports : /exports/data 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash) Si vos pods du cluster utilisent un CIDR différent (par exemple, 10.244.0.0/16), le serveur NFS peut rejeter car l'adresse IP client provient de cette plage. Mettez à jour l'exportation pour inclure ce CIDR : /exports/data 10.244.0.0/16(rw,sync,no_subtree_check,no_root_squash) Exécutez ensuite exportfs -ra sur le serveur NFS. Aucun redémarrage de pod n'est nécessaire si le montage réussit à la prochaine tentative. ### Mode de défaillance 4 : NetworkPolicy bloquante Symptômes : le pod peut atteindre le serveur NFS depuis d'autres pods mais pas depuis son propre namespace, ou la connectivité échoue après l'application d'une NetworkPolicy. Diagnostic : passez en revue les NetworkPolicies comme décrit. Utilisez kubectl describe networkpolicy pour voir les règles. Si une politique de refus global est présente, assurez-vous d'avoir des règles d'autorisation pour NFS. Récupération : appliquez une nouvelle NetworkPolicy autorisant la sortie vers le serveur NFS : apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-nfs-egress namespace: application-namespace spec: podSelector: matchLabels: app: db policyTypes: - Egress egress: - to: - ipBlock: cidr: 192.168.1.100/32 ports: - protocol: TCP port: 2049 - protocol: UDP port: 2049 Appliquez et testez la connectivité. ### Mode de défaillance 5 : Inadéquation des options de montage Symptômes : le montage réussit mais les performances sont médiocres, ou des délais d'attente fréquents. Une inadéquation de nfsvers entraîne un repli vers une version plus ancienne ou un échec. Diagnostic : vérifiez les options de montage de la StorageClass et les versions prises en charge par le serveur NFS. Utilisez rpcinfo -p 192.168.1.100 | grep nfs (depuis un nœud avec accès) pour lister les versions. Récupération : mettez à jour la StorageClass avec le nfsvers correct et redémarrez les pods. ## Liste de contrôle des opérations Utilisez cette liste de contrôle pour vous assurer de couvrir tous les aspects lors du dépannage réseau des PV.
ÉtapeActionCommande ou vérificationRésultat attendu
1Enregistrer la version du cluster et les nœudskubectl version --short, kubectl get nodes -o wideTous les nœuds Ready, version cohérente
2Identifier le fournisseur de stockage et le backendkubectl get storageclass, kubectl get pvLe fournisseur correspond à l'intention (par exemple, nfs.csi.k8s.io), PV Bound
3Vérifier la joignabilité du serveur NFS depuis le nœudping -c 3 192.168.1.100 depuis le nœud0 % de perte de paquets
4Vérifier le port NFS ouverttelnet 192.168.1.100 2049 ou nc -zvConnexion réussie
5Vérifier la résolution DNS dans le podkubectl exec <pod> -- nslookup nfs-server.example.comRenvoie la bonne IP
6Tester le montage NFS manuellement dans un pod de débogagemount -t nfs 192.168.1.100:/exports/data /mnt dans le pod de débogageLe montage réussit sans erreur
7Examiner les événements du podkubectl describe pod <pod-name>Aucun avertissement FailedMount
8Vérifier les journaux de kubeletjournalctl -u kubelet -n 50 --no-pager sur le nœudAucune erreur de montage
9Inspecter les NetworkPolicieskubectl get networkpolicies -n <ns>Les règles autorisent le trafic NFS si nécessaire
10Confirmer l'état du PV/PVCkubectl get pv,pvc -n <ns>Bound et disponible
11Valider les options de montagekubectl get storageclass <name> -o yamlLes options correspondent aux capacités du serveur
12Effectuer une modification test contrôléePatcher la StorageClass ou le PV, redémarrer le pod, vérifier le montageAucun effet indésirable
13Documenter les conclusions et les étapes de récupérationMettre à jour le runbookNotes claires
### Exemple d'entrée de runbook Après avoir résolu un problème (par exemple, permission d'exportation NFS refusée), ajoutez une entrée à votre runbook : ## Incident : le montage du PVC a échoué avec "access denied by server" Date : 2025-04-02 Cluster : prod-shared Namespace : application-namespace PV : pvc-38b7f2a3-4c5d-4e6f-8a1b-9c0d1e2f3a4b Symptômes : le pod app-db-0 redémarre, l'événement affiche mount.nfs access denied. Cause racine : l'exportation NFS du serveur n'autorisait que 192.168.1.0/24, mais le CIDR du réseau des pods est 10.244.0.0/16. Résolution : mise à jour de /etc/exports pour inclure 10.244.0.0/16, exécution d'exportfs -ra, redémarrage du pod. Vérification : le pod a redémarré avec succès, les écritures de l'application ont repris. ## Conclusion Le dépannage réseau des volumes persistants Kubernetes exige une approche structurée : inventorier l'environnement, vérifier la configuration, exécuter des diagnostics ciblés, comprendre les modes de défaillance et suivre une liste de contrôle de récupération. En utilisant les commandes et les exemples concrets de ce guide, vous pouvez rapidement déterminer si le problème réside dans le DNS, la connectivité des ports, les options de montage, les politiques réseau ou les permissions du backend. Observez toujours avant d'intervenir. Capturez l'état actuel, effectuez une petite modification à la fois et vérifiez le résultat. Gardez les données sensibles hors des journaux et des commandes en utilisant des espaces réservés et en les masquant lors du partage. Avec ces pratiques, vous réduirez les temps d'arrêt et améliorerez la fiabilité de vos applications avec état. Comme prochaine étape, choisissez une vérification à faible risque de la liste de contrôle des opérations, exécutez-la dans votre environnement et documentez le résultat. Au fil du temps, vous construirez un playbook de dépannage robuste pour le réseau des volumes persistants Kubernetes.