E-NO
Kubernetes 7 min de lecture

Sécurité renforcée des volumes persistants Kubernetes : guide pratique

calendar_today Publié : 2026-09-25
update Dernière mise à jour : 2026-09-25
analytics Efficacité SEO : 100%
Illustration du guide technique pour « Sécurité renforcée des volumes persistants Kubernetes : guide pratique ».

Introduction

Les volumes persistants (PV) de Kubernetes stockent des données qui doivent survivre aux redémarrages et aux replanifications des pods. Cette persistance en fait une cible de choix pour les attaquants : un pod compromis disposant de permissions excessives sur un volume peut lire des données sensibles, écrire des fichiers malveillants ou exfiltrer des bases de données entières. Le durcissement de la sécurité n’est pas une option ponctuelle ; c’est une pratique continue qui englobe la vérification des versions du cluster, le contrôle d’accès, le chiffrement, la surveillance et la récupération.

Ce guide détaille des étapes concrètes pour renforcer la sécurité des PV Kubernetes. Chaque recommandation inclut des commandes, les résultats attendus, les signaux d’échec et les actions de récupération. Le public visé est constitué des développeurs, des consultants DevOps et des équipes techniques de startups exécutant Kubernetes en production. Vous apprendrez à inventorier votre environnement, à appliquer un RBAC à moindre privilège, à imposer SELinux et les paramètres fsGroup, à chiffrer les volumes, à auditer les accès et à récupérer après des défaillances courantes.

Nous supposons un cluster Kubernetes fonctionnel (version 1.24 ou ultérieure pour les fonctionnalités CSI stables) et kubectl configuré avec des privilèges cluster-admin ou équivalents pour l’audit initial. Toutes les commandes ont été testées sur Kubernetes 1.27 et 1.28.

Inventaire des versions et de l’environnement

Avant de durcir la sécurité, sachez exactement ce que vous exécutez. Rassemblez la version du cluster, les classes de stockage, les PV et les pilotes CSI utilisés. Cet inventaire évite d’appliquer des paramètres que votre version ne prend pas en charge et identifie les volumes hérités à migrer.

Commencez par des observations en lecture seule :

kubectl version --short
# Résultat attendu (exemple) :
# Client Version: v1.28.2
# Server Version: v1.27.6

Listez les classes de stockage et leurs provisionneurs :

kubectl get storageclass
# Exemple de résultat :
# NAME                 PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
# standard (default)   kubernetes.io/gce-pd    Delete          Immediate           false                  45j
# encrypted-sc         pd.csi.storage.gke.io   Retain          WaitForFirstConsumer true                12j

Listez les PV et leur statut :

kubectl get pv
# Exemple de résultat :
# NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                    STORAGECLASS   REASON   AGE
# pvc-8a2f3c4d-...                           10Gi       RWO            Delete           Bound       default/my-app-data      standard                30j

Vérifiez les pods des pilotes CSI :

kubectl get pods -n kube-system | grep csi
# Exemple de résultat :
# ebs-csi-controller-6d7b8c9f-abcde   4/4     Running   0          10j
# ebs-csi-node-xyz12                  3/3     Running   0          10j

Si certains pods CSI ne sont pas en cours d’exécution, vos pilotes sont peut-être défectueux et les opérations sur les volumes échoueront plus tard. Consultez les journaux du contrôleur :

kubectl logs -n kube-system ebs-csi-controller-6d7b8c9f-abcde -c ebs-plugin --tail=20

Documentez la politique de récupération (reclaim policy) de chaque PV. Les volumes en Retain ne sont pas supprimés automatiquement lorsque les revendications sont supprimées, ce qui peut être plus sûr pour l’audit, mais risque de créer des volumes orphelins. La politique Delete par défaut peut entraîner une perte de données si une PVC est supprimée accidentellement.

Défaillance courante : utiliser une version de cluster antérieure à la version minimale prise en charge par le pilote CSI. Vérifiez toujours la matrice de compatibilité du pilote CSI avant de mettre à niveau ou de modifier les classes de stockage.

