34 Persistente Volumes (PV) und Volume Claims (PVC)

Persistente Volumes und Volume Claims implementieren Storage-Abstraktion in OpenShift durch Entkopplung von Storage-Bereitstellung und Storage-Nutzung über deklarative Ressourcenmanagement-Mechanismen. Diese Architektur ermöglicht flexible Storage-Integration mit verschiedenen Backend-Systemen bei gleichzeitiger Abstraktion der Infrastruktur-Komplexität für Anwendungsentwickler.

34.1 Grundkonzepte der Storage-Abstraktion

Persistente Volumes (PV) fungieren als Cluster-weite Storage-Ressourcen, die physische oder virtuelle Storage-Geräte abstrahieren und über standardisierte APIs zugänglich machen. Diese Infrastruktur-Abstraktion ermöglicht portable Anwendungsdefinitionen unabhängig von spezifischen Storage-Backend-Implementierungen.

Volume Claims (PVC) repräsentieren Storage-Anforderungen von Anwendungen und definieren gewünschte Storage-Charakteristika wie Kapazität, Zugriffsmodi und Performance-Klassen. Diese deklarativen Storage-Requests abstrahieren Anwendungs-Storage-Anforderungen von konkreten Storage-Implementierungsdetails.

34.1.1 Die PV/PVC-Beziehung

Das Binding-System zwischen PVs und PVCs implementiert automatische Storage-Zuordnung basierend auf Matching-Kriterien und Verfügbarkeit. Diese automatisierte Zuordnung reduziert den administrativen Aufwand und ermöglicht Self-Service Storage-Bereitstellung für Entwicklungsteams.

Grundprinzip: - Administratoren erstellen PVs (Angebot) - Entwickler erstellen PVCs (Nachfrage) - Kubernetes verbindet passende PV/PVC-Paare automatisch

[Diagramm: PV-PVC-Architektur mit Binding-Prozess]

34.1.2 Lifecycle-Management

Storage-Ressourcen durchlaufen definierte Lifecycle-Phasen mit strukturierten Zustandsübergängen:

Phase Beschreibung Nächster Schritt
Available PV ist erstellt und verfügbar Binding an PVC
Bound PV ist an PVC gebunden In Verwendung
Released PVC wurde gelöscht Reclamation
Failed Automatische Reclamation fehlgeschlagen Manuelle Intervention

34.2 Storage-Backend-Integration

Storage-Provider-Integration ermöglicht die Anbindung verschiedener Storage-Systeme wie NFS, iSCSI, Ceph, GlusterFS oder Cloud-Provider Storage-Services durch standardisierte Volume-Plugins. Diese Plugin-Architektur gewährleistet Vendor-Neutralität und Storage-Technologie-Flexibilität.

34.2.1 Container Storage Interface (CSI)

Das Container Storage Interface (CSI) standardisiert Storage-Plugin-Entwicklung und ermöglicht Out-of-Tree Storage-Driver-Implementierungen ohne Kubernetes-Core-Modifikationen:

apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:
  name: csi.example.com
spec:
  attachRequired: true
  podInfoOnMount: true
  volumeLifecycleModes:
  - Persistent
  - Ephemeral

Vorteile von CSI: - Unabhängige Entwicklung von Storage-Treibern - Standardisierte API zwischen Kubernetes und Storage-Anbietern - Vereinfachte Storage-Vendor-Integration - Schnellere Storage-Innovation

34.2.2 Volume-Plugin-Architektur

Volume-Plugins abstrahieren Storage-Backend-spezifische Operationen wie Mount/Unmount, Format und Resize-Operationen über einheitliche Interfaces. Diese Abstraktion ermöglicht konsistente Storage-Operationen unabhängig von der Backend-Technologie.

34.2.3 Storage-Topology-Awareness

Storage-Topology-Awareness berücksichtigt physische Storage-Standorte und Netzwerk-Proximität für optimale Pod-zu-Storage-Platzierung:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-with-topology
spec:
  capacity:
    storage: 10Gi
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: topology.kubernetes.io/zone
          operator: In
          values:
          - us-west-1a

