Introduction
Les Storage Classes Kubernetes permettent aux administrateurs de cluster de définir le type de stockage disponible pour les charges de travail sans coder en dur les détails du stockage dans les manifestes d’application. Une Storage Class définit un provisionneur, des paramètres comme le type de disque ou le facteur de réplication, et une politique de récupération. Les développeurs demandent du stockage via des PersistentVolumeClaims (PVC) qui référencent une Storage Class, et Kubernetes provisionne dynamiquement un PersistentVolume (PV) correspondant. Cette séparation de l’intention et de l’implémentation réduit la charge opérationnelle et permet des configurations portables entre fournisseurs cloud et solutions sur site. Un modèle mental clair des composants et du flux de requêtes évite les retouches lors du diagnostic des échecs de provisionnement, comme le notent les praticiens qui séparent les étapes de recherche, de configuration et de publication pour la documentation sur le stockage.
Dans ce guide, nous examinons l’architecture derrière les Storage Classes, y compris le flux de contrôle depuis la création du PVC jusqu’à l’attachement du volume. Nous mettrons en place une implémentation ciblée utilisant le provisionneur intégré standard kubernetes.io/aws-ebs dans un cluster EKS hypothétique (Kubernetes v1.27), puis nous vérifierons le provisionnement dynamique avec de vraies commandes et leurs sorties. Nous couvrons les modes de défaillance courants comme les incompatibilités de zones et les permissions, et fournissons des étapes de restauration et de récupération. Enfin, une checklist opérationnelle vous aide à maintenir la configuration de stockage en bonne santé.
Inventaire des versions et de l’environnement
Avant de créer une Storage Class, confirmez que la version de votre cluster Kubernetes, votre fournisseur cloud et vos pilotes CSI (si utilisés) répondent aux exigences. Le provisionnement dynamique de volumes est stable depuis Kubernetes 1.6, mais les fonctionnalités spécifiques au fournisseur évoluent. Pour ce guide, nous supposons :
- Version Kubernetes : v1.27 (EKS 1.27 hypothétique)
- Fournisseur cloud : AWS, utilisant le provisionneur EBS intégré
kubernetes.io/aws-ebs - Nœuds : trois nœuds travailleurs dans une seule zone de disponibilité (us-east-1a) pour simplifier les attachements ; notez que les volumes EBS sont spécifiques à une zone.
- Le compte de service par défaut pour kube-controller-manager a la permission de créer des volumes EBS via l’IAM du fournisseur cloud (dans EKS, le rôle d’instance de nœud ou un rôle IRSA dédié doit avoir
ec2:CreateVolume,ec2:AttachVolume, etc.). - Une Storage Class nommée
gp2-encrypteddémontrera le chiffrement et la sélection du type.
Vérifiez la version de votre cluster et vos nœuds :
kubectl version --short
kubectl get nodes -o wide
Sortie attendue pour la version (le format réel peut varier) :
Client Version: v1.27.3
Kustomize Version: v5.0.3
Server Version: v1.27.4
Pour les nœuds, confirmez que la colonne zone de disponibilité correspond à votre zone EBS prévue (par exemple, us-east-1a). Si les nœuds s’étendent sur plusieurs zones, définissez des Storage Classes spécifiques à la zone ou utilisez un pilote CSI conscient de la topologie. Une approche pilote étroite réduit les risques ; commencez avec une seule Storage Class, un seul namespace et un PVC d’application avant d’étendre.
Chemin de configuration sûr
Commencez avec une Storage Class qui utilise un provisionneur bien connu et des paramètres conservateurs. Évitez de définir allowVolumeExpansion à true avant d’avoir testé le redimensionnement avec votre pilote CSI. Utilisez explicitement volumeBindingMode: WaitForFirstConsumer pour garantir que le volume est créé dans la même zone que le pod, évitant ainsi les échecs d’attachement inter-zones.
Créez le manifeste de Storage Class gp2-sc.yaml :
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: gp2-encrypted
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
fsType: ext4
encrypted: "true"
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
Appliquez-le :
kubectl apply -f gp2-sc.yaml
Vérifiez la classe :
kubectl get storageclass gp2-encrypted
Sortie attendue :
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
gp2-encrypted kubernetes.io/aws-ebs Retain WaitForFirstConsumer false 10s
Le mode WaitForFirstConsumer retarde la création du volume jusqu’à ce qu’un pod utilisant le PVC soit planifié, garantissant que le volume est créé dans la zone du nœud du pod. Le paramètre encrypted: "true" déclenche le chiffrement du volume EBS en utilisant la clé KMS par défaut pour EBS.
Ensuite, créez un namespace et un PVC pour tester le provisionnement :
kubectl create namespace storage-test
cat <<EOF | kubectl apply -n storage-test -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: test-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: gp2-encrypted
resources:
requests:
storage: 1Gi
EOF
Initialement, le PVC reste à l’état Pending car aucun pod ne l’a consommé :
kubectl get pvc -n storage-test test-pvc
Sortie :
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
test-pvc Pending gp2-encrypted 10s
Déployez maintenant un pod trivial (par exemple, busybox) qui monte le PVC :
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: app
image: busybox
command: ["sleep", "3600"]
volumeMounts:
- mountPath: "/data"
name: data
volumes:
- name: data
persistentVolumeClaim:
claimName: test-pvc
Appliquez-le :
kubectl apply -n storage-test -f test-pod.yaml
Attendez quelques secondes et vérifiez à nouveau le PVC :
kubectl get pvc -n storage-test test-pvc
Sortie attendue après provisionnement :
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
test-pvc Bound pvc-0c8e5e9f-3a7f-4c3b-8f0e-123456789abc 1Gi RWO gp2-encrypted 45s
Le volume est maintenant lié à un PV. Vérifiez les détails du PV :
kubectl get pv pvc-0c8e5e9f-3a7f-4c3b-8f0e-123456789abc
La sortie inclut l’ID du volume EBS AWS et la zone.
Ce chemin ciblé utilise le provisionneur intégré pour plus de simplicité. Pour la production, envisagez le pilote EBS CSI (ebs.csi.aws.com) qui offre une meilleure intégration, mais les concepts restent les mêmes.
Vérification et diagnostic
Après que le pod est en cours d’exécution, confirmez que le volume est attaché et monté. Tout d’abord, obtenez le statut du pod :
kubectl get pod -n storage-test test-pod
Attendu :
NAME READY STATUS RESTARTS AGE
test-pod 1/1 Running 0 2m
Vérifiez l’attachement du volume du point de vue du nœud. Connectez-vous en SSH au nœud (ou utilisez kubectl debug node), puis exécutez lsblk ou df -h pour voir le système de fichiers monté. Alternativement, exécutez dans le pod :
kubectl exec -n storage-test test-pod -- df -h /data
Sortie :
Filesystem Size Used Available Use% Mounted on
/dev/xvdba 976M 1.3M 958M 0% /data
Pour confirmer le chiffrement, utilisez l’AWS CLI depuis un emplacement avec permissions :
aws ec2 describe-volumes --volume-ids vol-0abc123def456ghij --query 'Volumes[0].Encrypted'
Attendu : true.
Vérifiez les annotations de la Storage Class et les événements pour tout avertissement :
kubectl describe storageclass gp2-encrypted
kubectl get events -n storage-test --field-selector involvedObject.name=test-pvc
Les événements peuvent montrer ProvisioningSucceeded ou des erreurs.
Pièges courants et comment les éviter
Même avec une architecture solide, des erreurs de configuration peuvent causer des maux de tête. Voici les pièges fréquents, pourquoi ils se produisent et comment les éviter ou s’en remettre.
1. Utiliser volumeBindingMode: Immediate dans les clusters multi-zones
Pourquoi cela arrive : Avec Immediate, le PV est créé dès que le PVC est soumis, sans attendre qu’un pod soit planifié. Dans les clusters multi-zones, le volume peut être créé dans une zone où aucun nœud ne peut l’attacher, laissant le pod bloqué en Pending avec une erreur node(s) had volume node affinity conflict.
Comment l’éviter : Toujours définir volumeBindingMode: WaitForFirstConsumer pour les Storage Classes qui seront utilisées dans les clusters multi-zones, ou utiliser un pilote CSI avec conscience topologique.
Récupération : Supprimez le PVC et recréez-le après avoir modifié le mode de liaison de la Storage Class, ou créez manuellement un PV dans la bonne zone et modifiez le PVC pour le lier.
2. Ignorer les conséquences de la politique de récupération
Pourquoi cela arrive : Les administrateurs définissent souvent reclaimPolicy: Delete par commodité sans réaliser que la suppression d’un PVC ou d’un namespace supprimera également le volume sous-jacent, entraînant potentiellement une perte de données. Inversement, Retain peut conduire à des volumes orphelins et des coûts inutiles si non nettoyés.
Comment l’éviter : Définissez explicitement la politique de récupération en fonction des besoins en données de la charge de travail. Utilisez Retain pour les applications stateful où les données doivent être préservées, et Delete uniquement pour les charges de travail éphémères ou facilement reproductibles. Documentez la politique dans la description de la Storage Class.
Récupération : Si Delete a été utilisé involontairement et que le volume est perdu, restaurez à partir des sauvegardes. Si Retain est utilisé et que des volumes sont orphelins, supprimez manuellement les volumes EBS après avoir confirmé qu’ils ne sont pas nécessaires.
3. Permissions IAM manquantes pour le provisionneur
Pourquoi cela arrive : Le gestionnaire de contrôleur ou le pilote CSI a besoin des permissions appropriées du fournisseur cloud pour créer, attacher et supprimer des volumes. Sans elles, le provisionnement échoue avec des erreurs AccessDenied.
Comment l’éviter : Assurez-vous que le rôle IAM associé à vos nœuds Kubernetes ou au pilote CSI dispose des permissions requises. Pour EBS intégré, le rôle d’instance de nœud a besoin de ec2:CreateVolume, ec2:AttachVolume, ec2:DetachVolume, etc. Pour CSI, utilisez les politiques recommandées.
Récupération : Vérifiez les journaux du contrôleur (kubectl logs -n kube-system kube-controller-manager-...) pour les erreurs de permission, corrigez la politique IAM, puis recréez le PVC.
4. Ne pas définir une Storage Class par défaut
Pourquoi cela arrive : Si aucune Storage Class par défaut n’est définie, les PVC sans storageClassName resteront indéfiniment non liés. Cela surprend souvent les nouveaux utilisateurs qui s’attendent à ce qu’une valeur par défaut existe.
Comment l’éviter : Désignez une Storage Class par défaut en utilisant l’annotation storageclass.kubernetes.io/is-default-class, ou spécifiez explicitement storageClassName dans chaque PVC.
Récupération : Ajoutez l’annotation à la Storage Class souhaitée, ou patchez le PVC pour inclure un storageClassName valide et recréez-le.
5. Surestimer les capacités d’expansion du stockage
Pourquoi cela arrive : Tous les provisionneurs ne prennent pas en charge l’expansion de volume, et même ceux qui le font peuvent nécessiter le drapeau allowVolumeExpansion: true. Tenter de redimensionner un PVC sur une Storage Class non compatible entraîne une erreur.
Comment l’éviter : Vérifiez que votre provisionneur prend en charge l’expansion et définissez allowVolumeExpansion: true seulement après avoir testé dans un environnement non productif. Pour EBS intégré, l’expansion n’est pas supportée ; vous devez utiliser le pilote CSI.
Récupération : Si l’expansion échoue, restaurez la taille d’origine du PVC et soit migrez les données vers un volume plus grand en utilisant un processus de sauvegarde/restauration, soit passez à un pilote CSI qui prend en charge l’expansion.
6. Oublier de nettoyer les ressources de test
Pourquoi cela arrive : Après les tests, les développeurs oublient souvent de supprimer les PVC et PV de test, laissant des ressources cloud orphelines qui engendrent des coûts.
Comment l’éviter : Mettez en place un script de nettoyage ou utilisez le ramasse-miettes Kubernetes avec des références propriétaires. Auditez régulièrement les volumes et leurs PVC associés.
Récupération : Supprimez manuellement le PVC et le PV, et vérifiez que le volume cloud sous-jacent est supprimé si la politique de récupération est Delete. Pour Retain, supprimez le volume cloud séparément.
Modes de défaillance et récupération
Les échecs courants avec le provisionnement dynamique incluent :
- Incompatibilité de zone : Avec
volumeBindingMode: Immediate, un PVC peut se lier à un volume dans une zone où aucun nœud n’existe, provoquant l’échec de planification du pod. Corrigez en utilisantWaitForFirstConsumer(comme nous l’avons fait) ou une planification consciente de la topologie avec CSI. - Permissions insuffisantes : Le fournisseur cloud manque de permissions IAM pour créer des volumes. Vérifiez les journaux du contrôleur (
kubectl logs -n kube-system kube-controller-manager-...) pour les erreursAccessDenied. Corrigez le rôle IAM et réessayez. - Conflits de protection contre la suppression :
reclaimPolicy: Retainlaisse des volumes après la suppression du PVC, nécessitant un nettoyage manuel. Si vous définissezreclaimPolicy: Delete, assurez-vous qu’aucun instantané ou dépendance ne bloque la suppression. - Quota fournisseur dépassé : Le fournisseur cloud peut refuser de créer de nouveaux volumes si les limites sont atteintes. Augmentez le quota ou supprimez les volumes inutilisés.
Étapes de restauration et de récupération :
- Supprimez le pod qui utilise le PVC pour détacher le volume.
- Si le PVC est bloqué en
Pendingen raison d’une mauvaise configuration, supprimez-le et recréez-le après avoir corrigé la Storage Class. - Pour une Storage Class corrompue, créez-en une nouvelle et patchez le champ
storageClassNamedu PVC (nécessite que le PVC soit en étatPending). - Si un volume ne se supprime pas, supprimez les finalisateurs ou supprimez manuellement via l’API cloud.
Exemple : forcer la suppression d’un PVC bloqué après avoir sauvegardé les données :
kubectl patch pvc -n storage-test test-pvc -p '{"metadata":{"finalizers":[]}}' --type=merge
kubectl delete pvc -n storage-test test-pvc
Vérifiez ensuite l’état du volume EBS dans AWS ; avec Retain, il reste disponible pour une récupération manuelle.
Checklist opérationnelle
Utilisez les vérifications répétables suivantes pour les Storage Classes dans votre environnement. Attribuez un responsable unique pour chaque vérification majeure afin de garantir qu’elle soit effectuée. Revoyez la checklist mensuellement lors d’une réunion d’équipe pour adapter les fréquences et les commandes à votre environnement.
| Fréquence | Tâche | Commande / Outil | Résultat attendu | Responsable (Nom, Rôle) |
|---|---|---|---|---|
| Quotidienne | Lister les Storage Classes et leur statut | kubectl get storageclass | Toutes les classes montrent les provisionneurs attendus et AGE | Priya Shah, Responsable Ingénierie |
| Quotidienne | Vérifier les PVC en échec | kubectl get pvc --all-namespaces | Aucun PVC bloqué en Pending pendant plus de 5 minutes | Tom Nguyen, Ingénieur DevOps |
| Hebdomadaire | Vérifier la Storage Class par défaut (si existante) | kubectl get storageclass -o name avec vérification d’annotation | Exactement une par défaut ou aucune comme prévu | Priya Shah, Responsable Ingénierie |
| Hebdomadaire | Examiner la conformité du chiffrement des volumes | Dépend du fournisseur ; ex. aws ec2 describe-volumes | Tous les volumes de production chiffrés | Tom Nguyen, Ingénieur DevOps |
| Mensuelle | Tester l’expansion de volume si activée | Appliquer une taille de PVC plus grande et vérifier le redimensionnement du PV | Le PVC montre la nouvelle taille sans redémarrage du pod (CSI uniquement) | Priya Shah, Responsable Ingénierie |
| Lors de changement | Valider le YAML de la Storage Class avant application | kubectl apply --dry-run=client -f sc.yaml | Aucune erreur de validation | Tom Nguyen, Ingénieur DevOps |
| Lors d’incident | Inspecter les événements pour PVC/PV | kubectl describe pvc <name> -n <ns> | Aucun événement d’avertissement | Ingénieur de garde |
Enregistrez ces vérifications dans le runbook de votre équipe et automatisez-les avec un cron job ou un système de surveillance. Utilisez une approche pilote étroite lors de l’introduction de nouveaux provisionneurs ou paramètres, en mesurant le succès avec une seule application avant une adoption plus large.
Conclusion
Les Storage Classes Kubernetes abstraient le provisionnement du stockage, mais comprendre leur architecture est essentiel pour des opérations fiables. Nous avons parcouru une implémentation ciblée utilisant le provisionneur AWS EBS intégré avec chiffrement, vérifié le provisionnement dynamique et l’attachement, exploré les modes de défaillance courants avec des étapes de récupération, et fourni une checklist opérationnelle. Commencez avec une Storage Class pilote petite et mesurable, puis étendez en fonction du succès observé. Gardez vos définitions de Storage Class simples, utilisez WaitForFirstConsumer pour éviter les problèmes de zone, et testez toujours les procédures de restauration dans un environnement sûr avant la production.