Gestion du stockage
Vue d'ensemble
Le stockage dans Kubernetes est géré via un système de ressources découplant les Pods de l'infrastructure de stockage sous-jacente. Ce document décrit les options de stockage disponibles sur le cluster Kubernetes SdV, leurs cas d'usage, leurs limites et les bonnes pratiques associées.
Concepts clés
| Concept | Description | Rôle |
|---|---|---|
PersistentVolume (PV) | Ressource de stockage physique dans le cluster | Représente un espace de stockage disponible |
PersistentVolumeClaim (PVC) | Demande de stockage par un utilisateur | Consomme un PV et l'attache à un Pod |
StorageClass | Définit les classes de stockage disponibles | Permet le provisionnement dynamique des PV |
VolumeSnapshot | Point de sauvegarde d'un volume | Permet la restauration et la duplication |
Stockage Persistant
SdV propose dans son catalogue une classe de stockage NFS pour le stockage persistant des données des workloads Kubernetes. Cette solution est adaptée au stockage de fichiers nécessitant un accès concurrent depuis plusieurs Pods.
StorageClasses disponibles
StorageClass | Type | Politique de rétention | Provisionnement | Cas d'usage recommandé |
|---|---|---|---|---|
managed-nfs-storage | fichier | Delete | Dynamique | Développement, staging, données temporaires |
managed-nfs-storage-retain | fichier | Retain | Dynamique | Production, données critiques nécessitant une conservation manuelle |
Politique de rétention
Delete: LePersistentVolumeet les données associées sont automatiquement supprimés lorsque lePVCest détruit. ⚠️ Risque de perte de données.Retain: LePersistentVolumeest conservé même après la suppression duPVC. Les données restent disponibles et doivent être supprimées manuellement par un administrateur.
Stockage en mode fichier (NFS)
Cette StorageClass est basée sur le protocole NFS (Network File System). Elle permet de partager un système de fichiers entre plusieurs Pods simultanément.
Caractéristiques
| Critère | Valeur | Commentaire |
|---|---|---|
| Protocole | NFSv3/NFSv4 | Protocole réseau pour partage de fichiers |
| Performance | Moyenne (réseau) | Latence dépendante du réseau (~1-5ms) |
| IOPS | Faibles à moyennes | Non adapté aux charges intensives en I/O |
| Débit | ~100-500 MB/s | Dépendant du réseau et de la charge |
| Accès concurrent | Oui (ReadWriteMany) | Plusieurs Pods peuvent lire/écrire simultanément |
Cas d'usage recommandés
✅ Adapté pour :
- Applications web stateless (assets, uploads utilisateurs)
- Partage de fichiers de configuration entre Pods
- Stockage de fichiers médias (images, vidéos, documents)
- Logs d'applications à centraliser
- Dossiers partagés pour traitement batch
- CMS (WordPress, Drupal, etc.)
- Applications nécessitant
ReadWriteMany
❌ Déconseillé pour :
- Bases de données relationnelles (PostgreSQL, MySQL, MariaDB)
- Bases de données NoSQL nécessitant des IOPS élevées (Cassandra, MongoDB)
- Applications nécessitant des performances disque élevées
- Stockage de données nécessitant une forte cohérence transactionnelle
- Workloads avec des milliers d'opérations I/O par seconde
Modes d'accès supportés
| Mode | Abréviation | Description | Support NFS |
|---|---|---|---|
ReadWriteOnce | RWO | Lecture-écriture par un seul nœud | Oui |
ReadOnlyMany | ROX | Lecture seule par plusieurs nœuds | Oui |
ReadWriteMany | RWX | Lecture-écriture par plusieurs nœuds | Oui (principal avantage NFS) |
Exemple de PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: webapp-storage
namespace: production
labels:
app: webapp
environment: production
annotations:
description: "Stockage partagé pour les uploads utilisateurs"
spec:
storageClassName: managed-nfs-storage-retain
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10GiUtilisation dans un Pod
apiVersion: v1
kind: Pod
metadata:
name: webapp-pod
namespace: production
labels:
app: webapp
spec:
containers:
- name: webapp
image: myapp:1.0.0
volumeMounts:
- name: persistent-storage
mountPath: /var/www/html/uploads
subPath: uploads # Utilise un sous-répertoire du PVC
volumes:
- name: persistent-storage
persistentVolumeClaim:
claimName: webapp-storageExemple avec Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: myapp:1.0.0
volumeMounts:
- name: shared-data
mountPath: /data/shared
readOnly: false
volumes:
- name: shared-data
persistentVolumeClaim:
claimName: webapp-storageAutres types de stockage
Kubernetes propose par défaut plusieurs types de volumes pour le stockage. Tous ne sont pas persistants et présentent des caractéristiques différentes. Voir la documentation officielle pour une liste exhaustive.
Stockage objet S3
SdV propose offres de stockage objet compatible S3 pour les besoins de stockage massif, d'archivage ou de distribution de contenu statique.
Caractéristiques
| Critère | Valeur |
|---|---|
| Type | Stockage objet (Object Storage) |
| Protocole | API REST S3 (compatible AWS S3) |
| Durabilité | Très élevée (réplication multi-zones) |
| Scalabilité | Illimitée |
| Performance | Optimisé pour le throughput, pas pour la latence |
Cas d'usage
✅ Adapté pour :
- Stockage de backups et archives
- Distribution de contenu statique (CDN)
- Data lakes et analytics
- Stockage d'images et vidéos à grande échelle
- Logs applicatifs (via Fluentd, Loki, etc.)
- Artefacts de build (images Docker, binaires)
Intégration avec Kubernetes
Le stockage S3 n'est pas directement monté comme un volume Kubernetes. L'accès se fait via :
- SDK applicatif : Boto3 (Python), AWS SDK (Java, Node.js, Go...)
- S3 FUSE : Monte un bucket S3 comme système de fichiers (performances limitées)
Exemple d'utilisation avec des secrets
apiVersion: v1
kind: Secret
metadata:
name: s3-credentials
namespace: production
type: Opaque
stringData:
access-key: "AKIAIOSFODNN7EXAMPLE"
secret-key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"emptyDir
Un volume emptyDir est créé lorsqu'un Pod est assigné à un nœud et existe aussi longtemps que le Pod s'exécute sur ce nœud. Comme son nom l'indique, le volume est initialement vide. Tous les conteneurs du Pod peuvent lire et écrire dans ce volume.
Caractéristiques
| Critère | Valeur |
|---|---|
| Persistance | Non persistant (supprimé avec le Pod) |
| Localisation | Disque local du nœud ou RAM |
| Partage | Entre conteneurs d'un même Pod uniquement |
| Taille | Limitée par l'espace disque/RAM du nœud |
Cas d'usage
✅ Adapté pour :
- Cache temporaire d'une application
- Échange de données entre conteneurs d'un même
Pod(sidecars) - Espace de travail pour traitements temporaires
- Stockage de fichiers de session éphémères
❌ Déconseillé pour :
- Données devant survivre au redémarrage du
Pod - Volumétries importantes (>100 Mo)
- Données critiques nécessitant une persistance
Exemple avec stockage disque
apiVersion: v1
kind: Pod
metadata:
name: webapp-cache
namespace: production
labels:
app: webapp
spec:
containers:
- name: webapp
image: nginx:1.25
volumeMounts:
- name: cache-volume
mountPath: /var/cache/nginx
- name: cache-warmer
image: busybox:1.36
command: ['sh', '-c', 'while true; do date > /cache/timestamp; sleep 60; done']
volumeMounts:
- name: cache-volume
mountPath: /cache
volumes:
- name: cache-volume
emptyDir:
sizeLimit: 100Mi # Limite la taille du volumeExemple avec stockage en RAM (tmpfs)
Pour optimiser les temps d'accès, il est possible d'utiliser un stockage en RAM (tmpfs) en définissant le champ emptyDir.medium à Memory.
apiVersion: v1
kind: Pod
metadata:
name: high-speed-cache
namespace: production
spec:
containers:
- name: app
image: myapp:1.0.0
resources:
requests:
memory: "256Mi" # Inclut l'emptyDir en mémoire
limits:
memory: "512Mi"
volumeMounts:
- name: tmp-cache
mountPath: /tmp/cache
volumes:
- name: tmp-cache
emptyDir:
medium: Memory
sizeLimit: 128Mi # Taille max en RAMConfigMap et Secret (volumes projetés)
Les ConfigMap et Secret peuvent être montés comme volumes dans les Pods pour injecter des fichiers de configuration ou des informations sensibles.
Exemple avec ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: production
data:
app.conf: |
server {
listen 80;
server_name example.com;
}
settings.json: |
{
"debug": false,
"max_connections": 100
}Exemple avec Secret
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
namespace: production
type: Opaque
stringData:
username: admin
password: "P@ssw0rd!Secure"Commandes utiles
Gestion des PersistentVolumeClaims
# Lister les PVC dans le namespace courant
kubectl get pvc
# Lister les PVC dans tous les namespaces
kubectl get pvc --all-namespaces
# Détails d'un PVC
kubectl describe pvc <nom-pvc> -n <namespace>
# Voir les événements liés à un PVC
kubectl get events --field-selector involvedObject.name=<nom-pvc> -n <namespace>
# Supprimer un PVC
kubectl delete pvc <nom-pvc> -n <namespace>Gestion des PersistentVolumes
# Lister tous les PV du cluster
kubectl get pv
# Détails d'un PV
kubectl describe pv <nom-pv>
# Voir les PV avec leur statut et leur claim
kubectl get pv -o wide
# Filtrer les PV disponibles
kubectl get pv --field-selector status.phase=AvailableGestion des StorageClasses
# Lister les StorageClasses disponibles
kubectl get storageclass
kubectl get sc # Alias
# Détails d'une StorageClass
kubectl describe sc managed-nfs-storageVérification de l'utilisation du stockage
# Voir l'utilisation disque dans un Pod
kubectl exec -it <nom-pod> -n <namespace> -- df -h
# Taille d'un répertoire monté
kubectl exec -it <nom-pod> -n <namespace> -- du -sh /path/to/mount
# Lister les fichiers d'un volume
kubectl exec -it <nom-pod> -n <namespace> -- ls -lah /path/to/mountBonnes pratiques
Choix de la politique de rétention
| Environnement | StorageClass recommandée | Justification |
|---|---|---|
| Production | managed-nfs-storage-retain | Évite la suppression accidentelle des données |
| Staging | managed-nfs-storage-retain | Facilite les tests de restauration |
| Développement | managed-nfs-storage | Simplifie le nettoyage automatique |
| CI/CD | managed-nfs-storage | Volumes éphémères pour les tests |
Dimensionnement des volumes
- Anticiper la croissance : Prévoir 30-50% de marge par rapport aux besoins initiaux
- Surveiller l'utilisation : Mettre en place des alertes sur l'espace disque (ex: >80%)
- Tester l'extension : Vérifier si la
StorageClasssupporte l'expansion de volume (allowVolumeExpansion)
Sécurité
# Utiliser des permissions restrictives
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
containers:
- name: app
image: myapp:1.0.0
volumeMounts:
- name: data
mountPath: /data
readOnly: false # false pour écriture, true pour lecture seule
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000 # Group ID pour les permissions des fichiers
allowPrivilegeEscalation: false
volumes:
- name: data
persistentVolumeClaim:
claimName: app-dataNommage et labels
Adopter une convention de nommage claire :
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: <app>-<type>-<env> # Ex: webapp-uploads-prod
namespace: production
labels:
app: webapp
component: storage
environment: production
storage-type: nfs
annotations:
owner: "team-platform@example.com"
description: "Stockage des uploads utilisateurs"
backup: "enabled"Gestion du cycle de vie
- Création : Toujours définir
storageClassNameexplicitement - Utilisation : Monitorer l'espace disque et les performances
- Mise à jour : Tester l'extension de volume en pré-production
- Suppression :
- Pour
Retain: Supprimer manuellement lePVaprès vérification - Documenter les
PVorphelins et leur contenu - Archiver les données avant suppression définitive
- Pour
Monitoring et alerting
Métriques à surveiller :
- Utilisation de l'espace disque : Pourcentage d'utilisation du
PVC - Latence I/O : Temps de réponse des opérations disque
- Erreurs de montage : Échecs de binding
PVC/PV - PV orphelins : PV en statut
Releasedaprès suppression duPVC
Exemple d'alerte Prometheus :
# Alerte si un PVC est rempli à plus de 85%
- alert: PVCAlmostFull
expr: |
kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes > 0.85
for: 10m
labels:
severity: warning
annotations:
summary: "PVC {{ $labels.persistentvolumeclaim }} presque plein"
description: "Le PVC est rempli à {{ $value | humanizePercentage }}"Dépannage
Problèmes courants
PVC en état Pending
Causes possibles :
- Aucun
PVdisponible correspondant aux critères StorageClassinexistante ou mal configurée- Quota de stockage dépassé
- Provisioner NFS indisponible
# Vérifier l'état du PVC
kubectl describe pvc <nom-pvc> -n <namespace>
# Vérifier les événements
kubectl get events -n <namespace> --sort-by='.lastTimestamp'
# Vérifier les PV disponibles
kubectl get pv --field-selector status.phase=AvailableErreur de montage dans le Pod
Causes possibles :- Serveur NFS inaccessible
- Permissions insuffisantes
- Volume déjà monté en exclusif (
RWO) sur un autre nœud
# Voir les événements du Pod
kubectl describe pod <nom-pod> -n <namespace>
# Vérifier les logs du CSI driver (si applicable)
kubectl logs -n kube-system -l app=nfs-provisionerPerformance dégradée
Actions :- Vérifier la charge réseau vers le serveur NFS
- Analyser les I/O du Pod :
kubectl exec <pod> -- iostat -x 5 - Contacter le support SdV pour vérifier l'état de la baie de stockage