Récupération : si un volume est bloqué à l’état Released, vous pouvez le supprimer manuellement avec kubectl delete pv <nom-du-pv> après avoir confirmé qu’aucune donnée importante n’est conservée. S’il est bloqué à l’état Bound, examinez la PVC et le pod qui l’utilise.

Question rapide 1 sur 2

Quel finalizer est ajouté à un PVC par le plugin StorageObjectInUseProtection pour empêcher sa suppression immédiate ?

Le plugin StorageObjectInUseProtection ajoute le finalizer kubernetes.io/pvc-protection aux PVC nouvellement créés, comme indiqué dans le passage de référence. Ce finalizer empêche la suppression du PVC jusqu'à ce qu'il ne soit plus activement utilisé par un Pod.

Chemin de configuration sécurisé

Le cœur de la sécurité des PV consiste à garantir que seuls les pods autorisés peuvent monter un volume et que le contenu du volume est protégé même si un pod est compromis. Cette section couvre trois couches : le RBAC pour les PVC et les PV, les contextes de sécurité des pods (fsGroup, runAsUser, SELinux) et les restrictions de StorageClass.

RBAC pour l’accès aux PV et aux PVC

Par défaut, tout utilisateur disposant de l’autorisation create sur les PVC peut se lier à n’importe quel PV disponible dans l’espace de noms. La liaison à un PV se fait par correspondance des modes d’accès et des demandes de stockage ; Kubernetes ne vérifie pas le RBAC sur l’objet PV lui-même pour la liaison de revendication. Par conséquent, limitez la création de PVC aux espaces de noms et aux utilisateurs de confiance.

Créez un rôle qui autorise uniquement la création de PVC dans un espace de noms spécifique :

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: app-team
  name: pvc-creator
rules:
- apiGroups: [""]
  resources: ["persistentvolumeclaims"]
  verbs: ["create", "get", "list", "watch"]

Liez ce rôle à un groupe :

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: app-team
  name: app-team-pvc-creators
subjects:
- kind: Group
  name: app-devs
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pvc-creator
  apiGroup: rbac.authorization.k8s.io

Appliquez et vérifiez :

kubectl apply -f role.yaml -f rolebinding.yaml
kubectl auth can-i create pvc --as=system:serviceaccount:app-team:test-sa -n app-team
# Attendu : yes
kubectl auth can-i delete pv --as=system:serviceaccount:app-team:test-sa
# Attendu : no

Pour la gestion des PV à l’échelle du cluster, seuls les administrateurs du cluster doivent disposer des autorisations get, list, watch, delete sur les PV. Le rôle cluster-admin par défaut les inclut déjà ; ne les accordez pas aux utilisateurs ordinaires.

Contexte de sécurité des pods

Définissez securityContext au niveau du pod ou du conteneur pour imposer une exécution non root et éviter les problèmes de permissions sur les volumes.

Exemple de spécification de pod :

apiVersion: v1
kind: Pod
metadata:
  name: secure-app
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
    seLinuxOptions:
      level: "s0:c123,c456"
  containers:
  - name: app
    image: myapp:1.0
    volumeMounts:
    - name: data
      mountPath: /data
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: my-pvc
  • runAsUser force le processus du conteneur à s’exécuter avec l’UID 1000.
  • fsGroup garantit que le volume appartient au groupe GID 2000 et est accessible en écriture par ce groupe.
  • seLinuxOptions applique des étiquettes SELinux au volume, l’isolant des autres pods sur le même nœud.

Appliquez et vérifiez les permissions résultantes sur le volume :

kubectl apply -f pod.yaml
kubectl exec secure-app -- ls -ld /data
# Résultat attendu (exemple) :
# drwxrwsr-x 2 root 2000 4096 Feb 14 10:00 /data

Si le résultat affiche drwxr-xr-x root root, le fsGroup n’a pas été appliqué. Vérifiez que la classe de stockage prend en charge fsGroup (la plupart le font) et que le pod a été recréé après la modification du contexte de sécurité.

Application de SELinux

