Aller au contenu principal

Volumes et Stockage


1 - Introduction

Les conteneurs sont éphémères par nature. Pour persister les données, Kubernetes propose un système de volumes flexible.


2 - Types de Volumes

2.1 emptyDir

Volume éphémère créé quand un Pod est assigné à un Node.

apiVersion: v1
kind: Pod
metadata:
name: shared-storage
spec:
containers:
# Conteneur qui écrit
- name: writer
image: busybox
command: ['sh', '-c', 'while true; do date >> /data/log.txt; sleep 5; done']
volumeMounts:
- name: shared-data
mountPath: /data

# Conteneur qui lit
- name: reader
image: busybox
command: ['sh', '-c', 'tail -f /data/log.txt']
volumeMounts:
- name: shared-data
mountPath: /data

volumes:
- name: shared-data
emptyDir: {}
# Optionnel: stocker en RAM
# emptyDir:
# medium: Memory
# sizeLimit: 100Mi

2.2 hostPath

Monte un répertoire du Node hôte.

apiVersion: v1
kind: Pod
metadata:
name: hostpath-pod
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: host-data
mountPath: /data
volumes:
- name: host-data
hostPath:
path: /var/data
type: DirectoryOrCreate # Directory, File, Socket, etc.
attention

hostPath pose des risques de sécurité et n'est pas recommandé en production. Utilisez-le uniquement pour des cas spécifiques (DaemonSets, monitoring).

2.3 configMap et secret

Déjà couverts dans le chapitre précédent.

volumes:
- name: config-vol
configMap:
name: app-config
- name: secret-vol
secret:
secretName: app-secrets

2.4 projected

Combine plusieurs sources dans un seul volume.

apiVersion: v1
kind: Pod
spec:
containers:
- name: app
volumeMounts:
- name: all-in-one
mountPath: /etc/config
volumes:
- name: all-in-one
projected:
sources:
- configMap:
name: app-config
- secret:
name: app-secrets
- downwardAPI:
items:
- path: labels
fieldRef:
fieldPath: metadata.labels

3 - Persistent Volumes (PV)

3.1 Qu'est-ce qu'un PV ?

Un PersistentVolume est une ressource de stockage provisionnée dans le cluster.

3.2 Créer un PV statique

# pv-nfs.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv
labels:
type: nfs
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: manual
nfs:
server: 192.168.1.100
path: /exports/data

---
# pv-local.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-pv
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /mnt/disks/ssd1
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- worker-1

3.3 Access Modes

ModeAbréviationDescription
ReadWriteOnceRWOLecture/écriture par un seul Node
ReadOnlyManyROXLecture seule par plusieurs Nodes
ReadWriteManyRWXLecture/écriture par plusieurs Nodes
ReadWriteOncePodRWOPLecture/écriture par un seul Pod

3.4 Reclaim Policies

PolicyDescription
RetainGarde les données après suppression du PVC
DeleteSupprime le volume et les données
RecycleEfface les données (deprecated)

4 - Persistent Volume Claims (PVC)

4.1 Créer un PVC

# pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: manual
# Optionnel: sélectionner un PV spécifique
selector:
matchLabels:
type: nfs

4.2 Utiliser un PVC dans un Pod

apiVersion: v1
kind: Pod
metadata:
name: app-with-storage
spec:
containers:
- name: app
image: postgres:14
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumes:
- name: data
persistentVolumeClaim:
claimName: app-storage

4.3 Cycle de vie PV/PVC


5 - Storage Classes

5.1 Provisionnement dynamique

Les StorageClasses permettent le provisionnement automatique de PV.

5.2 Créer une StorageClass

# AWS EBS
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-storage
provisioner: ebs.csi.aws.com
parameters:
type: gp3
iops: "3000"
throughput: "125"
reclaimPolicy: Delete
allowVolumeExpansion: true
volumeBindingMode: WaitForFirstConsumer

