Introduction
Les volumes Kubernetes fournissent un stockage qui survit aux conteneurs et aux pods individuels. Comprendre comment les volumes, les PersistentVolumes (PV), les PersistentVolumeClaims (PVC) et les StorageClasses interagissent est essentiel pour exécuter des charges de travail avec état de manière fiable. Cet article parcourt l'architecture avec des exemples pratiques, des commandes et des étapes de dépannage pour vous aider à passer d'un problème à une solution vérifiée.
Nous nous concentrons sur la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, éviter les secrets codés en dur, vérifier chaque étape et documenter les chemins de récupération. Que vous soyez développeur, consultant DevOps ou membre d'une équipe de startup, ce guide relie les concepts fondamentaux à des commandes réelles, des sorties attendues, des signaux d'échec et des décisions de récupération.
Composants principaux et flux de données
Les volumes Kubernetes ne sont pas de simples montages de disque ; ils constituent un système à plusieurs composants. Les principaux éléments sont :
- Volume : Un répertoire accessible aux conteneurs d'un pod, défini dans la spécification du pod. Il peut être soutenu par de nombreuses sources : emptyDir, hostPath, disques cloud, NFS, etc.
- PersistentVolume (PV) : Une ressource de stockage au niveau du cluster provisionnée par un administrateur ou dynamiquement via une StorageClass. Son cycle de vie est indépendant de tout pod.
- PersistentVolumeClaim (PVC) : Une demande de stockage d'un utilisateur. Elle spécifie la taille, les modes d'accès et éventuellement une StorageClass. Le plan de contrôle lie un PVC à un PV correspondant.
- StorageClass : Définit le provisionneur et les paramètres pour le provisionnement dynamique de volumes. Elle permet aux utilisateurs de demander du stockage sans connaître l'infrastructure sous-jacente.
- Container Storage Interface (CSI) : Une norme pour exposer les systèmes de stockage aux orchestrateurs de conteneurs. La plupart des pilotes modernes sont basés sur CSI.
Le flux de données pour le provisionnement dynamique est :
- Un utilisateur crée un PVC avec un nom de StorageClass.
- Le provisionneur de la StorageClass crée un PV qui correspond à la demande.
- Kubernetes lie le PVC au PV nouvellement créé.
- Le pod utilisant le PVC monte le PV dans ses conteneurs via le kubelet du nœud.
Pour le provisionnement statique, un administrateur pré-crée des PV, et les PVC se lient au premier PV correspondant.
Inventaire de la version et de l'environnement
Avant de travailler avec les volumes, confirmez votre version de Kubernetes et les pilotes de stockage. Utilisez kubectl version --short ou kubectl version pour obtenir les versions client et serveur. Par exemple :
$ kubectl version --short
Client Version: v1.28.2
Server Version: v1.28.4
Vérifiez quels pilotes CSI sont installés dans votre cluster. La plupart des clusters gérés ont des pilotes spécifiques au cloud. Vous pouvez lister les pilotes CSI avec :
kubectl get csidrivers
Exemple de sortie :
NAME ATTACHREQUIRED PODINFOONMOUNT STORAGECAPACITY TOKENREQUESTS REQUIRESREPUBLISH
pd.csi.storage.gke.io true true true <unset> false
Vérifiez la StorageClass par défaut, qui est utilisée lorsqu'un PVC n'en spécifie pas :
kubectl get storageclass
Vous pourriez voir :
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
standard (default) kubernetes.io/gce-pd Delete WaitForFirstConsumer true 12d
Si aucune valeur par défaut n'est définie, marquez-en une avec :
kubectl patch storageclass standard -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
Capturez toujours l'état actuel avant les modifications. Par exemple, enregistrez les PVC existants :
kubectl get pvc -n myapp
Chemin de configuration sûr
Un chemin de configuration sûr signifie appliquer les modifications de manière incrémentielle et vérifier chaque étape. Commencez par un pod simple qui utilise un volume emptyDir pour comprendre les montages de base.
Créez test-volume.yaml :
apiVersion: v1
kind: Pod
metadata:
name: test-volume
spec:
containers:
- name: busybox
image: busybox:1.36
command: ['sh', '-c', 'echo hello > /data/message.txt && sleep 3600']
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
emptyDir: {}
Appliquez et vérifiez :
kubectl apply -f test-volume.yaml
kubectl get pod test-volume
Une fois en cours d'exécution, exécutez pour confirmer l'écriture :
kubectl exec test-volume -- cat /data/message.txt
Sortie attendue : hello.
Maintenant, passez au stockage persistant. Créez un PVC et un pod qui l'utilise. D'abord, définissez pvc.yaml :
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
# storageClassName: standard # optionnel si la valeur par défaut est définie
Appliquez et vérifiez l'état :
kubectl apply -f pvc.yaml
kubectl get pvc my-pvc
Si le PVC est en attente, cela peut être dû à l'absence de PV correspondant ou de StorageClass. Décrivez-le pour voir les événements :
kubectl describe pvc my-pvc
Une fois lié, créez un pod utilisant le PVC dans pod-with-pvc.yaml :
apiVersion: v1
kind: Pod
metadata:
name: pod-with-pvc
spec:
containers:
- name: app
image: nginx:1.25
volumeMounts:
- name: data
mountPath: /usr/share/nginx/html
volumes:
- name: data
persistentVolumeClaim:
claimName: my-pvc
Appliquez et vérifiez :
kubectl apply -f pod-with-pvc.yaml
kubectl get pod pod-with-pvc
Après vérification, supprimez les ressources de test :
kubectl delete pod pod-with-pvc test-volume
kubectl delete pvc my-pvc
Remarque : comme la politique de récupération par défaut pour les volumes provisionnés dynamiquement est généralement Delete, le PV est supprimé. Si vous devez conserver les données, définissez persistentVolumeReclaimPolicy: Retain sur le PV.
Vérification et diagnostics
Lorsque les volumes échouent, utilisez une approche systématique. Commencez par des observations en lecture seule :
kubectl get pods -o wide
kubectl describe pod <pod-name>
kubectl logs <pod-name> --previous
Par exemple, si un pod est bloqué dans ContainerCreating, décrivez-le :
kubectl describe pod my-app-7c8b9d6f4-abcde
Recherchez des événements comme :
Warning FailedAttachVolume 2m42s attachdetach-controller AttachVolume.Attach failed for volume "pvc-123..." : timed out waiting for the condition
Cela indique souvent un problème avec le backend de stockage ou le nœud. Vérifiez l'état du nœud :
kubectl get nodes
Si le nœud est NotReady, inspectez-le :
kubectl describe node <node-name>
Vérifiez que le PVC est lié :
kubectl get pvc
Si le PVC est Pending, décrivez-le :
kubectl describe pvc my-pvc
Raisons courantes :
- Aucun provisionneur de StorageClass disponible.
- La taille demandée dépasse le quota.
- Mésappariement du mode d'accès.
- La StorageClass a
WaitForFirstConsumeret aucun pod n'est planifié.
Vous pouvez également vérifier les détails du PV :
kubectl get pv
kubectl describe pv <pv-name>
Utilisez kubectl get events --sort-by=.metadata.creationTimestamp pour voir les événements récents du cluster.
Pour les volumes montés, testez l'écriture/lecture dans le pod :
kubectl exec <pod-name> -- sh -c 'echo test > /data/testfile && cat /data/testfile'
Si le pod plante, utilisez kubectl logs <pod-name> --previous pour voir les journaux du conteneur précédent.
Modes de défaillance et récupération
Comprendre les modes de défaillance courants aide à la récupération.
1. PVC bloqué en Pending
Cause : Aucun PV correspondant ou provisionneur ne fonctionne pas.
Diagnostic :
kubectl describe pvc my-pvc
Si les événements indiquent no persistent volumes available for this claim and no storage class is set, vous devrez peut-être créer un PV ou définir une StorageClass par défaut.
Récupération : Créez un PV manuellement si le provisionnement statique est prévu, ou définissez une StorageClass et référencez-la dans le PVC.
2. Pod bloqué dans ContainerCreating avec des erreurs de volume
Cause : Le volume ne peut pas être attaché ou monté (par exemple, disque cloud dans la mauvaise zone, pilote manquant sur le nœud).
Diagnostic :
kubectl describe pod <pod-name>
Recherchez des événements comme FailedMount ou FailedAttachVolume.
Récupération :
- Si vous utilisez des disques zonaux, assurez-vous que le pod est planifié dans la même zone que le disque. Utilisez l'affinité de nœud ou le mode de liaison
WaitForFirstConsumer. - Pour les pilotes CSI, vérifiez que les pods du pilote fonctionnent :
kubectl get pods -n kube-system | grep csi. - Vérifiez que le nœud dispose des utilitaires de montage requis.
3. Les données ne persistent pas après la suppression du pod
Cause : Le volume était emptyDir ou la politique de récupération du PVC est Delete.
Diagnostic : Inspectez la politique de récupération du PV :
kubectl get pv <pv-name> -o jsonpath='{.spec.persistentVolumeReclaimPolicy}'
Récupération : Pour la conservation des données, définissez persistentVolumeReclaimPolicy: Retain sur le PV. Après la suppression du PVC, le PV reste et peut être récupéré manuellement.
4. Problèmes d'accès multi-nœuds
Cause : Utilisation de ReadWriteOnce sur un volume qui nécessite plusieurs nœuds.
Diagnostic : Vérifiez les modes d'accès sur le PVC et le PV :
kubectl get pvc my-pvc -o jsonpath='{.spec.accessModes}'
Récupération : Utilisez un volume qui prend en charge ReadWriteMany (par exemple, NFS, Azure Files, Amazon EFS) et mettez à jour les modes d'accès en conséquence. Notez que vous ne pouvez pas modifier les modes d'accès d'un PVC lié ; vous devez le recréer.
5. Disque plein ou quota dépassé
Cause : L'application écrit trop de données.
Diagnostic : Vérifiez l'utilisation du disque dans le pod : kubectl exec <pod> -- df -h /mountpoint.
Récupération : Étendez le volume si allowVolumeExpansion est vrai dans la StorageClass :
kubectl patch pvc my-pvc -p '{"spec":{"resources":{"requests":{"storage":"5Gi"}}}}'
Puis vérifiez avec kubectl get pvc.
Documentez toujours les étapes de récupération et testez-les dans un environnement non productif avant un incident.
Liste de contrôle des opérations
Utilisez cette liste de contrôle pour des opérations de volume sûres :
- [ ] Vérifiez la version de Kubernetes et les pilotes de stockage :
kubectl versionetkubectl get csidrivers. - [ ] Vérifiez la StorageClass par défaut :
kubectl get storageclass. - [ ] Enregistrez l'état existant des PVC/PV :
kubectl get pvc,pv -A. - [ ] Testez le montage de volume avec un pod simple (emptyDir) avant de passer aux volumes persistants.
- [ ] Créez un PVC avec un mode d'accès et une taille appropriés, et spécifiez explicitement la StorageClass pour éviter toute ambiguïté.
- [ ] Pour la production, utilisez le mode de liaison
WaitForFirstConsumerpour garantir la prise en compte de la planification du pod. - [ ] Appliquez la configuration du pod et vérifiez l'état :
kubectl get pod <name>. - [ ] Vérifiez les événements et les journaux en cas d'échec :
kubectl describe pod <name>,kubectl logs <name> --previous. - [ ] Testez la persistance des données : écrivez un fichier, supprimez le pod, recréez et lisez le fichier.
- [ ] Définissez la politique de récupération sur
Retainsi les données doivent survivre à la suppression du PVC. - [ ] Surveillez la capacité du volume et étendez-le si nécessaire.
- [ ] Avant de supprimer un PVC, assurez-vous qu'aucun pod ne l'utilise :
kubectl get pvc -o wide. - [ ] Documentez les procédures de récupération pour les défaillances courantes.
Exemple de définition de PVC en production :
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-data
namespace: production
spec:
accessModes:
- ReadWriteOnce
storageClassName: fast-ssd
resources:
requests:
storage: 20Gi
Et la StorageClass correspondante :
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-ssd
reclaimPolicy: Retain
allowVolumeExpansion: true
volumeBindingMode: WaitForFirstConsumer
Appliquez les deux, puis créez un Deployment qui utilise le PVC. Vérifiez toujours le déploiement :
kubectl apply -f storageclass.yaml
kubectl apply -f pvc.yaml
kubectl apply -f deployment.yaml
kubectl rollout status deployment/my-app
Conclusion
L'architecture des volumes Kubernetes est puissante mais nécessite une configuration et une vérification minutieuses. En comprenant les PV, les PVC et les StorageClasses, et en suivant une approche systématique pour les tests et le dépannage, vous pouvez éviter les pièges courants et garantir le fonctionnement fiable de vos applications avec état.
Commencez par une vérification à faible risque : créez un pod de test avec un volume emptyDir, puis progressez vers le stockage persistant. Enregistrez l'état actuel, exécutez des contrôles documentés et comparez les résultats aux attentes. Limitez toujours les modifications à la ressource prévue et documentez les étapes de récupération avant qu'un incident ne force une décision.
Avec les commandes et les exemples de cet article, vous devriez pouvoir diagnostiquer les problèmes de volume, récupérer des défaillances et exploiter le stockage Kubernetes en toute confiance.