Kubernetes StorageClass en dynamische volume-provisioning op AWS, GCP en Azure

Dynamische volume-provisioning laat Kubernetes automatisch cloudopslag aanmaken als een pod dat nodig heeft. In plaats van handmatig disks voorbereiden, definieer je een StorageClass die het cluster vertelt welke CSI-driver moet worden aangeroepen en welke parameters meegegeven worden. Deze gids behandelt de juiste CSI-driver, StorageClass-configuratie en WaitForFirstConsumer-binding voor EKS (AWS), GKE (GCP) en AKS (Azure).

Inhoudsopgave

Wat je aan het einde hebt

Een productieklare StorageClass voor jouw cloudprovider, met de juiste CSI-driver geinstalleerd, WaitForFirstConsumer-binding ingeschakeld, volume-uitbreiding toegestaan, en een PVC die automatisch een clouddisk aanmaakt zodra een pod erom vraagt.

Vereisten

  • Een draaiend Kubernetes-cluster op een van de drie grote clouds: Amazon EKS, Google GKE of Azure AKS
  • kubectl geconfigureerd en geauthenticeerd tegen het cluster
  • Voor EKS: aws CLI en eksctl geinstalleerd; IAM-rechten om rollen aan te maken en add-ons te installeren
  • Voor GKE: gcloud CLI geauthenticeerd
  • Voor AKS: az CLI geauthenticeerd
  • Bekendheid met hoe PVs, PVCs en StorageClasses op elkaar aansluiten. Een StorageClass is de provisioning-template; een PVC is het verzoek; een PV is het daadwerkelijke volume dat wordt aangemaakt. Dynamische provisioning verbindt ze automatisch.

Anatomie van een StorageClass

Een StorageClass heeft zes velden die er in de dagelijkse praktijk toe doen:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: example
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"   # markeer als cluster-standaard
provisioner: <csi-driver-naam>              # welke driver het volume aanmaakt
reclaimPolicy: Delete                       # Delete of Retain
allowVolumeExpansion: true                  # PVCs vergroten na aanmaak (verkleinen kan nooit)
volumeBindingMode: WaitForFirstConsumer     # stel provisioning uit tot een pod is gescheduled
parameters:                                 # driver-specifiek: disktype, IOPS, encryptie
  type: gp3

Het provisioner-veld bepaalt alles. Elke cloud heeft zijn eigen CSI-driver met een specifieke drivernaam. Gebruik je de verkeerde naam, dan blijft de PVC voor altijd in Pending hangen.

Cloud CSI-drivernaam Wat het provisioneert
AWS EKS ebs.csi.aws.com EBS-volumes (gp2, gp3, io1, io2)
AWS EKS Auto Mode ebs.csi.eks.amazonaws.com EBS-volumes (beheerd door EKS Auto Mode)
GCP GKE pd.csi.storage.gke.io Persistent Disks (pd-balanced, pd-ssd, Hyperdisk)
Azure AKS disk.csi.azure.com Azure Managed Disks (Standard SSD, Premium SSD, Ultra)

De reclaimPolicy verdient een bewuste keuze. Delete (de standaard) vernietigt de onderliggende clouddisk als de PVC wordt verwijderd. Voor stateful productie-workloads zoals databases stel je het in op Retain. Je kunt de reclaim policy van een bestaande PV achteraf patchen, maar de StorageClass bepaalt de standaard voor nieuw aangemaakte volumes.

AWS EKS: de EBS CSI-driver installeren en een gp3 StorageClass aanmaken

EKS levert de EBS CSI-driver niet standaard mee. Zonder die driver falen PVCs die naar ebs.csi.aws.com verwijzen met fouten als failed to provision volume with StorageClass. Vanaf EKS 1.30 wordt ook geen standaard StorageClass meer geannoteerd, dus je moet zowel de driver als de StorageClass zelf configureren.

Stap 1: maak de IAM-rol aan

De EBS CSI-controller heeft AWS-rechten nodig om EBS-volumes aan te maken, te attachen en te verwijderen. Maak een serviceaccount-rol met de AmazonEBSCSIDriverPolicy managed policy:

eksctl create iamserviceaccount \
  --name ebs-csi-controller-sa \
  --namespace kube-system \
  --cluster production-cluster \
  --role-name AmazonEKS_EBS_CSI_DriverRole \
  --role-only \
  --attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \
  --approve

Zowel EKS Pod Identities als IRSA (IAM Roles for Service Accounts) werken. Pod Identities is de aanbevolen authenticatiemethode voor nieuwe clusters.

Stap 2: installeer de EBS CSI add-on

aws eks create-addon \
  --cluster-name production-cluster \
  --addon-name aws-ebs-csi-driver \
  --service-account-role-arn arn:aws:iam::111122223333:role/AmazonEKS_EBS_CSI_DriverRole

Wacht tot de add-on-status ACTIVE bereikt:

aws eks describe-addon --cluster-name production-cluster --addon-name aws-ebs-csi-driver \
  --query 'addon.status' --output text

Verwachte output: ACTIVE

EBS-volumes vereisen EC2-nodes. Fargate-pods kunnen geen EBS-volumes mounten.

