Les containers, par conception, ont un système de fichiers éphémère. Cela signifie que toutes les données écrites à l'intérieur du système de fichiers d'un container sont perdues lorsque ce container s'arrête ou est redémarré (par exemple, lors d'un crash ou d'une mise à jour de Pod).
Pour les applications qui nécessitent de conserver des données au-delà du cycle de vie d'un seul container (bases de données, uploads utilisateurs, logs persistants, etc.), ce comportement pose problème. Kubernetes résout cela grâce au concept de Volumes.
Un Volume Kubernetes est essentiellement un répertoire, potentiellement pré-rempli avec des données, qui est accessible aux containers d'un Pod. La particularité clé est que le cycle de vie d'un Volume est lié au Pod lui-même, et non aux containers individuels qui le composent.
emptyDir
) sont également supprimés. Pour une persistance au-delà du cycle de vie du Pod, il faut utiliser des Volumes Persistants.Un Pod spécifie les Volumes qu'il utilise dans spec.volumes
, et chaque container qui a besoin d'accéder à un Volume le monte dans son propre système de fichiers via spec.containers[*].volumeMounts
.
apiVersion: v1
kind: Pod
metadata:
name: pod-avec-volume
spec:
containers:
- name: mon-container
image: busybox:1.36
command: ["sleep", "3600"]
volumeMounts:
# Monte le volume nommé 'data-partagee'
# dans le répertoire '/app/data' du container
- name: data-partagee
mountPath: /app/data
volumes:
# Définit un volume nommé 'data-partagee'
# de type emptyDir (détails ci-dessous)
- name: data-partagee
emptyDir: {} # Sans préciser le volume sera dans : /var/lib/kubelet/pods/<pod-uid>/volumes/kubernetes.io~empty-dir/<volume-name>
# Pour avoir l'UID : kubectl get pod pod-avec-volume -o jsonpath='{.metadata.uid}'
Kubernetes supporte de nombreux types de volumes. Voici quelques-uns des plus importants pour commencer et pour la CKA :
emptyDir
:
emptyDir
est définitivement perdu.emptyDir.medium: Memory
est spécifié).Exemple (partage entre containers) :
apiVersion: v1
kind: Pod
metadata:
name: shared-volume-pod
spec:
containers:
- name: writer # Container qui écrit
image: busybox:1.36
command: ['sh', '-c', 'while true; do echo "Données partagées $(date)" > /shared/data.txt; sleep 5; done']
volumeMounts:
- name: shared-data
mountPath: /shared
- name: reader # Container qui lit
image: busybox:1.36
command: ['sh', '-c', 'while true; do cat /input/data.txt; sleep 5; done']
volumeMounts:
- name: shared-data
mountPath: /input # Le mountPath peut être différent
volumes:
- name: shared-data
emptyDir: {} # Le même volume emptyDir est utilisé par les deux
hostPath
:
Exemple :
apiVersion: v1
kind: Pod
metadata:
name: hostpath-pod
spec:
containers:
- name: test-container
image: busybox:1.36
command: ["sh", "-c", "sleep 3600"]
volumeMounts:
- name: host-data
mountPath: /host/data # Accès aux données du nœud dans /host/data
volumes:
- name: host-data
hostPath:
path: /var/lib/mydata # Chemin sur le nœud hôte
type: DirectoryOrCreate # Crée le répertoire s'il n'existe pas
configMap
/ secret
:
Pour une persistance des données indépendante du cycle de vie du Pod, on utilise l'abstraction des Volumes Persistants.
Un PersistentVolume (PV) est une unité de stockage dans le cluster qui a été provisionnée par un administrateur ou dynamiquement provisionnée en utilisant des StorageClasses. C'est une ressource du cluster, tout comme un nœud est une ressource du cluster.
Un manifeste PV typique inclut :
spec.capacity
: La quantité de stockage (ex: 5Gi
).spec.volumeMode
: Filesystem
(défaut) ou Block
.spec.accessModes
: Comment le volume peut être monté (voir ci-dessous).spec.persistentVolumeReclaimPolicy
: Que faire du volume lorsque la demande (PVC) est libérée (Retain
, Delete
, Recycle
).spec.storageClassName
: Lien vers une StorageClass (pour le binding et le provisionnement dynamique).spec.hostPath
, spec.nfs
, spec.awsElasticBlockStore
, etc.).# Exemple de PV provisionné manuellement (Statique) avec hostPath
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-manual-hostpath
labels:
type: local # Utile pour le matching avec PVC
spec:
storageClassName: "manual" # Nom arbitraire pour le binding statique
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce # Peut être monté en lecture/écriture par un seul nœud à la fois
persistentVolumeReclaimPolicy: Retain # Garder les données après libération du PVC
volumeMode: Filesystem
hostPath:
path: "/mnt/data/pv1" # Chemin sur UN nœud spécifique - NON RECOMMANDÉ pour la production
Les accessModes
définissent comment un PV peut être monté sur les nœuds :
ReadWriteOnce
(RWO): Le volume peut être monté en lecture-écriture par un seul nœud à la fois. C'est le mode le plus courant, supporté par la majorité des types de volumes (y compris les disques bloc des fournisseurs cloud comme EBS, GCE PD, Azure Disk).ReadOnlyMany
(ROX): Le volume peut être monté en lecture seule par plusieurs nœuds simultanément.ReadWriteMany
(RWX): Le volume peut être monté en lecture-écriture par plusieurs nœuds simultanément. Supporté uniquement par certains types de volumes partagés (ex: NFS, GlusterFS, CephFS, Azure Files).ReadWriteOncePod
(RWOP): (Feature plus récente) Le volume peut être monté en lecture-écriture par un seul Pod à la fois. Utile pour les StatefulSets avec certains drivers CSI.ReadWriteOnce
(RWO) vs ReadWriteOncePod
(RWOP) Le mode d'accès ReadWriteOnce limite l'accès au volume à un seul nœud, ce qui signifie qu'il est possible pour plusieurs pods sur le même nœud de lire et d'écrire sur le même volume. Cela pourrait constituer un problème majeur pour certaines applications, en particulier si elles nécessitent au maximum un auteur pour garantir la sécurité des données.
Un PV peut supporter plusieurs modes d'accès. Un PVC spécifiera le mode dont il a besoin, et il ne pourra être lié qu'à un PV supportant ce mode.
La persistentVolumeReclaimPolicy
indique ce qu'il advient du volume sous-jacent (et de ses données) après qu'un Pod ait fini de l'utiliser et que le PersistentVolumeClaim (PVC) associé soit supprimé :
Retain
(Souvent le plus sûr) : Le PV reste dans le cluster (en état Released
), et les données sur le volume externe sont conservées. L'administrateur doit manuellement nettoyer le volume externe et supprimer l'objet PV (ou le réutiliser).Delete
: Le volume externe (ex: disque EBS, GCE PD) est supprimé par Kubernetes (via le provisionneur de stockage). C'est souvent le comportement par défaut pour les StorageClasses dynamiques.Recycle
(Déprécié) : Effectuait un nettoyage basique (rm -rf /volume/*
). Non recommandé et souvent non supporté par les provisionneurs récents pour des raisons de sécurité.Une StorageClass fournit un moyen aux administrateurs de décrire les "classes" de stockage qu'ils offrent. Différentes classes peuvent correspondre à des niveaux de qualité de service (QoS), des politiques de sauvegarde, ou des politiques arbitraires déterminées par l'administrateur.
Elles sont cruciales pour le provisionnement dynamique.
# Exemple de StorageClass pour provisionner dynamiquement des disques standards sur GCP
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: gcp-standard-disk
provisioner: kubernetes.io/gce-pd # Indique quel plugin provisionne le stockage
parameters:
type: pd-standard # Type de disque spécifique à GCP
reclaimPolicy: Delete # Supprimer le disque GCE quand le PVC est supprimé
allowVolumeExpansion: true # Autoriser l'augmentation de taille
volumeBindingMode: Immediate # Provisionner dès que le PVC est créé
provisioner
: Détermine quel plugin de volume est utilisé pour provisionner les PVs.parameters
: Paramètres spécifiques au provisionneur.reclaimPolicy
: Politique appliquée aux PVs créés dynamiquement par cette classe.allowVolumeExpansion
: Si true
, permet aux PVCs de cette classe d'être redimensionnés.volumeBindingMode
:
Immediate
(Défaut): Provisionne et lie le PV dès que le PVC est créé. Peut poser problème dans les clusters multi-zones si le Pod ne peut pas être schedulé dans la zone où le disque a été créé.WaitForFirstConsumer
: Retarde le provisionnement et le binding jusqu'à ce qu'un Pod utilisant le PVC soit créé et schedulé. Permet au provisionneur de créer le volume dans la bonne zone/topologie.Un PersistentVolumeClaim (PVC) est une demande de stockage faite par un utilisateur (ou une application/Pod). Il est similaire à un Pod en ce sens que les Pods consomment des ressources de nœud et les PVCs consomment des ressources de PV.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-database-pvc
namespace: production
spec:
storageClassName: gcp-standard-disk # Demande un PV de cette classe (ou un PV compatible)
accessModes:
- ReadWriteOnce # A besoin d'un accès RWO
resources:
requests:
storage: 10Gi # Demande 10 GiB de stockage
Processus de Binding (Liaison) :
Pending
jusqu'à ce qu'un PV approprié devienne disponible.Une fois qu'un PVC est lié (Bound
), il peut être utilisé par un Pod.
# Lister les PVs
kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-xxxx-yyyy-zzzz 10Gi RWO Delete Bound production/my-database-pvc gcp-standard-disk 5m
# Lister les PVCs dans le namespace 'production'
kubectl get pvc -n production
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
my-database-pvc Bound pvc-xxxx-yyyy-zzzz 10Gi RWO gcp-standard-disk 5m
Pour monter le volume persistant demandé par le PVC dans un Pod, on utilise le type de volume persistentVolumeClaim
dans spec.volumes
.
apiVersion: v1
kind: Pod
metadata:
name: mon-pod-db
namespace: production
spec:
containers:
- name: database-container
image: postgres:16 # Exemple avec PostgreSQL 16
env:
# Configurer les variables d'environnement pour PostgreSQL
- name: POSTGRES_DB
value: "mabase"
- name: POSTGRES_USER
value: "monuser"
- name: POSTGRES_PASSWORD
value: "monpasse"
ports:
- containerPort: 5432
volumeMounts:
- mountPath: /var/lib/postgresql/data # Chemin où PostgreSQL stocke ses données
name: db-storage # Doit correspondre au nom dans spec.volumes
volumes:
- name: db-storage
persistentVolumeClaim:
# Référence le PVC créé précédemment
claimName: my-database-pvc
Le répertoire /var/lib/postgresql/data
dans le container sera maintenant sauvegardé sur le volume persistant géré par le PVC my-database-pvc
.
Si la StorageClass
associée à un PVC a allowVolumeExpansion: true
, on peut augmenter la taille demandée par le PVC après sa création.
Modifier le PVC : Editer l'objet PVC (ex: kubectl edit pvc my-database-pvc -n production
) et augmenter la valeur de spec.resources.requests.storage
.
# ... snippet du PVC édité ...
spec:
resources:
requests:
storage: 20Gi # Nouvelle taille demandée
# ... reste de la spec ...
Attendre l'expansion : Le statut du PVC peut passer par FileSystemResizePending
. Le Kubelet sur le nœud où le Pod utilise le PVC tentera de redimensionner le système de fichiers. Le redimensionnement à chaud n'est pas supporté par tous les types de volumes/systèmes de fichiers. Parfois, un redémarrage du Pod est nécessaire pour que le nouveau système de fichiers soit utilisé.
On peut vérifier l'état avec kubectl describe pvc <nom-pvc> -n <namespace>
.