Veröffentlicht am

Kubernetes PVC Pending lösen: Storage-Troubleshooting

Teilen:
Authors

Kubernetes PVC Pending: Storage-Probleme systematisch loesen

TL;DR

  • PVC Pending bedeutet: Kubernetes findet kein passendes PersistentVolume -- alle Pods, die das Volume nutzen, bleiben ebenfalls Pending.
  • Erster Befehl: kubectl describe pvc <name> -- die Events zeigen die genaue Ursache.
  • Haeufigste Ursachen: keine Default StorageClass, Zone/Topology Mismatch, Kapazitaet erschoepft, CSI Driver fehlt.
  • WaitForFirstConsumer ist kein Fehler -- die PVC bleibt absichtlich Pending, bis ein Pod sie referenziert.
  • Dynamische Provisionierung loest die meisten Probleme. Statische PVs brauchen exakte Uebereinstimmung bei Capacity, Access Mode und StorageClass.

Was PVC Pending bedeutet

Wenn kubectl get pvc diesen Status zeigt, wartet Kubernetes auf ein Volume:

NAME        STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
app-data    Pending                                       standard       5m

Kubernetes sucht entweder ein vorhandenes PersistentVolume (statisch) oder erstellt eins ueber den CSI Driver (dynamisch). Wenn beides fehlschlaegt, bleibt die PVC auf Pending.

Der Diagnose-Workflow

Schritt 1: PVC Events pruefen

# PVC-Details mit Events
kubectl describe pvc app-data -n production

# Nur PVC-Events
kubectl get events --field-selector involvedObject.kind=PersistentVolumeClaim -n production

Schritt 2: StorageClass und PVs pruefen

# Verfuegbare StorageClasses
kubectl get storageclass

# Default StorageClass identifizieren
kubectl get storageclass -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.annotations.storageclass\.kubernetes\.io/is-default-class}{"\n"}{end}'

# Vorhandene PVs
kubectl get pv -o wide

Die 7 haeufigsten Ursachen

1. Keine Default StorageClass

Wenn eine PVC keine storageClassName angibt und keine Default StorageClass existiert, bleibt sie auf Pending.

# Event: "no persistent volumes available for this claim and no storage class is set"
kubectl get storageclass

Loesung:

kubectl patch storageclass standard \
  -p '{"metadata": {"annotations": {"storageclass.kubernetes.io/is-default-class": "true"}}}'

Oder eine neue StorageClass erstellen:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: ebs.csi.aws.com
parameters:
  type: gp3
  encrypted: "true"
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true

2. StorageClass existiert nicht

Die PVC referenziert eine StorageClass, die nicht im Cluster vorhanden ist.

# StorageClass aus PVC auslesen
kubectl get pvc app-data -n production -o jsonpath='{.spec.storageClassName}'

Loesung -- StorageClass fuer gaengige Cloud-Provider:

# AWS EBS (gp3)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-ssd
provisioner: ebs.csi.aws.com
parameters:
  type: gp3
  iops: "3000"
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
---
# Azure Managed Disk
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: azure-premium
provisioner: disk.csi.azure.com
parameters:
  skuName: Premium_LRS
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true

3. Zone / Topology Mismatch

Cloud-Volumes koennen nur in der Zone gemounted werden, in der sie erstellt wurden. Wenn das Volume in einer anderen Zone liegt als der Node, schlaegt das Mounting fehl.

# Zone des PVs
kubectl get pv <pv-name> -o jsonpath='{.spec.nodeAffinity}'

# Zonen der Nodes
kubectl get nodes --label-columns topology.kubernetes.io/zone

Loesung: WaitForFirstConsumer verwenden -- das Volume wird erst in der Zone des zugewiesenen Nodes erstellt:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: zone-aware
provisioner: ebs.csi.aws.com
parameters:
  type: gp3
volumeBindingMode: WaitForFirstConsumer   # Entscheidend fuer Multi-Zone

4. Kapazitaet erschoepft

Der Cloud-Provider hat keine Kapazitaet mehr fuer neue Volumes.

# Event: "ProvisioningFailed: rpc error: code = ResourceExhausted"
kubectl describe pvc app-data -n production | grep -A5 "Events"

Loesung:

# Nicht genutzte PVs finden
kubectl get pv --no-headers | awk '$5 == "Released" || $5 == "Available"'

# Released PV freigeben (Achtung: Datenverlust!)
kubectl patch pv <pv-name> -p '{"spec":{"claimRef": null}}'

5. WaitForFirstConsumer (kein Fehler)

Mit WaitForFirstConsumer bleibt die PVC absichtlich Pending, bis ein Pod sie referenziert.

