Skip to content

Module 2 — Stockage persistant : Kubernetes et cloud

Bonne lecture et bon apprentissage ! Junior TSAFACK – 12/09/2026 Temps de lecture estimé : 8 minutes


Le problème : le système de fichiers d’un conteneur est éphémère

Section titled “Le problème : le système de fichiers d’un conteneur est éphémère”

Tout ce qu’un conteneur écrit sur son propre système de fichiers disparaît quand le conteneur est supprimé — vrai en Docker (déjà implicite dans les modules précédents) comme en Kubernetes. Pour des données qui doivent survivre au conteneur (une base de données, des fichiers uploadés par un utilisateur), Kubernetes propose les PersistentVolume (PV) et PersistentVolumeClaim (PVC).

Le test réel : la donnée survit-elle vraiment à la suppression du pod ?

Section titled “Le test réel : la donnée survit-elle vraiment à la suppression du pod ?”

Sur le cluster k3s déjà utilisé dans les modules Kubernetes et Helm de ce cours, une réclamation de stockage a été créée puis utilisée par un premier pod pour écrire un fichier :

pvc-et-pod.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: demo-pvc
namespace: demo-app
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 500Mi
---
apiVersion: v1
kind: Pod
metadata:
name: storage-pod
namespace: demo-app
spec:
containers:
- name: writer
image: busybox
command: ["sh", "-c", "echo 'Donnee persistante ecrite par le pod' > /data/preuve.txt && sleep 3600"]
volumeMounts:
- { mountPath: "/data", name: storage-volume }
volumes:
- name: storage-volume
persistentVolumeClaim: { claimName: demo-pvc }
$ kubectl exec -n demo-app storage-pod -- cat /data/preuve.txt
Donnee persistante ecrite par le pod

Le pod original est ensuite supprimé, et un second pod, complètement différent, monte la même PVC :

$ kubectl delete pod storage-pod
pod "storage-pod" deleted
$ kubectl apply -f storage-pod2.yaml
pod/storage-pod-2 created
$ kubectl exec -n demo-app storage-pod-2 -- cat /data/preuve.txt
Donnee persistante ecrite par le pod

La donnée est toujours là, écrite par un pod qui n’existe plus, lue par un pod qui vient d’être créé. C’est exactement la garantie qu’un PVC doit apporter : la durée de vie de la donnée est découplée de la durée de vie du pod.

Un détail réel rencontré : provisionnement dynamique vs statique

Section titled “Un détail réel rencontré : provisionnement dynamique vs statique”

Une PersistentVolume nommée demo-pv avait été créée manuellement en amont (avec hostPath, pointant vers un chemin fixe du nœud) — dans l’intention qu’elle serve directement la PVC. Ce n’est pas ce qui s’est passé :

$ kubectl get pv,pvc -n demo-app
persistentvolume/demo-pv 1Gi Available ← jamais utilisée
persistentvolume/pvc-a1025343-... 500Mi Bound demo-app/demo-pvc local-path
persistentvolumeclaim/demo-pvc Bound pvc-a1025343-... local-path
$ kubectl describe pvc demo-pvc -n demo-app
Normal WaitForFirstConsumer waiting for first consumer to be created before binding
Normal Provisioning External provisioner is provisioning volume for claim "demo-app/demo-pvc"
Normal ProvisioningSucceeded Successfully provisioned volume pvc-a1025343-...

Ce qui s’est réellement passé : k3s embarque un provisionneur de stockage par défaut (local-path-provisioner), associé à une StorageClass par défaut. Comme la PVC ne précisait pas explicitement storageClassName: "" pour forcer une liaison statique à demo-pv, Kubernetes a préféré le provisionnement dynamique : créer automatiquement un tout nouveau PersistentVolume adapté exactement à la taille demandée, plutôt que d’utiliser le volume statique préexistant. demo-pv reste Available, jamais consommée.

La leçon à en tirer : sur un cluster moderne (k3s comme sur un cluster cloud managé EKS/GKE/AKS, tous équipés d’un provisionneur par défaut), le provisionnement dynamique est le comportement par défaut, pas une option à activer — créer manuellement des PersistentVolume statiques (l’approche historique) est aujourd’hui l’exception, réservée à des cas précis (un volume réseau externe préexistant à rattacher explicitement).

Au-delà de Kubernetes, tout fournisseur cloud propose trois familles de stockage, avec des cas d’usage distincts :

Type Usage typique Exemples
Stockage bloc (Block Storage) Disque attaché à une VM ou un conteneur, pour une base de données ou un système de fichiers AWS EBS, OpenStack Cinder
Stockage fichier (File Storage) Système de fichiers partagé, monté simultanément par plusieurs machines AWS EFS, NFS
Stockage objet (Object Storage) Fichiers individuels adressés par clé, pour sauvegardes, logs, médias — pas un vrai système de fichiers AWS S3, MinIO (l’équivalent auto-hébergeable)

Le choix entre les trois dépend d’abord d’une question : combien de machines doivent lire ou écrire simultanément ? Un disque bloc appartient à une seule machine à la fois (ou nécessite un système de fichiers en cluster complexe pour le partager) ; le stockage fichier est conçu pour l’accès concurrent de plusieurs machines ; le stockage objet n’est pas un système de fichiers du tout — chaque objet est manipulé individuellement via une API HTTP (GET/PUT sur une clé), ce qui le rend infiniment scalable pour du stockage de masse mais inadapté pour, par exemple, une base de données qui a besoin d’écritures aléatoires à faible latence.

Terminal window
# Le même geste (copier un fichier), sur les 3 grands fournisseurs cloud
aws s3 cp fichier.txt s3://mon-bucket/
az storage blob upload --container-name mon-conteneur --file fichier.txt --name fichier.txt
gsutil cp fichier.txt gs://mon-bucket/

Trois commandes différentes pour le même concept — le stockage objet reste le type le plus uniforme d’un fournisseur à l’autre, ce qui en fait souvent le point de départ le plus simple pour une architecture multi-cloud.

Ce parcours a couvert, dans un ordre cohérent : l’administration système et le scripting, l’automatisation Python, Git avancé et les plateformes, l’Infrastructure as Code, la conteneurisation et l’orchestration, la gestion de configuration, l’observabilité, la sécurité et la conformité, les réseaux, et enfin les données et le stockage — les mêmes briques qui composent, ensemble, ce qu’on appelle une chaîne d’outils DevOps complète. Chaque module s’appuie sur le précédent : Docker avant Kubernetes, Kubernetes avant Helm, les métriques avant l’alerting — pas une pile de sujets indépendants, mais un parcours where chaque étape prépare la suivante.