Préparation à la CKA - 06 - Persistent Volumes

Publié le 17/09/2024 par Ali Sanhaji

Volumes persistants

Nous avons vu précédemment la notion de volumes. C’est ce qui permet d’apporter des données aux Pods, par exemple de la configuration via des ConfigMap ou des identifiants via des Secrets. Mais les volumes que nous avons vu jusqu’ici étaient temporaires. C’est-à-dire tout ce qui est écrit dessus disparaît quand le Pod disparaît. Or il y a des applications qui ont besoin de persistance de données. Par exemple, on ne peut pas perdre les données d’une base de données SQL dès qu’il arrive un souci au Pod.

Dans ces cas, nous avons besoin de nouveaux objets Kubernetes qui nous apportent des volumes persistants : les PV, les PVC et les StorageClass.

Un PV (Persistent Volume) représente le stockage (par exemple un disque SSD) disponible à utiliser par des Pods sur un cluster. Chaque PV décrit ses capacités : type de stockage, taille, mode d’accès, et emplacement. Mais un Pod ne demande pas directement un PV, il passe d’abord par un PVC.

Un PVC (Persistent Volume Claim) est l’objet qui représente ce que demande un utilisateur comme stockage. Et c’est un algorithme de contrôle k8s qui se charge de désigner quel PV va correspondre à ce PVC. Si un utilisateur demande un PVC de 1Gi et qu’il n’y a qu’un PV de 10Gi de disponible, k8s va associer le PV de 10Gi au PVC demandant 1Gi. La plupart du temps, pour éviter ce genre de problèmes, les PV ne sont pas créés de manière statique au préalable de la demande de PVC. On attend qu’un utilisateur demande un PVC d’une certaine taille et avec certaines caractéristiques pour que k8s puisse satisfaire cette demande avec un PV qu’il va créer dynamiquement. Pour le faire, l’administrateur doit spécifier des StorageClass. Une StorageClass permet de décrire comment on peut demander des volumes persistants sur le cluster k8s. Par exemple, on peut avoir une StorageClass qui crée des disques SSD normaux, une qui crée des disques SSD très performants, une autre qui crée des partages de fichiers NFS ou SMB. Lorsqu’un utilisateur veut avoir un volume SSD de 1Gi par exemple, il doit créer un PVC qui fait référence à la StorageClass qui correspond à ses besoins, et un contrôleur k8s va créer le PV qui va correspondre à ce PVC, et lier les deux.

Création statique d’un Persistent Volume

Nous allons d’abord commencer par créer un volume persistant de manière statique pour comprendre comment marche la mécanique d’association des PV et PVC, ainsi que pour voir concrètement la persistance des volumes.

Créons d’abord le PV :

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-data
spec:
  storageClassName: "local"
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/opt/data"

Le PV que nous voulons créer est d’une capacité de 1Gi, avec un accessModes de ReadWriteOnce (RWO), ce qui signifie que le volume peut être monté en lecture/écriture par un seul nœud à la fois., et pour le fournir, nous demandons à k8s d’utiliser hostPath, c’est-à-dire qu’il sera créé sur le noeud sur lequel il sera utilisé, sur le chemin /opt/data.

La StorageClass “local” n’existe pas, mais elle nous sert afin de permettre la correspondance entre ce PV et le PVC que nous allons créer plus tard.

Quand nous créons le PV :

kubectl apply -f pv-data.yaml
kubectl get pv pv-data
NAME CAPACITY STATUS STORAGECLASS
pv-data 1Gi Available local                                                                                                                                  

Il est bien dans l’état Available.

Maintenant nous pouvons créer le PVC :

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-data
spec:
  storageClassName: "local"
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
kubectl apply -f pvc-data.yaml

Tout ce que nous avons demandé ici, c’est de créer un PVC d’une taille de 1Gi.

Quand on regarde le PVC :

kubectl get pvc pvc-data
NAME       STATUS   VOLUME    CAPACITY   STORAGECLASS
pvc-data   Bound    pv-data   1Gi   local

On voit bien que le PVC est lié au PV pv-data qui correspond à la taille de 1Gi demandée par le PVC. Si on avait demandé une taille plus grande, k8s n’aurait pas assigné ce PV à notre PVC. Le PVC resterait alors dans l’état Pending.

Et pour confirmer la liaison dans l’autre sens aussi, on peut revoir l’état du PV :

kubectl get pv pv-data
NAME      CAPACITY    STATUS   CLAIM    STORAGECLASS
pv-data   1Gi        RWO         Bound    test/pvc-data   local            

On voit bien que le PV a été attaché au PVC pvc-data qui se trouve dans le namespace test. Et que le PV est passé au statut Bound.

Nous allons maintenant créer un Pod qui va utiliser ce PV/PVC :

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: pvc-pod
  name: pvc-pod
spec:
  containers:
  - image: busybox:latest
    name: pvc-pod
    args:
      - sleep
      - "3600"
    volumeMounts:
    - name: data
      mountPath: "/data"
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: pvc-data

Nous avons déclaré le volume qui s’appelle data et qui fait référence au PVC pvc-data. Puis nous l’avons monté sur le container pvc-pod sur le chemin /data.

On le lance et on voit que le dossier /data est bien là :

kubectl apply -f pvc-pod.yaml

kubectl exec pvc-pod -- ls -l /
drwxr-xr-x    2 root     root          4096 Jan  2 10:50 data

Pour vérifier que le volume est bien persistent, on va créer un fichier dans le volume data :

kubectl exec pvc-pod -- touch /data/file
kubectl exec pvc-pod-2 -- ls /data/
file

On supprime le Pod :

kubectl delete -f pvc-pod.yaml

Puis on créé un nouveau Pod qui va s’appeler pvc-pod-2 et qui monte le volume data de la même manière que pvc-pod

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: pvc-pod
  name: pvc-pod-2
spec:
  containers:
  - image: busybox:latest
    name: pvc-pod
    args:
      - sleep
      - "3600"
    volumeMounts:
    - name: data
      mountPath: "/data"
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: pvc-data
kubectl apply -f pvc-pod-2.yaml

On regarde dans le dossier /data, et on voit que le fichier qu’on a créé dans le premier Pod existe toujours, donc que la donnée est bien persistée :

kubectl exec pvc-pod-2 -- ls /data/
file

Conclusion

Dans cet article, nous avons introduit les concepts de PersistentVolume (PV), PersistentVolumeClaim (PVC) et StorageClass, ainsi que leur rôle dans la gestion du stockage persistant dans Kubernetes.

Nous avons vu comment créer un PV de manière statique, l’associer à un PVC, puis l’utiliser dans un Pod afin de garantir la persistance des données, même après la suppression du Pod.

En pratique, le provisionnement dynamique via les StorageClasses est privilégié, car il permet de créer automatiquement les volumes persistants en fonction des besoins exprimés par les utilisateurs à travers leurs PVC.