---
# GCP Persistent Disk
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ssd-storage
provisioner: pd.csi.storage.gke.io
parameters:
type: pd-ssd
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer

---
# Azure Disk
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: azure-premium
provisioner: disk.csi.azure.com
parameters:
skuName: Premium_LRS
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer

5.3 Utiliser une StorageClass

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: dynamic-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
storageClassName: fast-storage # Référence la StorageClass

5.4 StorageClass par défaut

# Voir les StorageClasses
kubectl get storageclass

# Définir comme défaut
kubectl patch storageclass fast-storage -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

6 - Volume Expansion

6.1 Agrandir un PVC

# La StorageClass doit avoir allowVolumeExpansion: true
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: expandable-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi # Initialement 5Gi
storageClassName: fast-storage
# Modifier la taille
kubectl patch pvc expandable-pvc -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'

# Vérifier
kubectl get pvc expandable-pvc

7 - StatefulSets et stockage

7.1 VolumeClaimTemplates

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
ports:
- containerPort: 3306
volumeMounts:
- name: data
mountPath: /var/lib/mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: password

# Crée automatiquement un PVC par replica
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: fast-storage
resources:
requests:
storage: 10Gi

8 - CSI (Container Storage Interface)

8.1 Qu'est-ce que CSI ?

CSI est le standard pour connecter des systèmes de stockage à Kubernetes.

8.2 Drivers CSI populaires

DriverStorage
ebs.csi.aws.comAWS EBS
disk.csi.azure.comAzure Disk
pd.csi.storage.gke.ioGCP Persistent Disk
cephfs.csi.ceph.comCephFS
nfs.csi.k8s.ioNFS

8.3 Installer un driver CSI (exemple AWS EBS)

# Ajouter le repo Helm
helm repo add aws-ebs-csi-driver https://kubernetes-sigs.github.io/aws-ebs-csi-driver

# Installer
helm install aws-ebs-csi-driver aws-ebs-csi-driver/aws-ebs-csi-driver \
--namespace kube-system \
--set controller.serviceAccount.create=true \
--set controller.serviceAccount.name=ebs-csi-controller-sa

9 - Volume Snapshots

9.1 Créer un Snapshot

# VolumeSnapshotClass
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
name: csi-snapclass
driver: ebs.csi.aws.com
deletionPolicy: Delete

---
# VolumeSnapshot
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: pvc-snapshot
spec:
volumeSnapshotClassName: csi-snapclass
source:
persistentVolumeClaimName: my-pvc

9.2 Restaurer depuis un Snapshot

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: restored-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: fast-storage
dataSource:
name: pvc-snapshot
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io

10 - Exemple complet : Base de données PostgreSQL

# Secret pour le mot de passe
apiVersion: v1
kind: Secret
metadata:
name: postgres-secret
stringData:
password: supersecret123

---
# StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: postgres-storage
provisioner: ebs.csi.aws.com
parameters:
type: gp3
reclaimPolicy: Retain
allowVolumeExpansion: true

---
# PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
storageClassName: postgres-storage

---
# Deployment PostgreSQL
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:15
ports:
- containerPort: 5432
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 1
memory: 1Gi
volumes:
- name: data
persistentVolumeClaim:
claimName: postgres-data

---
# Service
apiVersion: v1
kind: Service
metadata:
name: postgres
spec:
type: ClusterIP
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432

Résumé

Dans ce chapitre, nous avons appris :

  • Les différents types de volumes (emptyDir, hostPath, etc.)
  • Les Persistent Volumes et Persistent Volume Claims
  • Le provisionnement dynamique avec StorageClasses
  • L'expansion de volumes
  • Les StatefulSets et volumeClaimTemplates
  • Les drivers CSI et snapshots

Prochaine étape

Dans le prochain chapitre, nous explorerons les Namespaces et RBAC pour l'isolation et la sécurité.

→ Chapitre suivant : Namespaces et RBAC


← Retour à la table des matières