Configuration dynamique de volumes persistants Kubernetes avec NFS

Cet article détaille la mise en place d'un provisionnement dynamique de volumes persistants (PV) dans Kubernetes en utilisant un serveur NFS. L'objectif est de permettre aux pods de demander et d'obtenir automatiquement de l'espace de stockage via une classe de stockage (StorageClass).

I. Environnement de déploiement

Les composants et nœuds utilisés pour cette configuration sont les suivants :

  • Système d'exploitation : CentOS Linux release 7.9.2009 (Core)
  • Kubernetes : v1.30.1
  • NFS Server : v1.3.0

La topologie du cluster est composée des nœuds suivants :

  • Maître : master-01 (192.168.71.161)
  • Nœuds de travail : worker-01 (192.168.71.150), worker-02 (192.168.71.151)

II. Installation et configuration du serveur NFS

La première étape consiste à installer et configurer le serveur NFS sur le nœud maître.

Installation des paquets NFS


# Installer les utilitaires NFS et rpcbind
yum install -y nfs-utils rpcbind

# Activer et démarrer les services
systemctl enable nfs
systemctl start nfs

Configuration du partage NFS

Créez le répertoire qui sera partagé via NFS et configurez le fichier /etc/exports.


# Créer le répertoire de partage
mkdir -pv /srv/nfs/shared

# Exporter le répertoire avec les permissions appropriées
# Les options rw, sync, no_root_squash sont utilisées pour permettre les écritures, la synchronisation des données et conserver les privilèges root de l'utilisateur distant.
echo "/srv/nfs/shared 192.168.71.0/24(rw,sync,no_root_squash)" > /etc/exports

# Redémarrer le service NFS pour appliquer la configuration
systemctl restart nfs

# Vérifier l'exportation du partage
showmount -e 127.0.0.1

Configuration des nœuds clients NFS

Sur les nœuds de travail, installez les utilitaires NFS et montez le partage distant.


# Installer les utilitaires NFS
yum install -y nfs-utils

# Vérifier la disponibilité du partage depuis le serveur NFS
showmount -e 192.168.71.161

# Activer et démarrer le service NFS (nécessaire pour le montage)
systemctl enable nfs
systemctl start nfs

# Créer le répertoire local de montage
mkdir -pv /mnt/nfs/data

# Monter le partage NFS distant
mount -t nfs 192.168.71.161:/srv/nfs/shared /mnt/nfs/data

Après le montage, un test peut être effectué : créer un fichier sur le serveur NFS devrait le rendre visible sur les nœuds clients, et vice versa.

Pour démonter le partage :


umount /mnt/nfs/data

III. Configuration du stockage Kubernetes

Création d'un espace de noms

Il est recommandé de créer un espace de noms dédié pour les ressources liées au provisionnement NFS.


kubectl create namespace dynamic-storage

3.1. Définition de la classe de stockage (StorageClass)

La StorageClass définit le type de stockage qui sera provisionné. Ici, nous utilisons un provisionneur externe.


kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: nfs-dynamic-storage
  namespace: dynamic-storage
  # Définir comme classe par défaut si vous souhaitez qu'elle soit utilisée sans spécification explicite dans les PVCs
  annotations:
    storageclass.kubernetes.io/is-default-class: "true" 
provisioner: nfs.example.com/provisioner # Le nom du provisionneur externe
reclaimPolicy: Retain # Politique de récupération : Retain conserve le volume, Delete le supprime avec le PVC
volumeBindingMode: Immediate # Le volume est lié dès la création du PVC

Appliquez cette définition :


kubectl apply -f nfs-storageclass.yaml

3.2. Configuration des permissions RBAC

Le provisionneur externe nécessite des autorisations spécifiques pour interagir avec l'API Kubernetes (création/suppression de volumes, etc.).


apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner-sa
  namespace: dynamic-storage
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nfs-provisioner-role
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: nfs-provisioner-binding
subjects:
  - kind: ServiceAccount
    name: nfs-provisioner-sa
    namespace: dynamic-storage
roleRef:
  kind: ClusterRole
  name: nfs-provisioner-role
  apiGroup: rbac.authorization.k8s.io
---
# Rôles pour le leader election (si plusieurs instances du provisionneur)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: nfs-provisioner-leader-role
  namespace: dynamic-storage
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: nfs-provisioner-leader-binding
  namespace: dynamic-storage
subjects:
  - kind: ServiceAccount
    name: nfs-provisioner-sa
    namespace: dynamic-storage
roleRef:
  kind: Role
  name: nfs-provisioner-leader-role
  apiGroup: rbac.authorization.k8s.io

Appliquez ces définitions RBAC :


kubectl apply -f nfs-rbac.yaml

3.3. Déploiement du provisionneur externe NFS

Ce déploiement exécute un pod qui agit comme provisionneur NFS pour Kubernetes. Il écoute les demandes de création de PVC et crée dynamiquement les volumes NFS correspondants.


apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-external-provisioner
  namespace: dynamic-storage
  labels:
    app: nfs-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-provisioner
  template:
    metadata:
      labels:
        app: nfs-provisioner
    spec:
      serviceAccountName: nfs-provisioner-sa # Utilisation du ServiceAccount créé précédemment
      containers:
        - name: nfs-provisioner
          # Utilisation d'une image de provisionneur NFS populaire
          image: quay.io/external_storage/nfs-client-provisioner:latest 
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: nfs-provisioner-storage
              mountPath: /persistentvolumes # Chemin où les nouveaux volumes seront créés
          env:
            - name: PROVISIONER_NAME
              value: nfs.example.com/provisioner # Doit correspondre au champ 'provisioner' dans la StorageClass
            - name: NFS_SERVER
              value: "192.168.71.161" # IP du serveur NFS
            - name: NFS_PATH
              value: "/srv/nfs/shared" # Chemin du partage NFS sur le serveur
      volumes:
        - name: nfs-provisioner-storage # Ce volume permet au provisionneur d'écrire sur le partage NFS
          nfs:
            server: "192.168.71.161"
            path: "/srv/nfs/shared"

Appliquez la configuration du déploeiment :


kubectl apply -f nfs-provisioner-deployment.yaml

3.4. Création d'une demande de volume persistant (PVC)

Une fois la StorageClass et le provisionneur configurés, vous pouvez créer un PVC. Kubernetes utilisera la StorageClass par défaut (ou spécifiée) pour demander un volume au provisionneur.


apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-nfs-pvc
  namespace: dynamic-storage
spec:
  storageClassName: nfs-dynamic-storage # Spécifie la StorageClass à utiliser
  accessModes:
    - ReadWriteMany # Mode d'accès : plusieurs nœuds peuvent lire et écrire
  resources:
    requests:
      storage: 1Gi # Taille du volume demandé

Créez le PVC :


kubectl apply -f my-nfs-pvc.yaml

Vérifiez le statut du PVC et le PV qui a été créé dynamiquement :


kubectl get pvc -n dynamic-storage
kubectl get pv

Le PVC devrait passer à l'état Bound, et un nouveau PersistentVolume correspondant devrait apparaître.

Pour supprimer le PVC :


kubectl delete pvc my-nfs-pvc -n dynamic-storage

Si la reclaimPolicy est définie sur Retain, le PV restera après la suppression du PVC. S'il est défini sur Delete, le PV sera supprimé. Le répertoire correspondant sur le serveur NFS sera géré selon la politique configurée dans le provisionneur (souvent, la suppression du PV via le provisionneur entraînera la suppression du répertoire NFS s'il est vide).

Étiquettes: kubernetes nfs storageclass dynamic provisioning persistent volumes

Publié le 14 juillet à 00h14