34.3 Access-Modi und Volume-Charakteristika

OpenShift unterstützt verschiedene Volume-Zugriffsmodi, die bestimmen, wie und von wie vielen Pods gleichzeitig auf ein Volume zugegriffen werden kann.

34.3.1 Volume-Access-Modi

Access-Modus Abkürzung Beschreibung Anwendungsfall
ReadWriteOnce RWO Ein Pod kann lesen/schreiben Datenbanken, File-Storage
ReadOnlyMany ROX Mehrere Pods können lesen Statische Inhalte, Konfigurationen
ReadWriteMany RWX Mehrere Pods können lesen/schreiben Shared File Systems, Collaborative Apps
ReadWriteOncePod RWOP Nur ein Pod kann zugreifen Höchste Isolation für kritische Daten

34.3.2 Praktische Beispiele für Access-Modi

ReadWriteOnce (RWO) - Database Storage:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: database-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
  storageClassName: fast-ssd

ReadWriteMany (RWX) - Shared Content:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: shared-content-pvc
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 100Gi
  storageClassName: shared-storage

34.4 Volume-Lifecycle und Zustandsverwaltung

34.4.1 Provisioning-Strategien

Static Provisioning: Administratoren erstellen PVs manuell im Voraus:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: static-pv-001
spec:
  capacity:
    storage: 50Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  nfs:
    server: nfs-server.example.com
    path: /exports/data/pv001

Dynamic Provisioning: Storage wird automatisch bei PVC-Erstellung bereitgestellt:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: dynamic-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: aws-ebs-gp2

34.4.2 Binding-Prozess

Der Binding-Prozess implementiert automatische PV-zu-PVC-Zuordnung basierend auf Größe, Access-Mode und Storage-Class-Matching-Kriterien:

Matching-Kriterien: 1. Kapazität: PV muss mindestens die angeforderte PVC-Kapazität haben 2. Access-Modi: PV muss den angeforderten Access-Modus unterstützen 3. Storage Class: PV und PVC müssen die gleiche Storage Class haben 4. Selektoren: Optionale Label-Selektoren für spezifische PV-Auswahl

Binding-Beispiel:

# PVC mit spezifischem Selector
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  selector:
    matchLabels:
      environment: production
      tier: database

34.5 Reclaim-Policies und Datenmanagement

Reclaim-Policies bestimmen, was mit einem PV passiert, nachdem die zugehörige PVC gelöscht wurde.

34.5.1 Policy-Typen

Retain Policy: Preserviert Storage-Inhalte nach PVC-Löschung und erfordert manuelle Datenwiederherstellung oder Storage-Cleanup:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: important-data-pv
spec:
  capacity:
    storage: 100Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain  # Daten bleiben erhalten
  nfs:
    server: backup-nfs.example.com
    path: /critical-data

Delete Policy: Implementiert automatische Storage-Ressourcen-Cleanup nach PVC-Löschung mit kompletter Datenentfernung:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: delete-after-use
provisioner: kubernetes.io/aws-ebs
reclaimPolicy: Delete  # Automatische Löschung
parameters:
  type: gp2

Recycle Policy (veraltet): Diese Legacy-Reclamation-Methode wurde durch Dynamic-Provisioning-Mechanismen ersetzt.

34.5.2 Data-Protection-Überlegungen

Data-Protection-Überlegungen erfordern Backup-Strategie-Integration vor Reclaim-Policy-Ausführung für kritischen Datenschutz:

Backup vor Reclamation:

# Backup erstellen vor PVC-Löschung
oc exec backup-pod -- tar czf /backup/app-data-$(date +%Y%m%d).tar.gz /var/lib/app/data

# PVC sicher löschen
oc delete pvc app-data-pvc

34.6 Volume-Mounting und Container-Integration

34.6.1 Mount-Spezifikationen

Volume-Mount-Spezifikationen definieren Container-Dateisystem-Integrationspunkte für persistenten Storage-Zugriff:

apiVersion: v1
kind: Pod
metadata:
  name: app-with-storage
