## Introduction

Lorsque les charges de travail Kubernetes perdent l'accès aux données persistantes, l'impact peut être grave : plantages d'applications, corruption de données, voire interruptions de service complètes. Les volumes persistants (PV) et les demandes de volume persistant (PVC) sont des abstractions qui découplent le stockage des pods, mais ils introduisent également une couche de complexité avec de nombreux points de défaillance potentiels. Ce guide aide les développeurs, les consultants DevOps et les équipes techniques de startups à diagnostiquer et corriger les erreurs les plus courantes des volumes persistants Kubernetes à l'aide d'étapes pratiques et reproductibles.

Nous mettons l'accent sur la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, utiliser des espaces réservés au lieu de secrets, vérifier le résultat et documenter les chemins de récupération. Chaque correctif inclut la commande ou le manifeste exact nécessaire, la sortie attendue et le signal qui confirme la résolution du problème. Les exemples supposent un cluster Kubernetes fonctionnel avec `kubectl` configuré, et nous notons les variations spécifiques au cloud.

## Inventaire des versions et de l'environnement

Avant de dépanner tout problème de volume persistant, confirmez votre environnement. Le comportement des PV a changé selon les versions de Kubernetes, notamment en ce qui concerne les classes de stockage, l'expansion des volumes et les pilotes CSI. Exécutez ces commandes en lecture seule et enregistrez les sorties :

```bash
kubectl version --short
kubectl get nodes -o wide
kubectl get sc   # classes de stockage
kubectl get pv,pvc -A
```

Exemple de sortie :
```
Client Version: v1.27.3
Server Version: v1.27.3
NAME                 STATUS   AGE
ip-10-0-1-23         Ready    45d
NAME                 PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
standard (default)   kubernetes.io/aws-ebs   Delete          Immediate           true                   45d
NAME                     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE
pvc-abc123              10Gi       RWO            Delete           Bound    default/myclaim   standard                30d
```

Éléments clés à vérifier :
- La version du cluster et les versions du pilote CSI ou du plugin intégré. Des versions incompatibles peuvent provoquer des échecs de montage.
- Les classes de stockage disponibles et leurs fournisseurs. Si votre PVC fait référence à une classe de stockage inexistante, le PVC reste en attente.
- Les PV et PVC existants et leur statut. Un PVC à l'état `Lost` indique que le PV sous-jacent est indisponible.

Pour les environnements cloud (AWS, GCP, Azure), assurez-vous que les pods du contrôleur cloud et du pilote CSI requis sont en cours d'exécution :
```bash
kubectl get pods -n kube-system | grep -E 'ebs|csi|cloud-controller'
```
Tous doivent être en état Running et Ready. Dans un cluster autogéré, vérifiez que le fournisseur de stockage (par exemple, NFS, Ceph, local) est installé et sain.

## Chemin de configuration sûr

Les erreurs de PV les plus courantes proviennent de PVC, de classes de stockage ou de sélecteurs de nœuds mal configurés. Commencez toujours par un manifeste minimal et augmentez progressivement la complexité pour isoler le problème.

### Exemple : PVC en attente en raison d'une classe de stockage manquante

Étant donné ce PVC :
```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: fast-ssd
```

Si aucune classe de stockage nommée `fast-ssd` n'existe, le PVC reste en attente. Vérifiez avec :
```bash
kubectl get pvc myclaim
kubectl describe pvc myclaim
```
Recherchez des événements :
```
Warning  ProvisioningFailed  5s (x3 over 15s)  persistentvolume-controller  storageclass.storage.k8s.io "fast-ssd" not found
```

Correctif : Créez la classe de stockage ou modifiez le PVC pour utiliser une classe existante. Voici une classe de stockage minimale pour les clusters sur site :
```yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-ssd
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
```
Après application, le PVC reste en attente jusqu'à ce qu'un pod l'utilise en raison de `WaitForFirstConsumer`. C'est attendu. Déployez un pod qui référence le PVC, puis il devrait se lier.

### Exemple de restauration sûre

Si un changement de configuration casse des charges de travail existantes, revenez immédiatement en arrière. Par exemple, si vous avez modifié un paramètre de classe de stockage et que les PVC ne parviennent pas à être provisionnés, restaurez le manifeste précédent :
```bash
kubectl apply -f previous-storageclass.yaml
kubectl get pvc -w
```
Conservez toujours des manifestes versionnés et évitez de modifier directement les ressources en direct avec `kubectl edit` pour les objets liés au stockage.

## Vérification et diagnostics

Supposons qu'un pod utilisant un PVC soit bloqué en `ContainerCreating` ou en `CrashLoopBackOff`. Utilisez ces commandes pour identifier le problème de volume.

### Étape 1 : Inspecter les événements du pod
```bash
kubectl describe pod mypod
```
Erreurs de volume typiques :
- `MountVolume.SetUp failed for volume "pvc-..." : mount failed`
- `Unable to attach or mount volumes: timed out waiting for the condition`
- `FailedMount` avec des détails sur le pilote ou le périphérique.

