Retour au cours

infra / kubernetes

Volumes persistants : PV, PVC et StorageClass

Leçon 81 exercice

Explication

Ce que vous allez apprendre

  • Expliquer pourquoi le stockage d'un conteneur est éphémère par défaut, et quelles applications en ont besoin autrement
  • Distinguer les trois responsabilités séparées : PersistentVolume (disque réel), PersistentVolumeClaim (demande), StorageClass (règle de provisionnement)
  • Écrire un PVC qui demande une capacité de stockage sans connaître le disque physique sous-jacent
  • Choisir le bon accessMode (ReadWriteOnce, ReadOnlyMany, ReadWriteMany) selon le besoin de partage entre nodes
  • Diagnostiquer un Pod bloqué en Pending à cause d'un PVC mal configuré ou d'un accessMode incompatible

Dans quel contexte ?

Une équipe déploie une base de données PostgreSQL dans Kubernetes et découvre, après un premier test, que toutes les données disparaissent à chaque redéploiement du Pod. En ajoutant un PersistentVolumeClaim de 20 Go avec le mode ReadWriteOnce, monté sur le répertoire de données de PostgreSQL, les données survivent désormais aux redémarrages, aux mises à jour et même au déplacement du Pod vers un autre node du cluster — exactement le comportement attendu d'une base de données en production.

Le problème du stockage éphémère

D'abord, un fait déjà entrevu : tout ce qu'un conteneur écrit sur son disque disparaît quand le Pod est recréé. C'est voulu : cela garantit que les Pods restent interchangeables.

Prérequis

Cette leçon suppose comprise la distinction Deployment/Pod (leçon 4) : un PVC est généralement référencé dans le template de Pod d'un Deployment ou, mieux, d'un StatefulSet (leçon 16) pour les bases de données.

Ce que ce comportement casse pour certaines applications

Mais certaines applications, typiquement les bases de données, ont besoin que leurs données survivent aux redémarrages, aux mises à jour, voire au déplacement du Pod vers un autre node.

Trois objets pour trois responsabilités séparées

Kubernetes sépare volontairement trois notions. Le PersistentVolume (PV) représente un espace de stockage réellement provisionné, comme un disque cloud ou un NFS.

ObjetRôleQui l'écrit habituellement
StorageClassDéfinit comment provisionner automatiquement un disqueAdministrateur du cluster
PersistentVolume (PV)Représente un espace de stockage réellement provisionnéGénéré automatiquement (ou par un admin)
PersistentVolumeClaim (PVC)Demande de stockage faite par l'applicationDéveloppeur

Ce qu'une application demande, sans connaître le disque réel

Le PersistentVolumeClaim (PVC) est une "demande" faite par l'application : "j'ai besoin de 20 Go", sans se soucier du disque physique exact derrière. La StorageClass, elle, définit comment ce provisionnement se fait automatiquement, avec quel type de disque, dans quelle zone.

Pourquoi cette séparation est utile en pratique

Un développeur écrit simplement un PVC, pendant qu'un administrateur configure les StorageClass disponibles, sans que l'un ait besoin de connaître les détails de l'autre.

Un piège fréquent : le mode d'accès

Une fois le PVC créé, il reste un détail à ne pas négliger : le accessMode, qui détermine comment le volume peut être monté. ReadWriteOnce autorise un seul node à la fois, le cas le plus courant pour une base de données.

Piège fréquent

Vouloir monter un PVC en écriture sur plusieurs nodes simultanément sans le bon accessMode (ReadWriteMany, qui nécessite un système de fichiers réseau comme NFS) bloque simplement le démarrage des Pods concernés, qui restent en Pending sans message d'erreur évident. Vérifiez toujours que l'accessMode correspond au nombre réel de Pods qui doivent écrire simultanément.

Les modes qui autorisent plusieurs nodes

ReadOnlyMany et ReadWriteMany autorisent plusieurs nodes en même temps, mais nécessitent un système de fichiers réseau comme NFS. Vouloir monter un PVC en écriture sur plusieurs nodes sans le bon mode bloque simplement le démarrage des Pods concernés.

Ne pas perdre les données par erreur

Enfin, la reclaimPolicy détermine ce qui arrive au volume physique quand le PVC est supprimé. Retain conserve les données même après suppression accidentelle du PVC, un filet de sécurité précieux pour toute donnée importante en production.

Maintenant que les données peuvent survivre à un Pod, la leçon suivante s'intéresse à un besoin différent : organiser un cluster partagé entre plusieurs équipes ou environnements, avec les Namespaces.

Commandes & code

PersistentVolume, PersistentVolumeClaim, StorageClass

yaml
# storageclass.yaml - définit COMMENT le stockage est provisionné dynamiquement
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-ssd
provisioner: kubernetes.io/aws-ebs     # dépend du cloud provider (ex: ebs.csi.aws.com)
parameters:
  type: gp3
reclaimPolicy: Retain                   # garde les données même après suppression du PVC
volumeBindingMode: WaitForFirstConsumer  # provisionne au moment où un Pod l'utilise réellement
yaml
# pvc.yaml - une "demande" de stockage faite par une application
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: db-data-pvc
spec:
  accessModes:
    - ReadWriteOnce        # RWO = un seul node en lecture/écriture (typique pour une base)
  storageClassName: fast-ssd
  resources:
    requests:
      storage: 20Gi
yaml
# statefulset-like usage dans un Deployment (voir aussi la leçon StatefulSets)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:16
          volumeMounts:
            - name: data
              mountPath: /var/lib/postgresql/data
          env:
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db-credentials
                  key: password
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: db-data-pvc
bash
kubectl apply -f storageclass.yaml -f pvc.yaml
kubectl get pv,pvc
kubectl describe pvc db-data-pvc     # "Pending" = souvent un StorageClass introuvable ou quota atteint
AccessModeSignification
ReadWriteOnce (RWO)Monté en lecture/écriture par un seul node
ReadOnlyMany (ROX)Monté en lecture seule par plusieurs nodes
ReadWriteMany (RWX)Monté en lecture/écriture par plusieurs nodes (NFS, EFS...)
ReadWriteOncePodMonté en lecture/écriture par un seul Pod (le plus strict)

Résumé

  • PV = ressource de stockage réelle, PVC = demande faite par une app, StorageClass = comment provisionner.
  • WaitForFirstConsumer évite de provisionner un volume dans la mauvaise zone de disponibilité.
  • reclaimPolicy: Retain protège les données même si le PVC est supprimé par erreur.
  • ReadWriteOnce est le mode le plus courant pour les bases de données.

Exercices pratiques

1 disponible
1

Mission : sauver les données de PostgreSQL

Objectif : Ajouter un stockage persistant à une base de données, et choisir le bon accessMode selon le besoin réel de partage entre nodes.

Contexte

L'équipe vient de découvrir que toutes les données de son PostgreSQL disparaissent à chaque redéploiement du Pod, car aucun stockage persistant n'a été configuré. Ils veulent aussi préparer un second scénario : un futur outil d'analyse qui devra lire les mêmes fichiers exportés depuis DEUX Pods différents, sur deux nodes différents, en même temps.

Résoudre l’exercice →