Volumes persistants - ii02735/learn-k8 GitHub Wiki

Les volumes persistants (PV & PVC)

Le problème : les données des Pods sont éphémères

Le système de fichiers d'un container est éphémère : dès qu'un Pod est supprimé ou recréé, tout ce qu'il y avait écrit disparaît. Or beaucoup d'applications (bases de données, files de messages…) ont besoin de conserver leurs données.

Kubernetes sépare la demande de stockage de sa fourniture au moyen de deux objets :

  • le PersistentVolume (PV) : un morceau de stockage du cluster ;
  • le PersistentVolumeClaim (PVC) : une demande de stockage faite par une application.

Un Pod, son PVC et le PV associé

Rappel : les volumes d'un Pod

Un volume est un répertoire partagé entre les containers d'un même Pod. Il en existe plusieurs types :

  • emptyDir : volume temporaire, créé avec le Pod et supprimé avec lui (cache, fichiers de travail) ;
  • configMap / secret : injecter de la configuration sous forme de fichiers ;
  • hostPath : un chemin du noeud — à éviter (couplage au noeud, risques de sécurité) ;
  • persistentVolumeClaim : le volume lié à un stockage persistant (c'est notre sujet).

Le PersistentVolume (PV)

Un PersistentVolume représente un espace de stockage dans le cluster. Il est :

  • indépendant des Pods : sa durée de vie n'est pas liée à celle des Pods qui l'utilisent ;
  • une ressource de portée cluster (pas de namespace) ;
  • défini par une capacité, des accessModes, une politique de récupération, une StorageClass et un backend (disque local, NFS, cloud, Ceph…).

Il est soit créé à la main par un administrateur, soit créé automatiquement (provisionnement dynamique).

Le PersistentVolumeClaim (PVC)

Un PersistentVolumeClaim est une demande de stockage exprimée par une application, dans son namespace. On y précise :

  • la taille voulue (requests.storage) ;
  • les accessModes souhaités ;
  • éventuellement la StorageClass.

Le parallèle est volontaire : un PVC se lie à un PV comme un Pod se planifie sur un noeud. Un Pod consomme le stockage en référençant le PVC dans ses volumes.

Le binding

  • Le PVC cherche un PV compatible (taille suffisante, mêmes accessModes, même StorageClass) et s'y lie (bound).
  • La liaison est exclusive : un PV n'est lié qu'à un seul PVC à la fois.
  • Si aucun PV ne correspond mais qu'une StorageClass existe, un PV est créé automatiquement.

Provisionnement statique ou dynamique

  • Statique : un administrateur crée les PV à l'avance ; les PVC s'y lient.
  • Dynamique (le plus courant aujourd'hui) : on définit une StorageClass ; à la création d'un PVC, un provisionner crée un PV à la volée.
  • Une StorageClass décrit une classe de stockage (provisionner, paramètres, politique de récupération). Sans storageClassName explicite, la StorageClass par défaut du cluster est utilisée.

Les accessModes

  • ReadWriteOnce (RWO) : monté en lecture-écriture par un seul noeud (le cas le plus fréquent).
  • ReadOnlyMany (ROX) : monté en lecture seule par plusieurs noeuds.
  • ReadWriteMany (RWX) : monté en lecture-écriture par plusieurs noeuds (exige un stockage partagé type NFS, CephFS…).
  • ReadWriteOncePod (RWOP) : monté par un seul Pod.

Les politiques de récupération (reclaim policy)

  • Retain : quand le PVC est supprimé, le PV est conservé (les données restent ; récupération manuelle).
  • Delete : le PV et le stockage sous-jacent sont supprimés automatiquement.
  • Recycle : obsolète, à ne plus utiliser.

:warning: La valeur par défaut est souvent Delete : supprimer un PVC peut donc effacer les données. Utiliser Retain pour les données précieuses.

Un PV et un PVC (provisionnement statique)

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-data
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual
  hostPath:
    path: /mnt/data          # exemple ; en production : NFS, disque cloud…
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: manual
  resources:
    requests:
      storage: 5Gi

Un PVC en provisionnement dynamique

Sans PV préexistant, il suffit de créer le PVC : la StorageClass par défaut fait le reste.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

Un Pod qui utilise le PVC

apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
    - name: app
      image: nginx
      volumeMounts:
        - name: data
          mountPath: /data
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: data

[!NOTE] Dans un StatefulSet, on ne crée pas les PVC un par un : le champ volumeClaimTemplates en génère un par Pod (data-web-0, data-web-1…), chacun restant attaché à son Pod. Voir Les StatefulSets.

Éphémère ou persistant ?

  • Données temporaires (cache, tmp) → emptyDir.
  • Configuration → ConfigMap / Secret.
  • Données à conserver (base de données, fichiers utilisateurs) → PV / PVC.

Les commandes principales

  • Lister les PV : kubectl get pv
  • Lister les PVC : kubectl get pvc
  • Détails d'un PV : kubectl describe pv pv-data
  • Détails d'un PVC : kubectl describe pvc data
  • Lister les classes de stockage : kubectl get storageclass (ou kubectl get sc)
  • Supprimer un PVC (attention à la politique de récupération) : kubectl delete pvc data