### Étape 2 : Vérifier le statut du PVC
```bash
kubectl get pvc
```
Si le statut est `Bound`, le PV est attaché. S'il est `Pending`, suivez les journaux de la classe de stockage et du fournisseur.

### Étape 3 : Consulter les journaux du pilote CSI (le cas échéant)
```bash
kubectl logs -n kube-system deployment/ebs-csi-controller -c csi-provisioner --tail=50
kubectl logs -n kube-system daemonset/ebs-csi-node -c ebs-csi-node --tail=50
```
Pour les plugins intégrés, consultez les journaux de kube-controller-manager et de kubelet.

### Étape 4 : Tester avec un pod de débogage
Montez le même PVC dans un pod simple (par exemple, busybox) et essayez d'écrire un fichier :
```bash
kubectl run -it --rm debug --image=busybox --restart=Never -- sh
# Dans le pod :
mount | grep /mnt
# Si le PVC est monté sur /mnt, testez l'écriture :
echo test > /mnt/testfile
ls -l /mnt
```
Si l'écriture échoue, cela peut être un problème de permissions ou un montage en lecture seule. Vérifiez la `persistentVolumeReclaimPolicy` du PV et les options de montage dans la spécification de votre pod.

## Pièges courants et comment les éviter

### Piège 1 : PVC bloqué en attente en raison de l'absence de PV correspondant
Lors de l'utilisation du provisionnement statique, un PVC ne se lie que s'il existe un PV disponible avec une capacité, des modes d'accès et une classe de stockage correspondants (si spécifiée). De nombreux utilisateurs s'attendent à un provisionnement automatique, mais sans fournisseur dynamique, rien ne se passe.

**Pourquoi cela arrive :** Le cluster n'a pas de classe de stockage avec un fournisseur, ou le PVC demande explicitement une classe de stockage inexistante.

**Comment éviter/récupérer :** Vérifiez `kubectl get pv` et `kubectl get storageclass`. Si vous vouliez une liaison statique, créez un PV manuellement avec des spécifications correspondantes. Exemple :
```yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-pv
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual
  hostPath:
    path: /mnt/data
```
Ensuite, référencez `storageClassName: manual` dans le PVC. Le PVC devrait se lier rapidement.

### Piège 2 : PVC bloqué en Terminating
Lors de la suppression d'un PVC, il peut rester bloqué en état Terminating si le pod qui l'utilise est encore en cours d'exécution, ou si le finaliseur ne peut pas se terminer.

**Pourquoi cela arrive :** Le PVC a un finaliseur `kubernetes.io/pvc-protection`, et le système attend qu'aucun pod ne l'utilise. Parfois, le pod est déjà supprimé mais le finaliseur reste en raison d'un problème de kubelet.

**Comment éviter/récupérer :** D'abord, assurez-vous qu'aucun pod n'utilise le PVC :
```bash
kubectl get pods -A -o json | jq '.items[] | select(.spec.volumes[]?.persistentVolumeClaim.claimName=="myclaim") | .metadata.name'
```
S'il n'y en a aucun, vous pouvez forcer la suppression en supprimant le finaliseur :
```bash
kubectl patch pvc myclaim -p '{"metadata":{"finalizers":null}}'
```
Soyez prudent : cela contourne les contrôles de sécurité et peut entraîner une perte de données si le volume est encore attaché.

### Piège 3 : Pod bloqué en raison d'une discordance entre l'affinité de nœud et la zone du volume
Sur les plateformes cloud, un PV est créé dans une zone de disponibilité spécifique. Si le pod est planifié sur un nœud dans une zone différente, le pod ne parvient pas à monter le volume.

**Pourquoi cela arrive :** La classe de stockage peut utiliser `volumeBindingMode: Immediate`, ce qui crée le PV dans la zone du premier nœud disponible, mais le pod est ensuite planifié ailleurs. Ou le pod a des sélecteurs de nœuds qui entrent en conflit avec la zone du PV.

**Comment éviter/récupérer :** Utilisez `volumeBindingMode: WaitForFirstConsumer` dans la classe de stockage pour que le PV soit créé dans la même zone que le pod. De plus, si votre pod doit s'exécuter sur des nœuds spécifiques, assurez-vous que ces nœuds sont dans la même zone que le PV, ou utilisez une planification consciente des zones avec `topologySpreadConstraints`.

Pour vérifier la zone d'un nœud :
```bash
kubectl get node <node-name> -o jsonpath='{.metadata.labels.topology\.kubernetes\.io/zone}'
```
Et la zone du PV (le cas échéant) :
```bash
kubectl get pv <pv-name> -o jsonpath='{.spec.nodeAffinity}'
```

## Modes de défaillance et récupération

Cette section couvre les scénarios de défaillance graves et les étapes de récupération.