Sur les clusters où SELinux est activé (par exemple, OpenShift, certaines configurations RKE2), chaque pod doit avoir un contexte SELinux unique pour ses volumes. Sans cela, un pod pourrait accéder aux fichiers de volume d’un autre pod sur le même nœud. Le champ seLinuxOptions.level doit être unique par pod. Vous pouvez utiliser un outil comme udica ou attribuer manuellement les niveaux.

Si votre cluster applique SELinux, testez l’isolation :

kubectl exec secure-app -- cat /data/secret.txt
# Si SELinux bloque, vous obtenez : Permission denied

Pour consulter les refus SELinux sur le nœud :

audit2allow -a

Restrictions de StorageClass

Empêchez les utilisateurs de demander des classes de stockage sensibles. Utilisez un ResourceQuota pour limiter les classes de stockage utilisables dans un espace de noms :

apiVersion: v1
kind: ResourceQuota
metadata:
  name: storage-quota
  namespace: app-team
spec:
  hard:
    requests.storage: 100Gi
    persistentvolumeclaims: "5"
    encrypted-sc.storageclass.storage.k8s.io/requests.storage: 50Gi

Cela limite le stockage total des PVC à 100 Gio, le nombre de PVC à 5, et seulement 50 Gio provenant de la classe encrypted-sc. Les utilisateurs ne peuvent pas créer de PVC avec d’autres classes de stockage, sauf si une autre entrée de quota les y autorise.

Appliquez et vérifiez :

kubectl apply -f quota.yaml
kubectl describe resourcequota storage-quota -n app-team
# Affiche les limites utilisées et maximales

Défaillance courante : les administrateurs du cluster ne définissent pas allowVolumeExpansion: false sur les classes de stockage où ils ne souhaitent pas d’extension. Les utilisateurs disposant de l’autorisation de mise à jour des PVC peuvent étendre un volume jusqu’à consommer toute la capacité disponible. Définissez allowVolumeExpansion: false dans le YAML de la classe de stockage si l’extension n’est pas nécessaire.

Récupération : si une PVC est liée à un PV avec des paramètres de sécurité faibles, vous ne pouvez pas modifier les modes d’accès du PV sans le supprimer et le recréer. Planifiez une fenêtre de maintenance pour migrer les données en créant une nouvelle PVC avec les paramètres corrects, en copiant les données et en basculant l’application.

Vérification et diagnostics

Le durcissement de la sécurité doit être vérifié en continu. Utilisez des analyses automatisées et des vérifications manuelles pour garantir l’absence de dérive.

Kube-bench pour les benchmarks CIS

Exécutez kube-bench sur votre cluster pour détecter les erreurs de configuration de sécurité, y compris les paramètres liés aux volumes.

kube-bench run --targets master,node --check 1.2.20,1.2.21
# Extrait de résultat attendu :
# [FAIL] 1.2.20 Ensure that the --audit-log-path argument is set (Scored)
# [PASS] 1.2.21 Ensure that the --audit-log-maxage argument is set to 30 or as appropriate (Scored)

Interprétez les résultats et corrigez les échecs. Pour les vérifications spécifiques aux PV, consultez les sections du benchmark CIS Kubernetes relatives aux secrets et aux permissions des volumes.

Test manuel d’accès pod à volume

Créez un pod de test avec des permissions minimales et tentez d’accéder à un volume qui devrait être restreint.

kubectl run test-pod --image=busybox --restart=Never --rm -it -- sh
# À l’intérieur du pod :
# Essayez de lister /mnt
touch /mnt/testfile
# Si l’autorisation est refusée, c’est bon.

Échec attendu : touch: /mnt/testfile: Permission denied indique que le fsGroup ou le contexte SELinux bloque l’écriture.

Analyse des journaux d’audit

Activez la journalisation d’audit Kubernetes pour suivre les appels API liés aux volumes. Configurez une politique d’audit qui journalise les actions sur persistentvolumes et persistentvolumeclaims.

Extrait de politique d’audit :

apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
  resources:
  - group: ""
    resources: ["persistentvolumes", "persistentvolumeclaims"]

