Begriff
PersistentVolumeClaim (PVC)
Warum wichtig?
Dieser Begriff ist ein Knoten im SengakujiWorks-Wissensnetz. Nutze Level 0 für die erste Einordnung, Level 1 für Praxis, Level 2 für technische Struktur und Level 3 für Grenzen, Fallstricke und Expertenkontext.
Wenn du in ein Restaurant gehst, reservierst du einen "Tisch für 2 Personen". Das ist dein Claim (Anspruch). Der Kellner (Kubernetes) sucht dann einen echten Tisch (PersistentVolume), der passt. Vielleicht einen Ecktisch (SSD) oder einen am Fenster (NFS). Du als Gast (Pod) weißt nicht, welcher Tisch es wird, bis du sitzt. Der PersistentVolumeClaim (PVC) ist genau diese Reservierung. Er sagt: "Ich brauche 10GB ReadWriteOnce". Ohne PVC kriegt dein Pod keinen Speicher.
Merksatz: Eine Anforderung eines Benutzers (oder Pods) nach Speicherressourcen, die vom Cluster durch das Binden an ein passendes PersistentVolume (PV) erfüllt wird.
Standard-YAML:
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mysql-pv-claim
spec:
storageClassName: standard # "Ich will den normalen Speicher"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
Der Status wechselt von Pending -> Bound (sobald K8s eine Disk gefunden oder erstellt hat).
Wenn es auf Pending bleibt: Wahrscheinlich hast du keine StorageClass oder die Cloud hat kein Quota mehr.
Praxisroutine
In der Praxis lernst du PersistentVolumeClaim (PVC), indem du mit einem kleinen, kontrollierten Beispiel beginnst. Baue zuerst einen Minimalfall, prüfe das Ergebnis, veraendere genau eine Sache und beobachte, was sich ändert. Notiere dir Eingabe, Aktion, Ausgabe und typischen Fehler.
Übung: Erstelle ein Beispiel aus deinem Alltag, fuehre den Ablauf gedanklich Schritt für Schritt durch und markiere die Stelle, an der du Feedback oder ein Log brauchst. Wenn du diese Stelle benennen kannst, verstehst du den Begriff praktisch.
1. Binding Lifecycle
Ein PVC sucht ein PV.
Wenn storageClassName: "" (leer) ist, sucht er ein vorhandenes PV, das manuell angelegt wurde.
Wenn storageClassName: standard ist, ruft er den Provisioner (z. B. ebs.csi.aws.com), um ein neues PV zu erstellen.
Das Binding ist exklusiv (1:1). Ein 100GB PV bindet an einen 10GB PVC -> 90GB Verschwendung! (K8s kann PVs nicht splitten).
Deshalb immer Dynamic Provisioning nutzen (genau passend).
2. Volume Mode (Filesystem vs Block)
Normalerweise mountet K8s ein Dateisystem (ext4).
Aber Datenbanken (Postgres, Cassandra) wollen oft direkten Zugriff auf die Rohdaten (Raw Block Device) für Performance (kein Filesystem-Overhead).
spec:
volumeMode: Block
Der Pod sieht dann /dev/xvda statt /data. Er muss selbst formatieren oder direkt drauf schreiben.
3. PVC Expansion
Deine DB ist voll.
Du editierst den PVC: storage: 50Gi.
Der CSI-Treiber vergrößert das Volume in der Cloud.
Dann triggert Kubelet den resize2fs Befehl im laufenden Betrieb.
Der Pod merkt kurz "Disk friert ein", dann "Disk ist größer".
Achtung: Geht nur, wenn allowVolumeExpansion: true in der StorageClass gesetzt ist. Und verkleinern geht nie! D.h. 50Gi -> 20Gi ist unmöglich.
Reclaim Policy & PVC Lifecycle (Retain vs Delete)
Was passiert mit dem echten Speicher (dem PV), wenn ich den "Gutschein" (den PVC) per kubectl delete pvc vernichte?
Das regelt die ReclaimPolicy im PV (geerbt von der StorageClass).
- Delete (Klassiker Clouds): Das CSI-Plugin ruft die EBS/GCE API an und löscht die Disk physikalisch mit sofortiger Wirkung. Deine DB-Daten sind für immer desintegriert.
- Retain (Production Standard für DBs): K8s belässt die Cloud-Disk am Leben ("Orphaned"). Das PV-Objekt geht in den State
Released. Du kannst nun keinen neuen PVC mehr darauf binden (!), da K8s davon ausgeht, dass die Daten sensibel sind. Ein Admin muss manuell alte PVC-Claims im YAML (claimRef) des PVs wipen, um das Bind-Lock freizugeben. Erst dann kann ein Recovery-Pod diesen Disk-Schatz wieder abgreifen.
Binding-Verhalten (Die Größen-Wüste)
Das Claim-Binding-Prinzip funktioniert wie eine knallharte Auktion.
Du forderst 15 Gi im PVC (requests.storage: 15Gi). K8s sucht in seinem Pool an ungebundenen PVs nach dem Kriterium Capacity >= 15Gi und passenden "AccessModes" (zb. ReadWriteOnce).
Gibt es kein exaktes 15 Gi PV, sondern nur eines mit 100 Gi freiem Platz, bindet K8s dein PVC mitleidlos an das 100 Gi PV. K8s unterstützt von sich aus keine "Partitions-Slices". Das Resultat: 85 Gi verschwendeter, nicht nutzbarer Speicher. Dynamic Provisioning via StorageClass verhindert dies, indem es die Disk in Echtzeit passgenau gießt.
StatefulSet VolumeClaimTemplates (Die Pod-Symbiose)
Ein PVC in einem standard Deployment ist suizidal, wenn du 3 Replicas (Pods) hast. Alle 3 Pods greifen den selben PVC und versuchen zeitgleich dasselbe Dateisystem zu crashen (was bei ReadWriteOnce meist schon am Node-Scheduler scheitert).
Verwendet man StatefulSets, gibt es keinen isolierten PVC mehr im manifest. Stattdessen schreibst du volumeClaimTemplates in die StatefulSet-Spec. K8s nutzt dieses Cookie-Cutter-Template und stanzt für jeden hochgefahrenen Pod (wie mysql-0, mysql-1) dynamisch einen brandneuen, komplett isolierten PVC aus (data-mysql-0, etc.). Stirbt Pod 0, heftet K8s genau diese ID und den dazugehörigen nummerierten PVC wieder an den neu bootenden Pod 0. Konsistenz ist garantiert.
Quick-Check
Was ist "Lost"?
Ein PVC Status, wenn das darunterliegende PV gelöscht wurde (Unfall), aber der Claim noch da ist. Datenverlust ist wahrscheinlich passiert. Backups prüfen!StatefulSet & PVC?
Ein Deployment teilt sich einen PVC (alle Replicas schreiben auf dieselbe Disk -> Chaos bei RWO!). Ein StatefulSet nutztvolumeClaimTemplates. Es erstellt für jeden Pod einen eigenen PVC (data-db-0,data-db-1).Ephemere Volumes?
Manchmal brauche ich Scratch-Space nur für den Pod (schnell, lokal), aber größer als RAM (emptyDir). "Generic Ephemeral Volumes" erlauben PVC-Syntax direkt im Pod-Spec, die beim Pod-Ende gelöscht werden.