### Statut du PV Lost
Un PV peut devenir `Lost` lorsque le stockage sous-jacent est supprimé ou inaccessible. Vérifiez :
```bash
kubectl get pv
kubectl describe pv <pv-name>
```
Récupération : Si le stockage est récupérable (par exemple, un volume EBS qui existe encore mais qui est détaché), rattachez-le manuellement via la console cloud ou recréez le PV avec le même ID de volume. Pour les PV dynamiques, la politique de récupération `Delete` signifie que le PV est supprimé automatiquement lorsque le PVC est supprimé ; si le PVC a été supprimé accidentellement, les données sont perdues sauf si vous avez des sauvegardes. Pour éviter cela, définissez `persistentVolumeReclaimPolicy: Retain` pour les données critiques, puis nettoyez manuellement plus tard.

### PVC lié à un mauvais PV
Si un PVC se lie à un PV plus petit ou incorrect, vous devez le dissocier. Supprimez le PVC, modifiez le `claimRef` du PV pour supprimer la liaison, puis recréez le PVC. Cependant, cela est risqué et peut entraîner une perte de données. Meilleure approche : utilisez des étiquettes et des sélecteurs dans le PVC pour cibler des PV spécifiques si vous utilisez le provisionnement statique.

### Corruption du système de fichiers ou montage en lecture seule
Si un pod signale un système de fichiers en lecture seule lors d'une tentative d'écriture, vérifiez le `securityContext` du pod et les options de montage du volume. Le PV peut être monté en lecture seule en raison d'une erreur. Obtenez les détails du pod :
```bash
kubectl describe pod <pod>
```
Recherchez `readOnly: true` dans la définition du volume. Sinon, vérifiez le mode du volume persistant. Vérifiez également que le système de fichiers n'est pas corrompu en exécutant `fsck` (si accessible) ou en montant le volume sur un pod de secours.

## Liste de contrôle des opérations

Utilisez cette liste de contrôle avant et après avoir apporté des modifications aux volumes persistants.

**Avant les modifications :**
- [ ] Lister tous les PV et PVC et noter leur statut : `kubectl get pv,pvc -A`
- [ ] Identifier les pods qui utilisent les volumes : `kubectl get pods -A -o json | jq '.items[] | select(.spec.volumes[]?.persistentVolumeClaim.claimName!="") | .metadata.name'`
- [ ] Vérifier la configuration de la classe de stockage et la santé du fournisseur.
- [ ] Noter la politique de récupération de chaque PV : `Retain` ou `Delete`.
- [ ] Assurer d'avoir une sauvegarde ou un instantané des volumes critiques.
- [ ] Si vous utilisez des volumes cloud, noter les ID de volume et les zones.
- [ ] Confirmer d'avoir les permissions pour modifier les PV/PVC et les classes de stockage.
- [ ] Pour toute suppression, d'abord s'assurer qu'aucun pod actif ne monte le volume.
- [ ] Tester les modifications dans un environnement de préproduction si possible.

**Après les modifications :**
- [ ] Vérifier que le statut du PVC devient `Bound` (si création nouvelle).
- [ ] Confirmer que les pods redémarrent correctement et peuvent lire/écrire.
- [ ] Exécuter un test d'écriture : `kubectl exec <pod> -- sh -c "echo test > /data/testfile && cat /data/testfile"`
- [ ] Surveiller les événements pour tout avertissement `FailedMount` ou `FailedAttachVolume`.
- [ ] Vérifier les journaux du fournisseur de stockage pour les erreurs.
- [ ] Documenter le changement et tout nouveau nom de PVC/PV.

**Propriété et cadence de révision :** Attribuez à un seul administrateur de stockage ou ingénieur de plateforme (par exemple, « Priya Shah, responsable ingénierie ») la responsabilité d'approuver tout changement aux classes de stockage, aux politiques de récupération des PV ou aux mises à niveau des pilotes CSI. Passez en revue l'inventaire et la santé des PV/PVC chaque semaine lors d'une courte réunion opérationnelle, en vous concentrant sur toute ressource `Pending`, `Lost` ou `Terminating` datant de plus de 24 heures.

## Conclusion

Les erreurs de volumes persistants Kubernetes peuvent être intimidantes, mais une approche systématique avec les bonnes commandes et une compréhension des abstractions sous-jacentes résout la plupart des problèmes rapidement. Ce guide a fourni un inventaire des diagnostics essentiels, des pratiques de configuration sûres, des pièges courants et des étapes de récupération. N'oubliez pas de toujours observer d'abord, de changer une variable à la fois et de vérifier avec des tests concrets.

Pour approfondir, explorez la documentation officielle de Kubernetes sur les volumes persistants, les classes de stockage et les pilotes CSI. Pratiquez ces étapes dans un cluster de test pour gagner en confiance. Un flux de travail fiable rend les défaillances visibles, protège les données sensibles, limite le rayon d'impact et définit la récupération avant qu'un incident ne vous force la main.