# Event: "waiting for first consumer to be created before binding"
kubectl get storageclass <name> -o jsonpath='{.volumeBindingMode}'

Das ist erwartetes Verhalten. Die PVC wird automatisch gebunden, sobald ein Pod erstellt wird. Falls sofortige Bindung noetig ist:

volumeBindingMode: Immediate   # Achtung: kann Zone-Mismatches verursachen

6. CSI Driver nicht installiert

Der Provisioner aus der StorageClass ist nicht im Cluster vorhanden.

# Event: "no volume plugin matched name: ebs.csi.aws.com"
kubectl get csidrivers
kubectl get pods -n kube-system -l app=ebs-csi-controller

Loesung (Beispiel AWS EBS):

helm repo add aws-ebs-csi-driver https://kubernetes-sigs.github.io/aws-ebs-csi-driver
helm repo update

helm install aws-ebs-csi-driver aws-ebs-csi-driver/aws-ebs-csi-driver \
  --namespace kube-system \
  --set controller.replicaCount=2

# Pruefen
kubectl get csidrivers

7. Access Mode passt nicht

Bei statischer Provisionierung muessen PVC und PV denselben Access Mode haben.

kubectl get pvc app-data -n production -o jsonpath='{.spec.accessModes}'
kubectl get pv -o custom-columns=NAME:.metadata.name,ACCESS:.spec.accessModes,STATUS:.status.phase

Access Modes im Ueberblick:

Access ModeKurzformBedeutung
ReadWriteOnceRWOEin Node kann lesen/schreiben
ReadOnlyManyROXViele Nodes koennen lesen
ReadWriteManyRWXViele Nodes koennen lesen/schreiben
ReadWriteOncePodRWOPGenau ein Pod (ab K8s 1.27)

Loesung -- PVC und PV muessen uebereinstimmen:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: app-data-pv
spec:
  capacity:
    storage: 50Gi
  accessModes:
    - ReadWriteOnce
  storageClassName: manual
  hostPath:
    path: /mnt/data
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-data
  namespace: production
spec:
  accessModes:
    - ReadWriteOnce          # Muss mit PV uebereinstimmen
  resources:
    requests:
      storage: 50Gi          # Darf nicht groesser als PV sein
  storageClassName: manual   # Muss mit PV uebereinstimmen

Dynamische vs. Statische Provisionierung

Dynamisch (empfohlen)

Kubernetes erstellt automatisch ein PV ueber die StorageClass:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-data
  namespace: production
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
  storageClassName: standard

Statisch (NFS, existierende Volumes)

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-share
spec:
  capacity:
    storage: 100Gi
  accessModes:
    - ReadWriteMany
  storageClassName: nfs
  nfs:
    server: 10.0.0.50
    path: /exports/data
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: shared-data
  namespace: production
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 100Gi
  storageClassName: nfs

Volume nachtraeglich vergroessern

# Expansion moeglich?
kubectl get storageclass standard -o jsonpath='{.allowVolumeExpansion}'

# PVC vergroessern
kubectl patch pvc app-data -n production \
  -p '{"spec": {"resources": {"requests": {"storage": "50Gi"}}}}'

# Status pruefen
kubectl describe pvc app-data -n production | grep -A5 "Conditions"

Zusammenfassung: Diagnose-Tabelle

UrsacheEvent-MeldungLoesung
Keine Default StorageClassno storage class is setDefault StorageClass erstellen
StorageClass fehltstorageclass not foundStorageClass erstellen
Zone Mismatchvolume node affinity conflictWaitForFirstConsumer verwenden
Kapazitaet erschoepftResourceExhaustedQuotas pruefen, alte PVs bereinigen
WaitForFirstConsumerwaiting for first consumerKein Fehler -- Pod erstellen
CSI Driver fehltno volume plugin matchedCSI Driver installieren
Access Mode Mismatch(kein PV matcht)Access Modes angleichen

Der wichtigste Tipp bei kubernetes pvc pending: Immer kubectl describe pvc ausfuehren. Die Events-Sektion verraet fast immer die Ursache.

Verwandte Artikel


Wenn Sie Hilfe bei der Konfiguration Ihrer Kubernetes-Storage-Infrastruktur brauchen oder wiederkehrende PVC-Probleme loesen moechten, helfen wir gerne -- Kontakt aufnehmen.

Kubernetes-Beratung gesucht?

Wir helfen deutschen Unternehmen bei der Kubernetes-Implementierung, Migration und Optimierung. DSGVO-konform und praxiserprobt.

📖 Verwandte Artikel

Weitere interessante Beiträge zu ähnlichen Themen