spec:
  containers:
  - name: app-container
    image: myapp:latest
    volumeMounts:
    - name: app-data
      mountPath: /var/lib/app/data
      readOnly: false
    - name: config-data
      mountPath: /etc/app/config
      readOnly: true
  volumes:
  - name: app-data
    persistentVolumeClaim:
      claimName: app-data-pvc
  - name: config-data
    configMap:
      name: app-config

34.6.2 SubPath-Mounting

SubPath-Mounting ermöglicht Directory-Level-Storage-Sharing zwischen mehreren Containern oder Anwendungen ohne vollständigen Volume-Zugriff:

apiVersion: v1
kind: Pod
metadata:
  name: multi-app-pod
spec:
  containers:
  - name: app1
    image: app1:latest
    volumeMounts:
    - name: shared-storage
      mountPath: /app1/data
      subPath: app1-data
  - name: app2
    image: app2:latest
    volumeMounts:
    - name: shared-storage
      mountPath: /app2/data  
      subPath: app2-data
  volumes:
  - name: shared-storage
    persistentVolumeClaim:
      claimName: shared-pvc

34.6.3 Security Context und Berechtigungen

Dateisystem-Berechtigungen und Security Context-Integration gewährleisten angemessene Zugriffskontrollen:

apiVersion: v1
kind: Pod
metadata:
  name: secure-app
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 1000
    fsGroup: 2000  # Gruppe für Volume-Zugriff
  containers:
  - name: app
    image: secure-app:latest
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
    volumeMounts:
    - name: data-volume
      mountPath: /var/lib/app
  volumes:
  - name: data-volume
    persistentVolumeClaim:
      claimName: app-pvc

34.7 Performance-Überlegungen

34.7.1 IOPS und Durchsatz-Anforderungen

IOPS-Anforderungen und Durchsatz-Spezifikationen beeinflussen Storage-Backend-Auswahl und Performance-Tuning-Strategien:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: high-performance-ssd
provisioner: kubernetes.io/aws-ebs
parameters:
  type: io2
  iopsPerGB: "50"      # 50 IOPS pro GB
  throughput: "1000"   # 1000 MB/s Durchsatz
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer

34.7.2 Storage-Latenz-Optimierung

Storage-Latenz-Optimierung durch lokale Storage-Integration oder High-Performance-Storage-Backend-Auswahl:

Local Storage für niedrige Latenz:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-ssd-pv
spec:
  capacity:
    storage: 100Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-ssd
  local:
    path: /mnt/local-ssd
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - node-with-ssd

34.7.3 Caching-Strategien

Caching-Strategien auf Storage-Layer können Read-Performance durch In-Memory oder SSD-basierte Caching-Layer verbessern:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: cached-storage
provisioner: csi.ceph.com
parameters:
  pool: cached-pool
  caching: "writeback"    # Write-Back-Caching aktivieren
  cache-tier: ssd-cache   # SSD-basierte Cache-Tier

34.8 Sicherheit und Verschlüsselung

34.8.1 Encryption-at-Rest

Encryption-at-Rest für persistente Volumes implementiert Datenschutz durch Storage-Layer oder OS-Level-Verschlüsselungsmechanismen:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: encrypted-storage
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp3
  encrypted: "true"
  kmsKeyId: "arn:aws:kms:us-west-2:123456789012:key/12345678-1234-1234-1234-123456789012"

34.8.2 Encryption-in-Transit

Encryption-in-Transit für netzwerkgebundene Storage-Systeme schützt Datenübertragung zwischen Storage-Clients und Storage-Backends:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: encrypted-nfs-pv
spec:
  capacity:
    storage: 50Gi
  accessModes:
  - ReadWriteMany
  mountOptions:
  - sec=krb5p      # Kerberos mit Verschlüsselung
  - proto=tcp      # TCP für bessere Sicherheit
  nfs:
    server: secure-nfs.example.com
    path: /encrypted/exports

34.8.3 Access Control Integration

Access-Control-Integration mit Kubernetes RBAC-Systemen implementiert feinabgestufte Storage-Zugriffsberechtigungen:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: production
  name: storage-user
