Veröffentlicht am

PVC Pending: StorageClass und Provisioner

Teilen:
Authors

PVC Pending: StorageClass, Provisioner, Zone

TL;DR

Ein PVC auf Pending hat noch kein Volume. Der Pod, der es mountet, bleibt oft ebenfalls Pending, mit dem Event unbound PersistentVolumeClaims. Zuerst die Klasse und der Modus:

kubectl get pvc PVC -o wide
kubectl describe pvc PVC
kubectl get storageclass

Keine StorageClass und kein Default: der Claim weiß nicht, wer das Volume anlegen soll. WaitForFirstConsumer: Pending ohne Pod ist normal. Provisioner-Pod fehlt oder eine Zone passt nicht: der Claim bleibt Pending, auch mit Pod.

Pending, das kein Fehler ist

volumeBindingMode: WaitForFirstConsumer bindet erst, wenn ein Pod den Claim benutzt und der Scheduler den Node kennt. Vorher bleibt der PVC auf Pending, Events melden sinngemäß, dass auf den ersten Consumer gewartet wird. Wer den PVC allein anlegt und sofort Bound erwartet, debuggt einen korrekten Zustand.

Erst wenn ein Pod den Claim referenziert und trotzdem nichts bindet, lohnt die weitere Suche. Der Pod zeigt dann Pod Pending mit einem Volume-Grund, oder er ist geschedult und hängt in ContainerCreating an FailedMount.

Keine Klasse, kein Default

kubectl get storageclass
kubectl get pvc PVC -o jsonpath='{.spec.storageClassName}{"\n"}'

(default) steht an genau einer Klasse. Fehlt sie, und der PVC nennt keine storageClassName, bleibt er Pending. Auf einem frischen Cluster oder nach dem Löschen des Default-Add-ons ist das der häufigste Fall.

Fix: im PVC die Klasse setzen, die es wirklich gibt, oder eine Klasse als Default markieren.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: daten
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: managed-premium
  resources:
    requests:
      storage: 20Gi

Ein leerer String storageClassName: "" schaltet dynamische Provisionierung aus. Der Claim wartet dann auf ein passendes, von Hand angelegtes PV. Gibt es keines, bleibt er Pending. Das ist Absicht, kein Bug der Klasse.

Provisioner läuft nicht

Die Klasse nennt einen provisioner, zum Beispiel disk.csi.azure.com, ebs.csi.aws.com oder pd.csi.storage.gke.io. Das dazugehörige Controller-Deployment muss laufen.

kubectl get pods -A | grep -i csi
kubectl describe pvc PVC

describe sagt waiting for a volume to be created und danach einen Provisioner-Fehler: Quota in der Cloud, unbekannte SKU, keine Berechtigung der Node- oder Controller-Identität. Das ist kein Kubernetes-Quota aus dem Namespace, sondern das Kontingent beim Cloud-Anbieter. kubectl describe quota bleibt dann grün.

failed to provision volume mit zone oder topology heißt: der Pod sitzt in einer Zone, in der die Klasse kein Volume anlegen darf, oder das bestehende Volume liegt in einer anderen Zone als der Node. ReadWriteOnce bindet an eine Zone. Ein Pod mit festem nodeSelector auf Zone A und ein Volume in Zone B mountet nie. Entweder die Affinity an die Volume-Zone anpassen oder die Klasse neu provisionieren lassen, nachdem der Pod in der richtigen Zone geplant wird. Dafür ist WaitForFirstConsumer da.

Access Mode und Größe

ReadWriteMany auf einer Klasse, die nur ReadWriteOnce kann, wird nicht gebunden. Die Klasse sagt nicht immer laut nein. Im describe des PVC steht, dass kein PV die Modes erfüllt. Dieselbe Falle bei einer Größe, die über dem erlaubten Maximum der Klasse liegt.

Ein Resize auf einem bestehenden Claim ist ein anderes Thema: die Klasse braucht allowVolumeExpansion: true, und der Pod muss das Dateisystem oft neu einhängen. Ein Pending beim ersten Anlegen hat mit Expansion nichts zu tun.

Backup hängt am selben Claim

Wer den Cluster sichert, sichert das Volume, nicht den Pending-Claim. Ein Claim, der nie Bound war, hat keine Daten. Ein Claim, der Bound ist und dessen Pod in Terminating festhängt, blockiert oft den nächsten Mount desselben Volumes. Erst den Pod lösen, dann den Restore prüfen. Der Ablauf für Datenbanken im Cluster steht im Backup-Artikel.

Quellen

📖 Verwandte Artikel

Weitere interessante Beiträge zu ähnlichen Themen