Stap 3: maak de StorageClass aan

gp3 is de juiste keuze voor nieuwe deployments: 20% goedkoper per GB dan gp2, met een baseline van 3.000 IOPS en 125 MiB/s throughput op elke volumegrootte. gp2 koppelt IOPS aan volumegrootte (3 IOPS/GiB), dus kleine volumes presteren slecht.

# storageclass-ebs-gp3.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ebs-gp3
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete                       # gebruik Retain voor productiedatabases
allowVolumeExpansion: true
parameters:
  type: gp3                                 # gp3 baseline: 3.000 IOPS, 125 MiB/s
  iops: "3000"
  throughput: "125"                          # MiB/s; schaal op tot 1.000 voor gp3
  encrypted: "true"                          # EBS-encryptie at rest
  csi.storage.k8s.io/fstype: ext4

Pas hem toe:

kubectl apply -f storageclass-ebs-gp3.yaml

EKS Auto Mode-opmerking: Als je cluster op EKS Auto Mode draait, is de standaard EBS CSI add-on niet compatibel. EKS Auto Mode gebruikt een eigen provisioner: ebs.csi.eks.amazonaws.com. Vervang het provisioner-veld. Handmatige add-on-installatie is in Auto Mode niet nodig.

Stap 4: maak een PVC en een testpod aan

# test-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ebs-test
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: ebs-gp3
  resources:
    requests:
      storage: 5Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: ebs-test-pod
spec:
  containers:
    - name: app
      image: busybox:1.36
      command: ["sh", "-c", "echo 'volume works' > /data/test.txt && sleep 3600"]
      volumeMounts:
        - mountPath: /data
          name: storage
  volumes:
    - name: storage
      persistentVolumeClaim:
        claimName: ebs-test
kubectl apply -f test-pvc.yaml

De PVC blijft in Pending tot de pod gescheduled is (dat is normaal met WaitForFirstConsumer). Zodra de pod draait:

kubectl get pvc ebs-test

Verwachte output:

NAME       STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ebs-test   Bound    pvc-a1b2c3d4-5678-90ab-cdef-111122223333   5Gi        RWO            ebs-gp3        45s

GCP GKE: de Persistent Disk CSI-driver gebruiken

GKE Autopilot-clusters worden geleverd met de PD CSI-driver ingeschakeld en twee standaard StorageClasses: standard-rwo (pd-balanced) en premium-rwo (pd-ssd), beide met WaitForFirstConsumer. Op GKE Standard-clusters moet je controleren of de CSI-driver is ingeschakeld; oudere clusters gebruiken mogelijk nog de in-tree kubernetes.io/gce-pd provisioner.

De provisionernaam is pd.csi.storage.gke.io.

Een aangepaste StorageClass aanmaken

Als de ingebouwde classes niet voldoen (je wilt pd-ssd als standaard, Hyperdisk, of regionale PDs), maak dan een eigen StorageClass:

# storageclass-gke-ssd.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: gke-ssd
provisioner: pd.csi.storage.gke.io
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
reclaimPolicy: Delete
parameters:
  type: pd-ssd                              # opties: pd-balanced, pd-standard, pd-ssd, pd-extreme

Voor regionale persistent disks die data repliceren over twee zones:

parameters:
  type: pd-balanced
  replication-type: regional-pd
allowedTopologies:
  - matchLabelExpressions:
      - key: topology.kubernetes.io/zone
        values:
          - europe-west4-a
          - europe-west4-b

GKE ondersteunt ook Hyperdisk-types (hyperdisk-balanced, hyperdisk-throughput, hyperdisk-extreme, hyperdisk-ml) via dezelfde pd.csi.storage.gke.io provisioner. Beschikbaarheid verschilt per regio.

Azure AKS: de ingebouwde disk CSI-driver gebruiken

AKS installeert de Azure Disk CSI-driver (disk.csi.azure.com) en meerdere StorageClasses automatisch. De standaard StorageClass (managed-csi) gebruikt StandardSSD_LRS met WaitForFirstConsumer.

Voor multi-zone AKS-clusters op Kubernetes 1.29+ gebruiken de ingebouwde StorageClasses automatisch Zone-Redundant Storage (StandardSSD_ZRS, Premium_ZRS). ZRS biedt cross-zone replicatie, wat de veerkracht verbetert maar ook de kosten verhoogt.

Een aangepaste StorageClass aanmaken

Om de SKU, caching of LRS voor kostenoptimalisatie te controleren:

# storageclass-aks-premium.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: premium-lrs
provisioner: disk.csi.azure.com
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
reclaimPolicy: Delete
parameters:
  skuName: Premium_LRS                      # opties: Standard_LRS, Premium_LRS, StandardSSD_LRS,
                                            #          PremiumV2_LRS, UltraSSD_LRS, *_ZRS-varianten
  cachingMode: ReadOnly                      # None, ReadOnly, ReadWrite

Waarom WaitForFirstConsumer ook op single-zone clusters belangrijk is

Een veel voorkomend misverstand is dat WaitForFirstConsumer alleen voor multi-zone clusters uitmaakt. Dat klopt niet. Er zijn drie redenen om het overal te gebruiken.

