Kubernetes'te Kalıcı Depolama: CSI, PV, StorageClass ve StatefulSet
Kubernetes, durum bilgisi olmayan iş yüklerine yönelik bir platform olarak doğdu ancak uygulamaların gerçekliği kurumsal ve çok farklı: veritabanları, mesaj kuyrukları, kalıcı önbellek sistemleri, Paylaşılan dosya sistemleri. Hepsi bir Pod'un yaşam döngüsü boyunca ayakta kalabilecek depolama alanına ihtiyaç duyar. Bu depolamayı bulut sağlayıcıları arasında güvenilir, yüksek performanslı ve taşınabilir bir şekilde yönetin farklı ve günlük üretimin en somut zorluklarından biri.
Bu makalede Kubernetes depolama katmanının tamamını keşfedeceğiz: Container Storage'dan Sağlayıcılar, PersistentVolume ve ile entegrasyonu standartlaştıran Arayüz (CSI) Dinamik provizyon için StorageClass, en fazla Durum BilgiliSet için Kubernetes üzerinde PostgreSQL, Cassandra ve Redis gibi veritabanlarını yönetin.
Ne Öğreneceksiniz
- Kubernetes depolama modeli: Volume, PersistentVolume, PersistentVolumeClaim
- Konteyner Depolama Arayüzü (CSI) nasıl çalışır ve en çok kullanılan sürücüler
- StorageClass ve dinamik provizyon: AWS EBS, GCE PD, Azure Disk için yapılandırma
- Erişim Modu: ReadWriteOnce, ReadOnlyMany, ReadWriteMany - ne zaman hangisi kullanılacak
- StatefulSet: kararlı kimlik, otomatik PVC'ler, düzenli güncelleme
- StatefulSet ile Kubernetes'te PostgreSQL nasıl çalıştırılır
- Velero ile PersistentVolumes'un yedeklenmesi ve geri yüklenmesi
Kubernetes Depolama Modeli
Kubernetes, depolama için "gerekli olanı" ayıran bir soyutlama hiyerarşisi tanımlar (PersistentVolumeClaim) "olarak ve sağlanan" (PersistentVolume ve StorageClass) seçeneğinden. Bu geliştiricilerin sağlayıcı ayrıntılarını bilmeden depolama talebinde bulunmasına olanak tanır altta yatan bulut.
Depolama İlkeleri
| Kaynak | Süpürgeler | Kim yönetiyor | Tanım |
|---|---|---|---|
| Hacim | Kapsül | Geliştirici | Pod'un yaşam döngüsüne bağlı geçici depolama |
| Kalıcı Hacim (PV) | Kümeler | Yönetici / Sağlayıcı | Kümedeki depolama parçası, Pod'lardan bağımsız yaşam döngüsü |
| Kalıcı Hacim Talebi (PVC) | Ad alanı | Geliştirici | Bir Pod'dan depolama isteğinde bulunma |
| Depolama Sınıfı | Kümeler | Yönetici | Depolama "tipini" ve sağlayıcıyı tanımlar |
PersistentVolume'un Yaşam Döngüsü
Bir PV'nin yaşam döngüsü farklı durumlardan geçer. Onları anlamak çok önemli sorun giderme:
- Mevcut: PV mevcuttur ve ücretsizdir, herhangi bir PVC ile ilişkili değildir
- Bağlı: PV, gereksinimleri karşılayan bir PVC'ye bağlanmıştır
- Piyasaya sürülmüş: PVC ortadan kaldırıldı ancak PV henüz mevcut değil (veriler hala orada)
- Arızalı: PV otomatik geri alma işleminde başarısız oldu
# Verifica lo stato dei PersistentVolume nel cluster
kubectl get pv -o wide
# Output tipico:
# NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS
# pv-db-001 100Gi RWO Retain Bound production/postgres fast-ssd
# pv-db-002 100Gi RWO Retain Available fast-ssd
# Descrizione dettagliata di un PV
kubectl describe pv pv-db-001
# Verifica i PVC in un namespace
kubectl get pvc -n production
kubectl describe pvc postgres-data -n production
Konteyner Depolama Arayüzü (CSI)
CSI'dan önce her depolama sağlayıcısının kendi kodlarında yerleşik eklentileri bulundurması gerekiyordu Kubernetes kaynağı (ağaç içi eklentiler). Bu güçlü ve etkili bir bağlantı oluşturdu eklentileri Kubernetes'ten bağımsız olarak güncellemek zordur. CSI bu işi çözüyor üçüncü tarafların depolama sürücüleri oluşturmasına olanak tanıyan standart bir gRPC arayüzüyle bağımsız Kubernetes Pod'ları olarak.
Ana CSI Sürücüleri
| CSI Sürücüleri | Sağlayıcılar | Depolama türü | OkumaYazmaÇok |
|---|---|---|---|
| aws-ebs-csi-sürücü | AWS | Blok (gp3, io2) | No |
| aws-efs-csi sürücüsü | AWS | NFS (EFS) | Si |
| gce-pd-csi sürücüsü | GCP | Blok (pd-ssd, pd-dengeli) | Hayır (yalnızca RWX FileStore) |
| azuredisk-csi sürücüsü | Azure | Blok (Premium SSD) | No |
| azurefile-csi-sürücü | Azure | NFS (Azure Dosyaları) | Si |
| csi-rook-ceph | Kale/Cef | Blok/FS/Nesne | Evet (CephFS) |
| longhorn | Çiftlik sahipleri | Blok dağıtıldı | Evet (NFS ile) |
CSI EBS Sürücüsünün EKS'ye Kurulumu
# Installa il driver CSI EBS su Amazon EKS
# Prima, crea un IAM Role con le policy necessarie
aws eks create-addon \
--cluster-name my-cluster \
--addon-name aws-ebs-csi-driver \
--service-account-role-arn arn:aws:iam::ACCOUNT_ID:role/EBSCSIRole
# Verifica il daemonset del driver CSI
kubectl get daemonset -n kube-system ebs-csi-node
kubectl get deployment -n kube-system ebs-csi-controller
StorageClass: Dinamik Sağlama
Statik provizyon (PV'lerin manuel olarak oluşturulması) üretimde pratik değildir. ile dinamik provizyon, Kubernetes bir PVC geldiğinde otomatik olarak PV oluşturur StorageClass'ta yapılandırılan CSI sürücüsü kullanılarak oluşturulur.
AWS EBS için StorageClass
# storage-classes-aws.yaml
# StorageClass per dischi gp3 (performance ottimale)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
annotations:
storageclass.kubernetes.io/is-default-class: "false"
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer # IMPORTANTE: evita cross-AZ mounting
reclaimPolicy: Retain # Protegge i dati in produzione
allowVolumeExpansion: true
parameters:
type: gp3
iops: "3000"
throughput: "125"
encrypted: "true"
kmsKeyId: "arn:aws:kms:eu-west-1:ACCOUNT:key/KEY_ID"
---
# StorageClass per io2 (database ad alto IOPS)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ultra-fast-ssd
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Retain
allowVolumeExpansion: true
parameters:
type: io2
iops: "32000"
encrypted: "true"
---
# StorageClass per EFS (ReadWriteMany, NFS)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: shared-storage
provisioner: efs.csi.aws.com
reclaimPolicy: Retain
parameters:
provisioningMode: efs-ap
fileSystemId: fs-XXXXXXXX
directoryPerms: "700"
GKE için StorageClass (Google Kubernetes Engine)
# storage-classes-gke.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd-gke
provisioner: pd.csi.storage.gke.io
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Retain
allowVolumeExpansion: true
parameters:
type: pd-ssd
replication-type: regional-pd # replica su 2 zone
availability-class: regional-hard-failover
hacimBindingMode: Neden WaitForFirstConsumer
Her zaman kullan WaitForFirstConsumer yerine Immediate ne zaman
kümenin birden fazla Erişilebilirlik Alanı vardır. İle Immediate, PV oluşturulur
provizyonun planlandığı bölgede (bölgeden farklı olabilir)
Pod'un nerede planlanacağı. Sonuç: Pod, birimi bağlayamıyor.
WaitForFirstConsumer PV'yi Pod ile aynı alanda oluşturur.
PersistentVolumeUygulamada İddia
PVC ve bir Pod'un nasıl depolama gerektirdiği. PVC boyutu, erişim modunu belirtir ve StorageClass. Kubernetes uyumlu bir PV bulur veya oluşturur ve bunu PVC'ye bağlar.
# pvc-database.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-data
namespace: production
labels:
app: postgres
tier: database
annotations:
# Snapshot policy (con alcuni storage providers)
storageclass.kubernetes.io/is-default-class: "false"
spec:
accessModes:
- ReadWriteOnce
storageClassName: fast-ssd
resources:
requests:
storage: 100Gi
# Espandi a 200Gi in futuro con:
# kubectl patch pvc postgres-data -p '{"spec":{"resources":{"requests":{"storage":"200Gi"}}}}'
Erişim Modu: Doğru Olanı Seçin
| Erişim Modu | Kısaltma | Bu ne anlama geliyor | Tipik kullanım |
|---|---|---|---|
| OkumaYazBir Kez | RWO | Yalnızca bir okuma/yazma düğümü | Veritabanları, tek örnekli uygulamalar |
| Salt OkunurÇok | ROX | Birçok salt okunur düğüm | Paylaşılan statik veriler, yapılandırmalar |
| OkumaYazmaÇok | RWX | Birçok okuma/yazma düğümü | Paylaşılan NFS, yükleme işleyicisi |
| OkumaYazmaOncePod | RWOP | Yalnızca bir okuma/yazma Pod'u | Tek Pod için özel depolama (K8s 1.29+) |
StatefulSet: Kararlı Kimlikle İş Yükü
Dağıtımlar, durum bilgisi olmayan iş yükleri için mükemmeldir ancak veritabanları ve uygulamalar için mükemmeldir. kararlı kimlik gerektirir (tahmin edilebilir ana bilgisayar adı, ayrılmış birim, önyükleme sırası) ona hizmet ediyor Durum BilgiliSet. Dağıtımlarla karşılaştırıldığında temel farklar:
- Kararlı kimlik: Pod'ların tahmin edilebilir isimleri var:
myapp-0,myapp-1,myapp-2 - Önyükleme sırası: Bölmeler sırayla başlatılır (0, sonra 1, sonra 2) ve ters sırada kapatılır
- Özel PVC'ler: Her Pod, kendi PVC'sini alır
volumeClaimTemplates - Başsız Hizmet: Her Pod'un sabit bir DNS girişi vardır:
myapp-0.myapp.namespace.svc.cluster.local
StatefulSet ile Kubernetes'te PostgreSQL
İşte StatefulSet ile PostgreSQL için eksiksiz ve üretime hazır bir kurulum: yapılandırma için ConfigMap, kimlik bilgileri için Gizli ve başsız Hizmet dahil:
# postgres-statefulset.yaml
apiVersion: v1
kind: Service
metadata:
name: postgres
namespace: production
labels:
app: postgres
spec:
ports:
- port: 5432
name: postgres
clusterIP: None # Headless Service - abilita il DNS per Pod individuali
selector:
app: postgres
---
# Service per accesso al master (read/write)
apiVersion: v1
kind: Service
metadata:
name: postgres-master
namespace: production
spec:
ports:
- port: 5432
selector:
app: postgres
role: master
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
namespace: production
spec:
serviceName: postgres # deve corrispondere al nome del headless Service
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
# Anti-affinity: distribuisce le repliche su nodi diversi
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: postgres
topologyKey: kubernetes.io/hostname
initContainers:
# init container per configurare i permessi del volume
- name: init-postgres
image: postgres:16
command:
- bash
- "-c"
- |
chown -R 999:999 /var/lib/postgresql/data
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
containers:
- name: postgres
image: postgres:16
ports:
- containerPort: 5432
name: postgres
env:
- name: POSTGRES_DB
value: myapp
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres-credentials
key: username
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-credentials
key: password
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
- name: postgres-config
mountPath: /etc/postgresql/postgresql.conf
subPath: postgresql.conf
resources:
requests:
memory: "2Gi"
cpu: "1000m"
limits:
memory: "4Gi"
cpu: "2000m"
livenessProbe:
exec:
command:
- pg_isready
- -U
- $(POSTGRES_USER)
- -d
- $(POSTGRES_DB)
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
exec:
command:
- pg_isready
- -U
- $(POSTGRES_USER)
- -d
- $(POSTGRES_DB)
initialDelaySeconds: 5
periodSeconds: 5
volumes:
- name: postgres-config
configMap:
name: postgres-config
# PVC template: ogni Pod ottiene il proprio volume da 100Gi
volumeClaimTemplates:
- metadata:
name: postgres-data
spec:
accessModes:
- ReadWriteOnce
storageClassName: fast-ssd
resources:
requests:
storage: 100Gi
PostgreSQL Yapılandırması için ConfigMap
# postgres-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: postgres-config
namespace: production
data:
postgresql.conf: |
# Performance tuning per 4GB RAM
shared_buffers = 1GB
work_mem = 64MB
maintenance_work_mem = 256MB
effective_cache_size = 3GB
# WAL settings
wal_level = replica
max_wal_senders = 5
wal_keep_size = 1GB
# Checkpoint
checkpoint_completion_target = 0.9
max_wal_size = 4GB
min_wal_size = 1GB
# Connection settings
max_connections = 200
# Logging
log_min_duration_statement = 1000 # log query lente >1s
log_checkpoints = on
log_connections = on
log_disconnections = on
Birim Anlık Görüntüsü ve Yedekleme
Birim Anlık Görüntüleri, PersistentVolumes'un belirli bir zamanda yedeklerini oluşturmanıza olanak tanır bulut sağlayıcının yerel yeteneklerini (EBS anlık görüntüsü, GCE PD anlık görüntüsü vb.) kullanarak.
# Installa le CRD per Volume Snapshot (se non presenti)
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml
# VolumeSnapshotClass
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
name: ebs-snapshot-class
driver: ebs.csi.aws.com
deletionPolicy: Retain
---
# Crea uno snapshot del volume di PostgreSQL
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: postgres-snapshot-20260801
namespace: production
spec:
volumeSnapshotClassName: ebs-snapshot-class
source:
persistentVolumeClaimName: postgres-data-postgres-0
---
# Verifica lo stato dello snapshot
kubectl get volumesnapshot -n production
# Restore da snapshot: crea un nuovo PVC da snapshot
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-data-restored
namespace: production
spec:
accessModes:
- ReadWriteOnce
storageClassName: fast-ssd
resources:
requests:
storage: 100Gi
dataSource:
name: postgres-snapshot-20260801
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
Tam Küme Yedeklemesi için Velero
Velero, tüm Kubernetes kümelerinin yedeklenmesi ve geri yüklenmesi için referans araçtır. PersistentVolumes dahil:
# Installa Velero con il plugin EBS
velero install \
--provider aws \
--plugins velero/velero-plugin-for-aws:v1.8.0 \
--bucket my-velero-backups \
--backup-location-config region=eu-west-1 \
--snapshot-location-config region=eu-west-1 \
--secret-file ./credentials-velero
# Crea un backup del namespace production con i volume
velero backup create production-backup-20260801 \
--include-namespaces production \
--snapshot-volumes \
--wait
# Verifica il backup
velero backup describe production-backup-20260801
velero backup logs production-backup-20260801
# Schedule: backup giornaliero a mezzanotte
velero schedule create daily-production \
--schedule="0 0 * * *" \
--include-namespaces production \
--snapshot-volumes \
--ttl 720h # mantieni per 30 giorni
# Restore in un nuovo cluster
velero restore create --from-backup production-backup-20260801 \
--namespace-mappings production:production-restored
AI/ML İş Yükleri için Depolama
Makine öğrenimi eğitimi iş yüklerinin özel depolama gereksinimleri vardır: paralel erişim Genellikle aynı anda birden fazla GPU çalışanından gelen, büyük veri kümeleri için yüksek verim.
# PVC con ReadWriteMany per training distribuito
# Usa EFS (AWS) o CephFS (on-premise) per RWX
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ml-dataset-storage
namespace: ml-training
spec:
accessModes:
- ReadWriteMany
storageClassName: shared-storage # EFS o CephFS
resources:
requests:
storage: 10Ti # 10TB per dataset ImageNet, etc.
---
# Job di training che accede ai dati in parallelo
apiVersion: batch/v1
kind: Job
metadata:
name: distributed-training
namespace: ml-training
spec:
parallelism: 8 # 8 worker GPU in parallelo
completions: 8
template:
spec:
containers:
- name: trainer
image: pytorch/pytorch:2.3.0-cuda12.1-cudnn8-runtime
resources:
limits:
nvidia.com/gpu: "1"
volumeMounts:
- name: dataset
mountPath: /data
readOnly: true # tutti i worker leggono, nessuno scrive
- name: checkpoints
mountPath: /checkpoints
volumes:
- name: dataset
persistentVolumeClaim:
claimName: ml-dataset-storage
readOnly: true
- name: checkpoints
persistentVolumeClaim:
claimName: ml-checkpoints-rwx # RWX per checkpoint condivisi
Kubernetes Depolama için En İyi Uygulamalar
Üretim Depolama Kontrol Listesi
- Her zaman reclaimPolicy'yi kullanın: Retain Üretim verileri için.
DeletePVC silindiğinde verileri otomatik olarak siler - hacimBindingMode: WaitForFirstConsumer: Çok bölgeli kümelerde AZ'ler arası bağlama sorunlarından kaçının
- AllowVolumeExpansion: doğru: Kesinti süresi olmadan birimin genişletilmesine izin vermek için StorageClasses'ı yapılandırma
- Disk kullanımını izleyin: PVC kapasitenin %80'ini aştığında Prometheus'ta uyarıları yapılandırın
- Otomatik anlık görüntüler: VolumeSnapshotClass'ı ve zamanlanmış yedeklemeleri yapılandırma
- Geri yüklemeyi test edin: Test edilmemiş ve işe yaramaz bir yedekleme. Aylık geri yükleme testleri yapın
- PVC'leri role göre ayırın: Veriler için bir PVC, günlükler için bir PVC, geçici yedeklemeler için bir PVC
- Anti-afiniteli StatefulSet: Replikaları farklı düğümlere ve bölgelere dağıtın
Anti-Desen: Bunu Yapmayın
- HostPath'i üretimde kullanmayın: Pod'u belirli bir düğüme bağlar ve taşınabilir değildir
- Kalıcı veriler için emptyDir kullanmayın: Pod yeniden başlatıldığında temizlenir
- reclaimPolicy kullanmayın: Üretim verileri için silin: Yanlışlıkla her şeyi kaybedebilirsin
- Aynı PVC'yi (RWO) birden fazla Pod'a monte etmeyin: Veri bozulmasına neden olur
Prometheus ile Depolama İzleme
# Metriche chiave da monitorare con kube-state-metrics
# Aggiungi alert a Prometheus
# Alert: PVC vicino alla capacita massima
groups:
- name: kubernetes-storage
rules:
- alert: PVCStorageUsageHigh
expr: |
kubelet_volume_stats_used_bytes /
kubelet_volume_stats_capacity_bytes > 0.80
for: 5m
labels:
severity: warning
annotations:
summary: "PVC {{ $labels.persistentvolumeclaim }} e all'80% della capacita"
description: "Namespace: {{ $labels.namespace }}"
- alert: PVCStorageFull
expr: |
kubelet_volume_stats_used_bytes /
kubelet_volume_stats_capacity_bytes > 0.95
for: 2m
labels:
severity: critical
annotations:
summary: "PVC {{ $labels.persistentvolumeclaim }} quasi piena!"
- alert: PVCNotBound
expr: |
kube_persistentvolumeclaim_status_phase{phase="Pending"} == 1
for: 10m
labels:
severity: warning
annotations:
summary: "PVC {{ $labels.persistentvolumeclaim }} in stato Pending da 10 minuti"
Sonuçlar ve Sonraki Adımlar
Kubernetes depolama, kurumsal uygulamalar için en kritik katmanlardan biridir. üretim. Konteyner Depolama Arayüzü, herhangi bir konteyner depolama arayüzü ile entegrasyonu standart hale getirir. sağlayıcı, StorageClass ile dinamik provizyon, manuel çalışmayı ortadan kaldırır, e StatefulSets, veritabanlarını kararlı kimliklerle yönetmek için gerekli ilkelleri sağlar.
Üretimde sağlam depolamanın anahtarı mimari seçimlerin birleşimidir doğru (reclaimPolicy Retain, WaitForFirstConsumer, anti-affinity), proaktif izleme Prometheus ile ve Velero veya VolumeSnapshot ile düzenli olarak test edilen bir yedekleme stratejisiyle.
Kubernetes at Scale Serisinde Yaklaşan Makaleler
İlgili Seriler
- Kubernetes Ağı: eBPF ve Ağ Politikası ile CNI, Cilium
- Üretimde MLOps ve Makine Öğrenimi — ML veri kümeleri için depolama
- AI için PostgreSQL ve Vektör Arama