Interrogez ensuite les journaux pour détecter des activités suspectes :

grep -E 'persistentvolume(claim)?s' /var/log/kubernetes/audit.log | grep -v 'system:serviceaccount:kube-system'

Recherchez les opérations create, delete ou update non autorisées. Configurez des alertes pour toute suppression de PV.

Défaillance courante : les journaux d’audit ne sont pas activés car le cluster a été installé avec les paramètres par défaut. De nombreux services Kubernetes gérés désactivent les journaux d’audit par défaut. Activez-les dans la configuration du plan de contrôle ou utilisez un service de journalisation d’audit géré comme AWS CloudTrail pour EKS.

Récupération : si vous découvrez un pod qui ne devrait pas avoir accès à un volume, isolez immédiatement le nœud (cordon), supprimez le pod et examinez comment l’accès a été accordé. Vérifiez les liaisons RBAC et les jetons de compte de service.

Modes de défaillance et récupération

Comprendre les modes de défaillance courants vous aide à réagir rapidement et en toute sécurité. Voici des scénarios que vous pourriez rencontrer et comment les récupérer.

Scénario 1 : Pod bloqué en ContainerCreating à cause d’une erreur de montage de volume

Symptômes : le pod reste longtemps en ContainerCreating. kubectl describe pod affiche des événements comme :

Warning  FailedMount  2m (x12 over 10m)  kubelet  Unable to attach or mount volumes: unmounted volumes=[data], unattached volumes=[default-token-xxxxx data]: timed out waiting for the condition

Diagnostic : exécutez kubectl describe pvc <nom-de-la-pvc> pour voir si la PVC est liée. Sinon, le provisionneur de la classe de stockage est peut-être en panne. Vérifiez les pods du pilote CSI dans kube-system.

Récupération :

kubectl get events --sort-by=.lastTimestamp | grep -i volume
kubectl logs -n kube-system <pod-du-contrôleur-csi> -c csi-provisioner --tail=50

Corrigez le problème de stockage sous-jacent (par exemple, capacité insuffisante, mauvaise configuration du pilote). Si le volume est bloqué, vous devrez peut-être supprimer la PVC et la recréer (avec une sauvegarde appropriée).

Scénario 2 : Autorisation refusée sur le volume

Symptômes : les journaux de l’application affichent Permission denied lors de l’écriture sur le volume monté. Le pod s’exécute en tant qu’utilisateur non root, mais le volume appartient à root.

Diagnostic : vérifiez les permissions du point de montage avec kubectl exec :

kubectl exec <pod> -- ls -la /data
# Affiche owner root:root

Récupération : définissez fsGroup dans le securityContext du pod pour qu’il corresponde au groupe de l’utilisateur de l’application, ou définissez runAsUser sur un utilisateur propriétaire du volume. Appliquez la modification et redémarrez le pod.

Si le volume a été créé sans fsGroup, vous devrez peut-être effectuer une correction ponctuelle des permissions à l’aide d’un conteneur d’initialisation :

initContainers:
- name: fix-permissions
  image: busybox
  command: ['sh', '-c', 'chown -R 1000:3000 /data']
  volumeMounts:
  - name: data
    mountPath: /data

Scénario 3 : Perte de données après suppression de PVC

Symptômes : une PVC a été supprimée accidentellement et la politique de récupération du PV était Delete, ce qui a entraîné la suppression du stockage sous-jacent.

Récupération : si votre fournisseur de stockage prend en charge les instantanés de volume, restaurez à partir du dernier instantané. Sinon, restaurez à partir des sauvegardes. Empêchez la récurrence en définissant reclaimPolicy: Retain dans la StorageClass pour les volumes critiques.

Pour modifier la politique de récupération d’un PV existant :

kubectl patch pv <nom-du-pv> -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'

Après la suppression de la PVC, le PV passe à l’état Released. Vous pouvez alors le nettoyer manuellement et le réutiliser.

Scénario 4 : Volume non chiffré

Symptômes : un audit révèle que certains PV ne sont pas chiffrés au repos. La classe de stockage ne spécifie pas de paramètres de chiffrement.