rules:
- apiGroups: [""]
  resources: ["persistentvolumeclaims"]
  verbs: ["get", "list", "create", "delete"]
- apiGroups: [""]
  resources: ["persistentvolumes"]
  verbs: ["get", "list"]  # Nur Lese-Zugriff auf PVs

34.9 Storage Classes und Dynamic Provisioning

Storage Classes definieren “Klassen” von Storage mit unterschiedlichen Performance-, Verfügbarkeits- und Kostencharakteristika:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: database-storage
  annotations:
    storageclass.kubernetes.io/is-default-class: "false"
provisioner: kubernetes.io/aws-ebs
parameters:
  type: io2
  iopsPerGB: "10"
  fsType: ext4
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true

34.9.1 Volume-Expansion

Volume-Expansion ermöglicht das Vergrößern von PVCs ohne Datenverlust:

# PVC vergrößern
oc patch pvc database-pvc -p '{"spec":{"resources":{"requests":{"storage":"50Gi"}}}}'

# Status überprüfen
oc get pvc database-pvc -o jsonpath='{.status.conditions[?(@.type=="Resizing")].status}'

34.10 Single-Node-Storage-Überlegungen

34.10.1 Local Storage Integration

Local Storage-Integration in Single-Node-Umgebungen nutzt Host-Dateisysteme oder Block-Geräte für hohe Performance ohne Netzwerk-Overhead:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-dev-storage
spec:
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:
    path: /opt/local-storage
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - localhost

34.10.2 EmptyDir Volumes

EmptyDir-Volume-Nutzung für temporäre Storage-Anforderungen bietet geteiltes Storage zwischen Containern in derselben Pod:

apiVersion: v1
kind: Pod
metadata:
  name: temp-storage-pod
spec:
  containers:
  - name: app
    image: myapp:latest
    volumeMounts:
    - name: tmp-storage
      mountPath: /tmp/shared
  - name: sidecar
    image: sidecar:latest
    volumeMounts:
    - name: tmp-storage
      mountPath: /shared
  volumes:
  - name: tmp-storage
    emptyDir:
      sizeLimit: 1Gi
      medium: Memory  # RAM-basiertes tmpfs

34.10.3 HostPath Volumes (Vorsicht geboten)

HostPath-Volume-Integration ermöglicht direkten Host-Dateisystem-Zugriff für Test- oder Entwicklungszwecke:

apiVersion: v1
kind: Pod
metadata:
  name: host-access-pod
spec:
  containers:
  - name: app
    image: debug-app:latest
    volumeMounts:
    - name: host-data
      mountPath: /host-data
      readOnly: true
  volumes:
  - name: host-data
    hostPath:
      path: /var/log
      type: Directory

Sicherheitshinweis: HostPath-Volumes sollten nur in Entwicklungsumgebungen verwendet werden, da sie Sicherheitsrisiken darstellen können.

34.11 Troubleshooting und Monitoring

34.11.1 Häufige PV/PVC-Probleme

PVC bleibt im Pending-Status:

# PVC-Status prüfen
oc describe pvc stuck-pvc

# Verfügbare PVs prüfen
oc get pv --show-labels

# Events prüfen
oc get events --field-selector reason=FailedBinding

Volume-Mount-Probleme:

# Pod-Events prüfen
oc describe pod problematic-pod

# Volume-Mount-Status prüfen
oc get pod problematic-pod -o yaml | grep -A 10 volumeMounts

34.11.2 Storage-Metriken

Wichtige Storage-Metriken für Monitoring und Kapazitätsplanung:

# ServiceMonitor für Storage-Metriken
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: storage-metrics
spec:
  selector:
    matchLabels:
      app: csi-driver
  endpoints:
  - port: metrics
    interval: 30s
    path: /metrics

Wichtige Storage-Metriken: - Volume-Auslastung (Used/Available) - IOPS und Durchsatz pro Volume - Latenz-Metriken für Storage-Operationen - PV/PVC-Binding-Erfolgsrate