☸️ Storage Systems — Chapitre 17 : Stockage persistant pour containers et Kubernetes
Kubernetes rend les containers mobiles et éphémères ; le stockage persistant rend les applications stateful possibles. Cette page densifie le sujet : PV, PVC, StorageClass, CSI, Longhorn, OpenEBS, Rook-Ceph, Portworx, cloud CSI, StatefulSets, backups Velero, snapshots CSI, bases de données, multi-zone, sécurité, observabilité, runbooks et checklist production.
Problème initial
Containers stateless vs applications stateful : pourquoi le stockage persistant devient difficile dans un monde éphémère.
StatelessStatefulEphemeralPersistent Volumes
PV, PVC, StorageClass, access modes, reclaim policy, volumeBindingMode et dynamic provisioning.
PVPVCStorageClassCSI
Container Storage Interface : contrôleur, node plugin, sidecars, attach/mount, snapshots, resize et drivers.
CSIDriversSidecarsSolutions Kubernetes
Longhorn, OpenEBS, Rook-Ceph, Portworx, EBS CSI, Azure Disk CSI, GCE Persistent Disk CSI.
LonghornRook-CephCloud CSIStatefulSets
Bases de données, files, brokers : identité stable, PVC par pod, ordonnancement, rolling updates et headless services.
StatefulSetDBBrokersBackup Kubernetes
Velero, snapshots CSI, disaster recovery, sauvegarde etcd, backup applicatif, restore namespace et GitOps.
VeleroCSI SnapshotsDRDifficultés
Performance, multi-zone, corruption, split-brain, backup cohérent, scheduling, permissions, expansion et observabilité.
PerformanceMulti-zoneSplit-brainAccess Modes
RWO, RWX, ROX, RWOP : choix volume bloc/fichier, implications pour pods, DB et workloads partagés.
RWORWXRWOPTopology & zones
WaitForFirstConsumer, topology keys, zones cloud, node affinity, local PV, anti-affinity et failure domains.
TopologyZonesAffinityLocal PV & performance
NVMe local, local persistent volumes, hostPath anti-pattern, node failure, database latency et edge clusters.
Local PVNVMeEdgeRWX / fichiers partagés
NFS, CephFS, Azure Files, EFS, Filestore, SMB CSI : usages, limites et performance metadata.
NFSCephFSEFSBases de données sur Kubernetes
PostgreSQL, MySQL, MongoDB, Cassandra, Kafka : operators, storage class, quorum, WAL, PVC et backups.
PostgreSQLKafkaOperatorsCloud CSI
AWS EBS/EFS, Azure Disk/Files, GCE PD/Filestore : contraintes zone, performance, snapshots et coûts.
AWSAzureGCPSécurité storage K8s
RBAC, secrets, encryption, FSGroup, permissions, tenant isolation, backup credentials et ransomware.
RBACEncryptionSecretsObservabilité
PVC usage, filesystem full, CSI errors, attach latency, IO latency, storage backend metrics et alerting.
MetricsPVCAlertingMatrice de décision
Choisir Longhorn, OpenEBS, Rook-Ceph, Portworx, cloud CSI, NFS selon SLA, équipe, coût et workloads.
DecisionSLACostRunbooks incidents
PVC pending, pod stuck, mount failed, volume full, snapshot failed, node lost, restore urgent et corruption DB.
RunbookIncidentRestoreChecklist production
Préprod Kubernetes storage : StorageClass, backup, snapshots, topology, monitoring, restore drills et documentation.
Prod-readyAuditChecklistContainers éphémères
Kubernetes a été conçu pour lancer, arrêter, déplacer et recréer des containers facilement. Un pod peut disparaître à tout moment : rescheduling, rolling update, autoscaling, drain de nœud, panne, éviction. Le filesystem interne d’un container n’est donc pas un endroit fiable pour conserver des données métier.
Besoin stateful
Les applications stateful exigent identité, ordre, persistance, cohérence, sauvegarde, restauration, latence et parfois quorum. Kubernetes peut les héberger, mais uniquement avec un design de stockage explicite.
| Type | Exemples | Stockage | Risque |
|---|---|---|---|
| Stateless | API web, workers, frontends. | Config/secrets, logs externes. | Faible si données externes. |
| Stateful simple | Uploads, cache persistant. | PVC, RWX parfois. | Permissions, backup. |
| Stateful critique | PostgreSQL, Kafka, MongoDB. | PVC dédiés, operators, snapshots. | Corruption, split-brain, RPO/RTO. |
| Distribué | Cassandra, Elasticsearch, Ceph. | Local PV ou bloc rapide. | Quorum et placement zones. |
- Les données survivent aux pods, pas forcément aux nœuds si local PV mal conçu.
- Un volume persistant ne remplace pas un backup.
- Une base stateful dans Kubernetes nécessite un operator ou un runbook très solide.
- La topologie multi-zone doit être pensée avant production.
- Les snapshots doivent être cohérents avec l'application, pas seulement avec le disque.
| Objet | Rôle | Qui le crée ? |
|---|---|---|
| PersistentVolume | Ressource stockage disponible dans le cluster. | Admin ou provisioner CSI. |
| PersistentVolumeClaim | Demande de stockage par une application. | Développeur/app chart. |
| StorageClass | Classe de provisioning : driver, paramètres, topology. | Admin plateforme. |
| VolumeSnapshot | Point-in-time snapshot via CSI. | App/admin/backup tool. |
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-rwo
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
reclaimPolicy: Delete
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-postgres-0
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: fast-rwo
resources:
requests:
storage: 100Gi| Policy | Effet | Usage |
|---|---|---|
| Delete | Supprime volume backend quand PVC supprimé. | Dev/test, données recréables. |
| Retain | Garde volume backend. | Production critique, investigations. |
| Recycle | Legacy, rarement utilisé. | À éviter. |
WaitForFirstConsumer retarde la création/binding du volume jusqu'au scheduling du pod. C'est essentiel en multi-zone pour créer le volume dans la même zone que le nœud choisi.
CSI standardise l'intégration des systèmes de stockage avec Kubernetes. Au lieu d'intégrations spécifiques dans Kubernetes, chaque fournisseur expose un driver CSI avec un controller plugin et un node plugin.
| Composant | Rôle |
|---|---|
| Controller plugin | Create/Delete volume, attach, snapshot, resize. |
| Node plugin | Stage/publish volume sur nœud, mount filesystem. |
| External provisioner | Observe PVC et crée PV. |
| External attacher | Gère VolumeAttachment. |
| Snapshotter | Crée VolumeSnapshot si supporté. |
| Resizer | Expansion PVC/volume. |
- Pod demande PVC.
- Provisioner crée le volume backend.
- Scheduler place le pod.
- Attacher attache le volume au nœud si bloc cloud.
- Node plugin stage le volume.
- Kubelet mount dans le container.
kubectl get storageclass kubectl get pvc -A kubectl get pv kubectl get volumeattachment kubectl describe pvckubectl describe pod kubectl logs -n kube-system -l app=csi-controller kubectl logs -n kube-system -l app=csi-node
- Driver CSI absent sur un nœud.
- Permissions cloud insuffisantes.
- Volume dans mauvaise zone.
- Attach limit atteint sur instance cloud.
- Filesystem déjà monté ou dirty.
- StorageClass sans allowVolumeExpansion.
| Solution | Type | Forces | Points d’attention |
|---|---|---|---|
| Longhorn | Block distribué K8s | Simplicité, UI, backups. | Réseau et perf selon cluster. |
| OpenEBS | Local/distribué selon moteur | Flexible, K8s-native. | Choix moteur critique. |
| Rook-Ceph | Ceph via operator | Block/File/Object complet. | Complexité Ceph. |
| Portworx | Enterprise K8s storage | DR, multi-cloud, features avancées. | Licence/coût. |
| AWS EBS CSI | Cloud block zonal | Managé, snapshots. | Zone-bound, attach limits. |
| Azure Disk CSI | Cloud block zonal | Intégration Azure. | Zone/performance tiers. |
| GCE PD CSI | Cloud block zonal/régional | Intégration GCP. | Mode régional coûteux/contraintes. |
- Cloud provider : utiliser d'abord CSI natif cloud pour simplicité.
- On-prem simple : Longhorn peut être un bon point d'entrée.
- On-prem complet block/file/object : Rook-Ceph/ODF.
- Enterprise multi-cloud : Portworx selon budget/SLA.
- Performance DB maximale : local PV ou bloc cloud performant + operator DB.
| SLA | RPO/RTO, panne nœud, panne zone. |
| Performance | IOPS, p99, throughput, small writes. |
| Ops | Qui sait réparer à 3h du matin ? |
| Backup | Snapshots, export, restore namespace/app. |
| Coût | Licences, disques, réseau, egress, snapshots. |
Un StatefulSet fournit identité stable, nom DNS stable et PVC stable par réplique. Il est adapté aux applications où chaque instance a un rôle ou des données propres : bases répliquées, brokers, clusters distribués.
| Élément | Rôle |
|---|---|
| Ordinal | Nom stable pod-0, pod-1. |
| volumeClaimTemplates | Crée un PVC par pod. |
| Headless Service | DNS stable par pod. |
| OrderedReady | Démarrage/arrêt ordonné par défaut. |
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres-headless
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: fast-rwo
resources:
requests:
storage: 100Gi- Supprimer le StatefulSet ne supprime pas forcément les PVC selon politique.
- Scale down conserve les PVC anciens.
- Un pod peut revenir avec ses données anciennes.
- La réplication applicative doit être cohérente avec le scheduling.
- Utiliser un operator mature pour DB critiques.
- Anti-affinity entre replicas.
- PDB pour éviter évictions simultanées.
- Backups applicatifs en plus des snapshots.
- Tests restore et failover.
| Niveau | Contenu | Outil type |
|---|---|---|
| Cluster metadata | YAML, CRDs, namespaces. | GitOps, Velero. |
| Volumes | PV/PVC data. | CSI snapshots, restic/kopia, backend snapshots. |
| Application | Dump DB, WAL, broker snapshots. | pgBackRest, mysqldump, operators. |
| etcd | Control plane state. | etcd snapshot. |
Velero sauvegarde les ressources Kubernetes et peut orchestrer snapshots de volumes via plugins cloud/CSI. Il est très utile pour restaurer namespace, manifests, PVC et migrations cluster.
velero backup create app-backup --include-namespaces app velero backup describe app-backup --details velero restore create --from-backup app-backup velero schedule create daily --schedule "0 2 * * *"
Les snapshots CSI capturent un volume. Ils sont rapides, mais pas toujours application-consistent. Pour bases critiques, coordonner avec l'application : freeze, flush, backup natif, WAL archiving.
kubectl get volumesnapshotclass kubectl get volumesnapshot -A kubectl describe volumesnapshot
- Restaurer CRDs/operators d'abord.
- Restaurer secrets/configmaps.
- Restaurer PVC/snapshots ou backups applicatifs.
- Restaurer workloads.
- Valider DNS, ingress, certificates, external dependencies.
- Mesurer RTO/RPO.
| Difficulté | Cause | Impact |
|---|---|---|
| Performance | Réseau, CSI, backend, small writes. | Latence p99 élevée. |
| Multi-zone | Volumes zonaux, scheduling. | Pod non schedulable. |
| Corruption | Deux writers non supportés, fs dirty. | Données perdues. |
| Split-brain | Quorum applicatif mal géré. | Deux primaires. |
| Backup incohérent | Snapshot crash-only. | Restore inutilisable. |
| Permissions | UID/GID, fsGroup, SELinux. | Pod démarre mais ne peut pas écrire. |
Les volumes cloud zonaux ne peuvent être attachés qu'à des nœuds de la même zone. Une StorageClass sans topology correcte peut créer des PVC inutilisables pour certains pods.
- Snapshot disque seul : crash-consistent.
- Snapshot avec freeze : filesystem-consistent.
- Backup natif DB : application-consistent.
- Le restore doit être testé, pas supposé.
| Mode | Sens | Usage |
|---|---|---|
| RWO | ReadWriteOnce, monté en écriture par un nœud. | DB, broker, bloc cloud. |
| RWX | ReadWriteMany, plusieurs nœuds/pods. | Fichiers partagés, uploads. |
| ROX | ReadOnlyMany. | Datasets, modèles IA en lecture. |
| RWOP | ReadWriteOncePod. | Exclusivité par pod. |
- DB primaire : RWO/RWOP généralement.
- Uploads partagés : RWX via NFS/CephFS/EFS/Azure Files.
- Datasets ML : ROX/RWX selon pipeline.
- Ne pas utiliser RWX pour contourner une architecture applicative mal conçue.
Le scheduler doit placer le pod là où le volume existe ou peut être créé. Dans le cloud, un disque EBS/Azure Disk/GCE PD est souvent zonal. En on-prem, un local PV dépend d'un nœud précis.
| volumeBindingMode | Immediate ou WaitForFirstConsumer. |
| nodeAffinity | Contraint le PV à certains nœuds. |
| topologyKeys | Zones/régions/racks. |
| podAntiAffinity | Évite replicas sur même domaine. |
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: zonal-fast
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
allowedTopologies:
- matchLabelExpressions:
- key: topology.kubernetes.io/zone
values: ["eu-west-1a", "eu-west-1b"]- Aligner replicas DB avec zones.
- Utiliser PodDisruptionBudgets.
- Tester perte zone/nœud.
- Documenter contraintes de stockage par StorageClass.
Un local PV expose un disque local d'un nœud à Kubernetes. Il offre une excellente latence, mais la donnée reste attachée au nœud. Si le nœud meurt, le volume n'est pas automatiquement disponible ailleurs.
- Databases avec réplication applicative.
- Kafka brokers.
- Cassandra/ScyllaDB.
- Elasticsearch/OpenSearch.
- Edge clusters avec NVMe local.
- Operator applicatif qui sait reconstruire replica.
- Anti-affinity entre replicas.
- Monitoring disque local.
- Runbook node loss.
- Backup hors nœud.
| Solution | Force | Limite |
|---|---|---|
| NFS CSI | Simple, classique. | HA/perf selon NAS. |
| CephFS | Distribué, intégré Ceph. | MDS/ops Ceph. |
| AWS EFS | Managé, multi-AZ. | Coût/perf modes. |
| Azure Files | SMB/NFS managé. | Performance tiers. |
| GCP Filestore | NFS managé. | Coût/capacité minimum. |
- Uploads partagés.
- CMS médias.
- Datasets lecture partagée.
- Fichiers temporaires multi-pods.
- Mais pas toujours DB transactionnelle.
Les workloads petits fichiers et metadata intensifs saturent vite les services RWX. Surveiller ops metadata, latence, locks et nombre de clients.
| PostgreSQL | CloudNativePG, Crunchy, Zalando selon contexte. |
| MySQL | Oracle MySQL Operator, Percona, Bitnami charts à évaluer. |
| MongoDB | Operator officiel/enterprise ou community. |
| Kafka | Strimzi, Confluent, Redpanda. |
| Cassandra | K8ssandra, cass-operator. |
- RWO rapide pour WAL/redo/logs.
- Low p99 latency.
- Topology anti-affinity.
- Snapshots coordonnés.
- Backup natif obligatoire.
| Cloud | Bloc RWO | Fichier RWX | Point clé |
|---|---|---|---|
| AWS | EBS CSI | EFS CSI | EBS zonal, EFS multi-AZ. |
| Azure | Azure Disk CSI | Azure Files CSI | Performance tiers. |
| GCP | Persistent Disk CSI | Filestore CSI | PD zonal/régional. |
- Attach limits par instance.
- Zones et topology.
- IOPS/débit selon type disque.
- Snapshots facturés.
- Expansion parfois online selon FS/driver.
- RBAC limité sur PVC/PV/snapshots.
- Secrets cloud CSI protégés.
- Encryption at rest côté backend.
- NetworkPolicy vers storage APIs si possible.
- Pod Security Standards pour limiter hostPath.
Les problèmes UID/GID, fsGroup, SELinux/AppArmor sont fréquents : le volume monte, mais l'application ne peut pas écrire.
securityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: "OnRootMismatch"
| Métrique | Pourquoi |
|---|---|
| PVC used/free | Éviter filesystem full. |
| PV phase | Bound, Released, Failed. |
| Pod mount errors | CSI/node/plugin issue. |
| Attach latency | Cloud/API delays. |
| IO latency | Performance applicative. |
| Snapshot status | Backup/DR reliability. |
kubectl get pvc -A kubectl get pv kubectl describe podkubectl get events -A --sort-by=.lastTimestamp kubectl top pod -A kubectl get volumesnapshot -A kubectl get volumeattachment
- PVC > 80/90/95%.
- PVC Pending > 5 min.
- VolumeAttachment stuck.
- CSI pod CrashLoopBackOff.
- Snapshot failed.
- Backend storage latency high.
| Besoin | Option | Attention |
|---|---|---|
| Cloud simple RWO | EBS/Azure Disk/GCE PD CSI | Zonal, attach limits. |
| Cloud RWX | EFS/Azure Files/Filestore | Coût, perf metadata. |
| On-prem simple | Longhorn | Réseau et backups. |
| On-prem complet | Rook-Ceph/ODF | Complexité Ceph. |
| Enterprise multi-cloud | Portworx | Licence, design. |
| DB très perf | Local PV + replication app | Node failure à gérer. |
- RWO ou RWX ?
- Cluster cloud ou on-prem ?
- Perte nœud/zone tolérée ?
- Latence p99 requise ?
- Qui opère le backend ?
- Comment restaurer une app complète ?
- kubectl describe pvc.
- Vérifier StorageClass/provisioner.
- Vérifier quotas namespace.
- Vérifier topology/zone.
- Vérifier logs CSI provisioner.
kubectl describe pvckubectl get sc kubectl logs -n kube-system -l app=csi-controller
- Décrire pod et events.
- Vérifier VolumeAttachment.
- Vérifier node plugin CSI.
- Vérifier permissions filesystem.
- Vérifier backend attach/mount.
- Confirmer usage dans pod.
- Étendre PVC si supporté.
- Agrandir filesystem si nécessaire.
- Purger données validées.
- Ajouter alertes.
- Identifier app, namespace, PVC, point restore.
- Restaurer dans namespace isolé.
- Valider données et application.
- Basculer service/DNS/Ingress.
- Documenter RTO/RPO.
| Contrôle | OK ? | Note |
|---|---|---|
| StorageClass par usage | ☐ | fast-rwo, rwx, archive. |
| Topology multi-zone validée | ☐ | WaitForFirstConsumer. |
| Backup + restore testé | ☐ | App complète, pas PVC seul. |
| Monitoring PVC/CSI | ☐ | Capacity, errors, latency. |
| Operators DB validés | ☐ | Failover, backup, upgrade. |
- RBAC minimal sur PVC/PV/snapshots.
- Secrets CSI protégés.
- Encryption backend.
- hostPath interdit sauf exceptions contrôlées.
- Backup credentials séparés.
- Runbook PVC Pending.
- Runbook Mount Failed.
- Runbook volume full.
- Runbook restore.
- Documentation StorageClasses et limitations.