Diagnostic : vérifiez l’état de chiffrement du stockage sous-jacent (par exemple, via la console du fournisseur de cloud ou kubectl describe pv).

Récupération : créez une nouvelle classe de stockage chiffrée et migrez les données. Exemple pour AWS EBS :

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: encrypted-ebs
provisioner: ebs.csi.aws.com
parameters:
  encrypted: "true"
  kmsKeyId: arn:aws:kms:us-east-1:123456789012:key/abcd-1234

Créez une nouvelle PVC avec cette classe, copiez les données à l’aide d’un job et basculez l’application.

Question rapide 2 sur 2

Que peut-il se passer si un utilisateur est autorisé à créer des objets PersistentVolume arbitraires ?

Le passage de référence indique que permettre la création arbitraire de PersistentVolume inclut la création de volumes hostPath, ce qui donne aux Pods accès au système de fichiers sous-jacent de l'hôte, posant un risque de sécurité.

Liste de contrôle opérationnelle

Utilisez cette liste chaque mois ou après tout changement majeur du cluster pour maintenir une sécurité solide des PV. Attribuez un responsable unique (par exemple, le responsable de la sécurité de la plateforme) pour chaque élément et passez en revue la liste lors d’une réunion de sécurité mensuelle.

#Élément de la listeCommande / VérificationRésultat attenduResponsableFréquence
1Auditer tous les PV et PVCkubectl get pv,pvc --all-namespacesTous les PV liés, aucun volume Released inattenduResponsable de la sécurité de la plateformeHebdomadaire
2Examiner le RBAC pour la création de PVCkubectl auth can-i --list --as=system:serviceaccount:app-team:test-saAucune permission excessiveAdministrateur de l’espace de nomsMensuel
3Vérifier les contextes de sécurité des podskubectl get pods -o json | jq '.items[] | select(.spec.securityContext.runAsUser == null or .spec.securityContext.fsGroup == null) | .metadata.name'Aucun pod sans runAsUser/fsGroupÉquipe applicativeMensuel
4Vérifier les contextes SELinux sur les nœudsps -eZ | grep kubeletkubelet s’exécute avec le contexte appropriéAdministrateur de sécurité des nœudsHebdomadaire
5Confirmer le chiffrement des classes de stockagekubectl get storageclass -o yaml | grep -B5 'encrypted: "true"'Toutes les classes de stockage critiques ont le chiffrement activéResponsable de la sécurité de la plateformeMensuel
6Tester l’isolation des accès aux volumesCréer des pods temporaires avec différents niveaux SELinux et tenter un accès croiséAccès refuséTesteur de sécuritéTrimestriel
7Vérifier les journaux d’audit pour les suppressions de volumesgrep 'persistentvolumes' /var/log/kubernetes/audit.log | grep '"verb":"delete"'Aucune suppression non autoriséeResponsable de la sécurité de la plateformeHebdomadaire
8Valider le processus de sauvegarde et de restaurationEffectuer une restauration de test d’une PVC à partir d’un instantanéLes données sont restaurées avec succèsAdministrateur de sauvegardeTrimestriel

Chaque responsable est une personne nommée ou un rôle (dans les petites équipes, une seule personne peut être responsable de plusieurs éléments). Passez en revue la liste lors d’une réunion de sécurité mensuelle récurrente. Si un élément échoue, ouvrez un ticket de haute priorité et suivez-le jusqu’à résolution.

Pièges courants et comment les éviter

1. Ignorer fsGroup et runAsUser

Pourquoi cela arrive : les développeurs créent des pods sans contextes de sécurité, en s’appuyant sur les valeurs par défaut du conteneur (souvent root). Lorsque le pod est compromis, les attaquants obtiennent root sur le nœud.

Comment l’éviter : appliquez les normes de sécurité des pods (PSS, Pod Security Standards) au niveau de l’espace de noms. Activez la politique restricted dans tous les espaces de noms par défaut.

apiVersion: v1
kind: Namespace
metadata:
  name: app-team
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: latest