Zoneveiligheid bij toekomstige uitbreiding. Een single-zone cluster dat groeit naar een tweede zone breekt elke Immediate-geprovisioned PVC. De volumes bestaan al in zone A; de scheduler kan pods op nodes in zone B plaatsen. Het resultaat: volume node affinity conflict-fouten en pods die in Pending blijven hangen. Met WaitForFirstConsumer worden volumes vanaf het begin in de zone van de pod aangemaakt.

Geen verweesde volumes. Immediate maakt een disk aan op het moment dat de PVC wordt gecreeerd, zelfs als er nooit een pod gebruik van maakt. Verweesde clouddisks kosten geld. WaitForFirstConsumer provisioneert alleen als een pod het volume daadwerkelijk nodig heeft.

Het is overal de standaard. Alle moderne managed-cloud StorageClasses gebruiken het: EKS 1.30+, AKS managed-csi, GKE standard-rwo. De officiele aws-ebs-csi-driver voorbeeld-StorageClass gebruikt WaitForFirstConsumer zonder voorbehoud.

Een operationeel bijeffect: een PVC met WaitForFirstConsumer blijft in Pending tot een pod ernaar verwijst. Dit is verwacht gedrag, geen provisioningfout. Stel spec.nodeName niet direct in op de pod bij gebruik van WaitForFirstConsumer; dit omzeilt de scheduler en laat de PVC permanent vastzitten. Gebruik nodeSelector of node affinity.

ReadWriteMany en NFS: niet automatisch

Block storage (EBS, Azure Disk, GCP PD) ondersteunt alleen ReadWriteOnce. Een node tegelijk. Als je meerdere pods op verschillende nodes naar hetzelfde volume wilt laten schrijven (ReadWriteMany), heb je een file-based storage-backend nodig.

Een NFS-server in je netwerk is niet genoeg. Kubernetes provisioneert geen NFS-volumes dynamisch zonder een expliciete CSI-driver. De NFS CSI-driver (nfs.csi.k8s.io) moet apart worden geinstalleerd, meestal via Helm.

Cloud-managed fileservices vereisen ook hun eigen drivers:

Service CSI-driver Standaard geinstalleerd?
AWS EFS efs.csi.aws.com Nee, vereist aws-efs-csi-driver add-on
Azure Files file.csi.azure.com Ja, standaard op AKS
GCP Filestore filestore.csi.storage.gke.io Nee, vereist expliciete activering

Azure Files is de enige cloud-fileservice met een standaard geinstalleerde CSI-driver. AKS levert azurefile-csi en azurefile-csi-premium StorageClasses direct mee.

Het resultaat verifieren

Bevestig na het toepassen van je StorageClass dat hij bestaat en de default-annotatie juist is:

kubectl get storageclass

Verwachte output (EKS-voorbeeld):

NAME              PROVISIONER       RECLAIMPOLICY   VOLUMEBINDINGMODE       ALLOWVOLUMEEXPANSION   AGE
ebs-gp3 (default) ebs.csi.aws.com   Delete          WaitForFirstConsumer    true                   2m

Maak een PVC en een pod aan (gebruik de testmanifesten uit het EKS-gedeelte hierboven, pas storageClassName aan). Controleer of de PVC Bound wordt en de pod start:

kubectl get pvc
kubectl get pod

Blijft de PVC in Pending nadat de pod gescheduled is, bekijk dan de events:

kubectl describe pvc <pvc-naam>

De events-sectie vertelt precies wat er misgaat: ontbrekende CSI-driver, IAM-permissiefout of zoneconflict.

Veelvoorkomende problemen

Symptoom Waarschijnlijke oorzaak Oplossing
PVC zit in Pending, geen pod aanwezig WaitForFirstConsumer werkt zoals ontworpen Maak een pod aan die de PVC gebruikt
PVC zit in Pending terwijl pod draait spec.nodeName direct op de pod gezet Gebruik nodeSelector of node affinity
UnauthorizedOperation bij volume-aanmaak CSI-driver mist IAM/RBAC-rechten Koppel AmazonEBSCSIDriverPolicy (EKS) of verifieer workload identity (GKE/AKS)
volume node affinity conflict Volume aangemaakt in verkeerde zone Schakel over naar WaitForFirstConsumer in de StorageClass
Multi-Attach error Block storage gebruikt met ReadWriteMany Block storage is alleen RWO; gebruik EFS, Azure Files of NFS voor RWX
EBS CSI-fout op EKS Auto Mode Provisioner ebs.csi.aws.com gebruikt Schakel over naar ebs.csi.eks.amazonaws.com
PVC aangemaakt, volume niet opgeruimd bij delete reclaimPolicy: Retain actief Handmatig PV en clouddisk opruimen

Terugkerende server- of deploymentproblemen?

Ik help teams productie betrouwbaar maken met CI/CD, Kubernetes en cloud—zodat fixes blijven en deploys geen stress meer zijn.

Bekijk DevOps consultancy

Doorzoek deze site

Begin met typen om te zoeken, of blader door de kennisbank en blog.