Kubernetes PersistentVolume — zarządzanie storage w klastrze
Opublikowano: 10 kwietnia 2026 · Kategoria: VPS / Kubernetes
Pody Kubernetes są efemeryczne — giną i odradzają się, tracąc dane zapisane wewnątrz kontenera. PersistentVolume to mechanizm K8s, który oddziela cykl życia danych od cyklu życia poda. Ten artykuł wyjaśnia cały model storage w K8s: PV jako zasób, PVC jako żądanie, StorageClass jako fabrykę PV, różne access modes, jak prawidłowo skonfigurować NFS jako backend oraz jak robić backupy z Velero.
Lifecycle PV i PVC — jak działa binding
Przepływ statycznego provisioningu (admin tworzy PV ręcznie):
# 1. Admin tworzy PV (statyczny)
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv-prod
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteMany # NFS obsługuje RWX
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs-slow # matchuje z PVC storageClassName
nfs:
server: 192.168.1.100
path: /exports/k8s-data
---
# 2. Uzytkownik tworzy PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-storage
namespace: production
spec:
accessModes:
- ReadWriteMany
storageClassName: nfs-slow
resources:
requests:
storage: 10Gi # K8s znajdzie PV z min 10Gi w tej StorageClass
---
# 3. Pod montuje PVC
apiVersion: v1
kind: Pod
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: data
mountPath: /var/data
volumes:
- name: data
persistentVolumeClaim:
claimName: app-storage # Sprawdzenie statusu kubectl get pv # NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM # nfs-pv-prod 50Gi RWX Retain Bound production/app-storage kubectl get pvc -n production # NAME STATUS VOLUME CAPACITY ACCESS MODES # app-storage Bound nfs-pv-prod 50Gi RWX
StorageClass — dynamiczne provisioning
Dynamiczny provisioning eliminuje ręczne tworzenie PV — K8s robi to automatycznie po stworzeniu PVC. StorageClass definiuje jaki storage i z jakimi parametrami:
# StorageClass dla Longhorn (on-prem distributed storage)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: longhorn-ssd
annotations:
storageclass.kubernetes.io/is-default-class: "true" # domyslna klasa
provisioner: driver.longhorn.io
parameters:
numberOfReplicas: "3" # replikacja danych na 3 wezlach
staleReplicaTimeout: "30"
diskSelector: "ssd" # tylko dyski oznaczone jako SSD
reclaimPolicy: Retain # zachowaj dane po usunieciu PVC!
allowVolumeExpansion: true # pozwol na resize PVC
volumeBindingMode: WaitForFirstConsumer # poczekaj az pod zostanie zaschedulowany
---
# StorageClass dla NFS (CSI Driver)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-csi
provisioner: nfs.csi.k8s.io
parameters:
server: 192.168.1.100
share: /exports/k8s
reclaimPolicy: Delete
mountOptions:
- hard
- nfsvers=4.1
---
# StorageClass dla local storage (pin pod do wezla z dyskiem)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-ssd
provisioner: kubernetes.io/no-provisioner # brak dynamicznego prov.
volumeBindingMode: WaitForFirstConsumer # WYMAGANE dla local
reclaimPolicy: Retain Porównanie backendów storage
| Backend | Access Modes | Latency | Replikacja | Snapshots | Kiedy używać |
|---|---|---|---|---|---|
| Local storage | RWO | Najniższa | Nie | Nie | Dev, stateless, bazy z własną replikacją |
| NFS | RWO, ROX, RWX | Sieciowa | Nie (serwer) | Nie | Współdzielone pliki, CMS, uploads |
| Longhorn | RWO, RWX* | Sieciowa | Tak (2-3) | Tak | On-prem produkcja, mały klaster |
| Ceph/Rook | RWO, ROX, RWX | Sieciowa | Tak (3+) | Tak | Duży on-prem klaster, enterprise |
| AWS EBS CSI | RWO | Niska (gp3) | Tak (AZ) | Tak | AWS EKS, produkcja chmurowa |
Resize PVC — zwiększanie rozmiaru
# Sprawdz czy StorageClass obsługuje resize
kubectl get storageclass longhorn-ssd -o jsonpath='{.allowVolumeExpansion}'
# true — OK, mozna resizowac
# Zwieksz PVC z 10Gi do 50Gi (edit spec.resources.requests.storage)
kubectl patch pvc app-storage -n production \
-p '{"spec":{"resources":{"requests":{"storage":"50Gi"}}}}'
# Monitoruj status resizu
kubectl describe pvc app-storage -n production
# Events:
# Warning ExternalExpanding Waiting for volume controller to expand volume
# Normal Resizing External resizer is resizing volume
# Normal FileSystemResizeRequired Require file system resize of volume
# Dla niektorych CSI wymagany restart poda (zeby OS zmienilo rozmiar FS)
kubectl rollout restart deployment my-app -n production
# Weryfikacja po resizu
kubectl exec -n production deploy/my-app -- df -h /var/data Backup z Velero — snapshots PV i manifesty K8s
# Instalacja Velero z backendem Backblaze B2 / S3-compatible velero install \ --provider aws \ --plugins velero/velero-plugin-for-aws:v1.9.0 \ --bucket velero-backups \ --secret-file ./credentials-velero \ --backup-location-config region=us-east-1,s3Url=https://s3.eu-central-003.backblazeb2.com,s3ForcePathStyle=true \ --snapshot-location-config region=eu-central-1 \ --use-volume-snapshots=true # Jednorazowy backup całego namespace velero backup create production-backup \ --include-namespaces=production \ --wait # Harmonogram codziennych backupow velero schedule create daily-backup \ --schedule="0 2 * * *" \ --include-namespaces=production \ --ttl 720h0m0s # przechowuj 30 dni # Restore namespace velero restore create --from-backup production-backup # Status backupow velero backup get velero backup describe production-backup --details