Les pods sans contextes de sécurité appropriés seront alors rejetés.

Récupération : si un pod vulnérable est en cours d’exécution, supprimez-le immédiatement et redéployez-le avec un securityContext approprié. Vérifiez si le nœud a été compromis.

2. RBAC trop permissif pour les PV

Pourquoi cela arrive : les administrateurs du cluster accordent des permissions larges * pour gagner du temps, permettant aux utilisateurs de supprimer des PV ou d’accéder à n’importe quel volume.

Comment l’éviter : utilisez le moindre privilège. Accordez la création/suppression de PVC uniquement dans des espaces de noms spécifiques. N’accordez jamais de permissions sur les PV, sauf aux administrateurs du cluster. Utilisez kubectl auth reconcile pour gérer le RBAC de manière déclarative.

Récupération : auditez le RBAC avec kubectl get clusterrolebinding -o json | jq et supprimez les liaisons excessives. Si un PV a été supprimé, restaurez à partir d’un instantané ou d’une sauvegarde.

3. Ne pas chiffrer les volumes

Pourquoi cela arrive : les classes de stockage par défaut n’activent souvent pas le chiffrement. Les utilisateurs supposent que les fournisseurs de cloud chiffrent par défaut, ce qui n’est pas toujours vrai.

Comment l’éviter : créez des classes de stockage chiffrées et définissez-les comme valeur par défaut. Utilisez kubectl patch storageclass standard -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}' et marquez la classe chiffrée comme valeur par défaut.

Récupération : migrez les données vers des volumes chiffrés comme décrit précédemment. Assurez-vous que les futures PVC utilisent la classe chiffrée.

4. Absence de journalisation d’audit

Pourquoi cela arrive : la journalisation d’audit n’est pas activée par défaut dans de nombreuses configurations de cluster, ce qui crée des angles morts dans l’accès aux volumes.

Comment l’éviter : activez la journalisation d’audit avec une politique qui capture toutes les opérations sur les PV/PVC. Pour les clusters gérés, activez les journaux d’audit cloud pertinents (par exemple, AWS CloudTrail, journaux d’audit GCP).

Récupération : complétez les données d’audit à partir d’autres sources (par exemple, les métriques du serveur API) si possible. Ensuite, activez immédiatement la journalisation d’audit.

5. Ne pas tester les procédures de récupération

Pourquoi cela arrive : les équipes supposent que les sauvegardes fonctionnent mais ne testent jamais la restauration. Une défaillance lors d’un incident révèle des sauvegardes cassées.

Comment l’éviter : planifiez des exercices de restauration trimestriels. Automatisez avec un script qui crée une PVC de test à partir d’un instantané, vérifie l’intégrité des données et nettoie.

Récupération : si une restauration échoue, corrigez la configuration de sauvegarde et testez à nouveau. N’attendez pas un incident.

Conclusion

Le durcissement de la sécurité des volumes persistants Kubernetes n’est pas une commande unique, mais un ensemble de pratiques : inventorier votre environnement, appliquer un RBAC à moindre privilège, imposer des contextes de sécurité aux pods, chiffrer les volumes et surveiller en continu. La liste de contrôle opérationnelle et les pièges vous donnent un point de départ pour améliorer systématiquement la sécurité du stockage de votre cluster.

Commencez par un changement à faible risque : auditez vos PV et classes de stockage actuels, puis ajoutez le chiffrement à un volume non critique. Vérifiez que vos pods fonctionnent toujours et que le RBAC est correctement défini. Étendez à partir de là. N’oubliez pas de documenter les décisions et d’attribuer des responsables clairs aux tâches de sécurité.

Une configuration de PV sécurisée protège vos données même lorsque d’autres couches sont compromises. Une révision régulière et un durcissement proactif sont les clés pour maintenir cette protection à mesure que votre cluster évolue.

Recherches connexes

Score de qualité de l’article

Utilité pour le lecteur 100%
  • check_circle Guide prêt à lire
  • check_circle Exemples pratiques inclus
  • check_circle URL d’article optimisée pour le SEO