Kubernetes PersistentVolume, PersistentVolumeClaim ve StorageClass Nedir?
10 min read

Kubernetes PersistentVolume, PersistentVolumeClaim ve StorageClass Nedir?

Kubernetes PersistentVolume, PersistentVolumeClaim ve StorageClass, kalıcı veri depolama ve talepleri yönetmek için kullanılan önemli kavramlardır.
Kubernetes PersistentVolume, PersistentVolumeClaim ve StorageClass Nedir?
Photo by Petr Magera / Unsplash

Kubernetes PersistentVolume ve PersistentVolumeClaim Kubernetes'te depolama kaynaklarını yönetmek için kullanılan iki nesnedir. PersistentVolume bir depolama kaynağını temsil ederken, PersistentVolumeClaim bu kaynağı isteyen Pod'lar tarafından kullanılabilecek şekilde birbirine bağlanmasını sağlar.

Bir önceki yazımızda Kubernetes Volume konusunu detaylı işlemiştik. Cloud provider ve NFS gibi volume tiplerinde farkedeceğiniz üzere volume kullanacak geliştiriciler ilgili volume için gerekli bağlantı ve teknik detaylara sahip olmak zorundadırlar. Örneğin bir NFS volume kullanacaksanız ilgili NFS sunucun bağlantı adresi, expose ettiği dizin ve varsa credentials gibi birçok teknik bilgiye sahip olması gerekir. Fakat bu şekilde infrastructure ve diğer önemli bilgiler ortalıkta dolaşır hale gelecektir.

Kubernetes Volume Nedir?
Kubernetes Volume, Container nesnelerinin kullandığı disk kaynaklarıdır

İdeal olarak, uygulamalarını Kubernetes üzerinde dağıtan bir geliştirici, pod'larını çalıştırmak için ne tür fiziksel sunucuların kullanıldığını bilmek zorunda olmadığı gibi, altında ne tür bir depolama teknolojisinin kullanıldığını asla bilmek zorunda kalmamalıdır. Infrastructure ile ilgili işlemler sadece Kubernetes cluster yöneticisinin etki alanında olmalıdır.

Bir geliştirici, uygulamaları için belirli bir miktarda kalıcı depolama alanına ihtiyaç duyduğunda, tıpkı bir bölme oluştururken CPU, bellek ve diğer kaynakları talep edebildikleri gibi, bunu Kubernetes'ten talep edebilir. Sistem yöneticisi, uygulamalara istediklerini verebilmesi için cluster'ı önceden yapılandırabilir.

1. PersistentVolume ve PersistentVolumeClaim Nesnelerinin Amacı

Uygulamaların, infrastructure bilgileri ve özellikleriyle uğraşmak zorunda kalmadan bir Kubernetes cluster'da depolama alanı talep etmesini sağlamak için PersistentVolume ve PersistentVolumeClaim nesneleri kullanılır.

Bir Pod içinde PersistentVolume kullanmak, normal bir Pod volume kullanmaktan biraz daha karmaşıktır. Aşağıdaki şekil; Pod'lar, PersistentVolumeClaim, PersistentVolume ve arkada yatan temel depolama biriminin birbiriyle nasıl ilişkili olduğunu gösterir.

Cluster yöneticisi, gerekli tüm teknik detaylarla beraber PersistentVolume ayarladıktan sonra, geliştirici bu detaylarla uğraşmadan sadece kendi Pod'unda kullanmak istediği alan miktarını ve özelliklerini belirterek kendisine bir Volume tahsis eder.

PersistentVolumeClaim daha sonra bir Pod içindeki volume'lardan biri olarak kullanılabilir. Diğer kullanıcılar, aktif kullanılan PersistentVolumeClaim silinip serbest bırakılana kadar aynı PersistentVolume'u kullanamazlar.

2. PersistentVolume Oluşturmak

PersistentVolume, bir disk veya depolama alanı gibi bir kaynağı temsil eder ve bir kez oluşturulduğunda, cluster içinde birçok Pod tarafından paylaşılabilir. Bu, disk kaynaklarını ve disk kaynaklarının kullanımını merkezi bir şekilde yönetmeyi mümkün kılar.

Kubernetes'te bir PersistentVolume öncelikle, bir depolama kaynağına ihtiyacınız var. Örneğin, bir bulut sağlayıcısında (AWS, Google Cloud, vb.) bir depolama servisi veya fiziksel bir sunucuda bir disk olabilir.

Ardından PersistentVolume manifest dosyası örneğini oluşturalım.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mongodb-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteOnce
  - ReadOnlyMany
  persistentVolumeReclaimPolicy: Retain
  gcePersistentDisk:
    pdName: mongodb
    fsType: ext4

Bu manifest dosyasında:

  • storage: "PersistentVolume" boyutunu belirtir.
  • accessModes: ReadWriteOnce veya ReadOnlyMany gibi, PersistentVolume ile kullanılacak Pod'ların "access mode" ayarını belirtir.
  • persistentVolumeReclaimPolicy: PersistentVolume silindiğinde, Retain (yani verilerin korunması için) veya Delete (verilerin silinmesi için) gibi reclaim politikasını belirtir.
  • gcePersistentDisk: Daha önceki "Kubernetes Volume Nedir?" yazımızda belirttiğimiz gibi kullanılacak GCE persistence disk objesinin özellikleridir.

Access Mode için kullanabileceğiniz değerler ve açıklamaları da şu şekildedir:

  • ReadWriteOnce (RWO): Yalnızca tek bir node, okuma ve yazma işlemi için Volume'u mount edebilir.
  • ReadOnlyMany (ROX): Birden fazla node, sadece okuma işlemi için Volume'u mount edebilir.
  • ReadWriteMany (RWX): Birden fazla node, hem okuma hem de yazma işlemi için Volume'u mount edebilir.
💡
RWO, ROX ve RWX, pod sayısıyla değil, aynı anda volume'u kullanabilen worker node sayısıyla ilgilidir!

Access mode seçeneklerinden hangisini hangi volume tipinde kullanabileceğinizi şu bağlantıdaki linkten görebilirsiniz.

Manifest dosyası hazır olduktan sonra kubectl create veya kubectl apply komutlarından birisi ile PersistentVolume nesnesini oluşturabilirsiniz.

 kubectl create -f pv.yaml

PersistentVolume nesnesini oluşturduktan sonra kubectl get pv komutu ile görüntüleyelim:

$ kubectl get pv
NAME         CAPACITY  RECLAIMPOLICY  ACCESSMODES  STATUS      CLAIM
mongodb-pv   1Gi       Retain         RWO,ROX      Available 
💡
kubectl get komutunda uzunca persistencevolume yazmak yerine kısaca pv yazabilirsiniz.

Beklendiği gibi, henüz PersistentVolumeClaim oluşturmadığınız için PersistentVolume, sadece Available olarak gösteriliyor.

💡
PersistentVolume aşağıdaki resimde göreceğiniz gibi herhangi bir namespace'e ait değildir. Node gibi cluster düzeyindeki objelerdendir.

3. PersistentVolumeClaim Oluşturmak

PersistentVolumeClaim, bir Pod'un bir veya daha fazla PersistentVolume kullanması için istekte bulunabileceği bir Kubernetes nesnesidir. Bir PersistentVolumeClaim nesnesi oluşturulduğunda, Kubernetes tarafından uygun bir PersistentVolume seçilir ve tahsil edilir. Bu, bir Pod'un depolama alanı ihtiyaçlarına yönelik dinamik bir çözüm sağlar.

Pod'lar direkt olarak PersistentVolume nesnesini kullanamazlar. Volume ihtiyaçları olduğunda öncelikle PersistentVolumeClaim nesnesi oluşturmaları gerekir.

PersistentVolumeClaim nesnesi oluşturabilmek için aşağıdaki gibi bir manifest dosyası hazırlayalım.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mongodb-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: ""

Bu manifest dosyasında:

  • accessModes: ReadWriteOnce veya ReadOnlyMany gibi, PersistentVolumeClaim ile kullanılacak Pod'ların "access mode" ayarını belirtir.
  • storage: İhtiyacınız olan depolama alanı boyutunu belirtir.
  • storageClassName: Varsa kullanılacak StorageClass'ı belirtir. Bu yazının sonunda 6.3. başlıkta yer alan StorageClass başlığında detayları öğreneceksiniz.
💡
Eğer birden fazla seçilebilecek uygun PersistentVolume mevcutsa, PersistentVolumeClaim oluşturduğunuzda aralarındaki en düşük boyutlu olan seçilir. Örneğin 3 ve 5GB lık PersistentVolume varsa ve 2GB lık bir PersistentVolumeClaim oluşturursanız, PersistentVolume nesneleri arasından 3GB lık olan tahsil edilir.

Manifest dosyası hazır olduktan sonra kubectl create veya kubectl apply komutlarından birisi ile PersistentVolumeClaim nesnesini oluşturabilirsiniz.

 kubectl create -f pvc.yaml

PersistentVolumeClaim nesnesini oluşturduktan sonra kubectl get pvc komutu ile görüntüleyelim:

$ kubectl get pvc
NAME         STATUS  VOLUME      CAPACITY  ACCESSMODES  AGE
mongodb-pvc  Bound   mongodb-pv  1Gi       RWO          3s

Bir volume talep ettikten PersistentVolume listesine tekrar bakarsak artık Available yerine Bound durumuna geçmiş olduğuınu görürüz.

$ kubectl get pv
NAME         CAPACITY  RECLAIMPOLICY  ACCESSMODES  STATUS    CLAIM                 AGE
mongodb-pv   1Gi       Retain         RWO,ROX      Bound     default/mongodb-pvc   1m

PersistentVolume, artık default/mongodb-pvc isimli PersistentVolumeClaim'e tahsis edilmiştir. Eğer başka bir PersistentVolumeClaim daha oluşturursanız aynı PersistentVolume üzerinden bir alan alamayacağı için Pending durumunda kaldığını görürsünüz.

kubectl get pvc
NAME          STATUS    VOLUME         CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mongodb-pvc   Bound     mongodb-pv     1          RWO                           16s
mysql-pvc     Pending

default, talebin bulunduğu namespace adıdır. PersistentVolume kaynaklarının cluster genelinde bir nesne olduğunu ve bu nedenle belirli bir namespace ile oluşturulamayacağını, ancak PersistentVolumeClaims'in yalnızca belirli bir namespace için oluşturulabileceğini zaten söylemiştik. Bu andan sonra PersistentVolumeClaims nesneleri yalnızca aynı namespace içinde yer alan pod'lar tarafından kullanılabilirler.

4. Pod'ların PersistentVolumeClaim Kullanması

PersistentVolume artık bizim kullanımımıza tahsil edildi. Siz tekrar bırakana kadar başka hiç kimse aynı volume'u talep edemez. Bir Pod içinde kullanmak için, aşağıdaki örnekte gösterildiği gibi, Pod içinde volume'u PersistentVolumeClaim'in adıyla belirtmeniz gerekir.

apiVersion: v1
kind: Pod
metadata:
  name: mongodb
spec:
  containers:
  - image: mongo
    name: mongodb
    volumeMounts:
    - name: mongodb-data
      mountPath: /data/db
    ports:
    - containerPort: 27017
      protocol: TCP
  volumes:
  - name: mongodb-data
    persistentVolumeClaim:
      claimName: mongodb-pvc 

Artık bu volume dizini içerisinde oluşturduğunuz dosyalar hem Pod silinse bile kalıcı olacak, hem de aynı PersistentVolumeClaim'i kullanan Pod'lar arasından ortak kullanılabilecektir.

Pod manifestinde gördüğünüz gibi, Pod'u oluşturan kişi herhangi bir teknik altyapı ve yapılandırma işiyle uğraşmadan sadece ne kadar alan ihtiyacı olduğunu belirterek bir volume aldı ve mount etti. Böylece kubernetes admini dışında kimse bu detaylarla boğuşmamış ve bu bilgilerde gün yüzüne çıkmamış oldu.

5. PersistentVolume Reclaim ve Life Cycle

PersistentVolume nesnesini oluştururken persistentVolumeReclaimPolicy parametresine verdiğimiz değerlere göre volume'lerin davranışı değişir. Bu değerler şunlar olabilir:

  • Retain
  • Recycle
  • Delete

5.1. Retain

persistentVolumeReclaimPolicy değeri Retain olarak ayarlandığında, PersistentVolumeClaim nesnesini silseniz bile dosyalarınızın silinmemesi için PersistentVolume silinmez ve Released durumuna geçer. Böylece yeni PersistentVolumeClaim nesneleri artık bu PersistentVolume nesnesini kullanamazlar.

Eğer bir PVC yi sildikten sonra PersistentVolume listesine bakarsak PV nin Released durumunda olduğunu, PersistentVolumeClaim listesine bakarsakta PVC nin Pending durumunda olduğunu görürüz.

$ kubectl delete pvc mongodb-pvc
persistentvolumeclaim "mongodb-pvc" deleted
$ kubectl get pv
NAME        CAPACITY  ACCESSMODES  STATUS    CLAIM REASON         AGE
mongodb-pv  1Gi       RWO,ROX      Released  default/mongodb-pvc  5m
$ kubectl create -f pvc.yaml
$ kubectl get pvc
NAME         STATUS   VOLUME  CAPACITY  ACCESSMODES  AGE
mongodb-pvc  Pending

İlgili PersistentVolume'u serbest bırakabilmek için kubectl edit pv mongodb-pv komutu ile açarak claimRef bölümünü silmeniz ve dosyayı kaydederek kapatmanız gerekir.

Ardından tekrar PersistentVolume listesine baktığımızda artık ilgili PV nin Available olduğunu görürsünüz. Bu andan itibaren yeni bir PersistentVolumeClaim ile kaldığınız yerden volume'u kullanmaya devam edebilirsiniz.

$ kubectl get pv
NAME        CAPACITY  ACCESSMODES  STATUS  
mongodb-pv  1Gi       RWO,ROX      Available

5.2. Recycle ve Delete

persistentVolumeReclaimPolicy değeri Recycle olarak ayarlandığında, PersistentVolumeClaim silindiğinde, PersistentVolume içindeki veriler otomatik olarak temizlenir ve PersistentVolume yeniden kullanıma hazır hale getirilir.

persistentVolumeReclaimPolicy değeri Delete olarak ayarlandığında, PersistentVolumeClaim silindiğinde hem PersistentVolume hem de içindeki verileri tamamen siler. Veriler geri dönüşümsüz bir şekilde kaybolur ve geri kazanılamaz. Bu politika, verilerin tamamen temizlenmesini ve kaynakların geri kazanılmasını sağlar.

6. StorageClass ile PersistentVolume Nesnelerinin Dinamil Oluşturulması

PersistentVolume ve PersistentVolumeClaim kullanmanın, geliştiricinin arkada kullanılan gerçek depolama teknolojisiyle uğraşmasına gerek kalmadan persistence depolama alanı elde edebilmesini nasıl kolaylaştırdığını gördünüz. Ancak bu, yine de bir cluster yöneticisinin persistence depolama alanını önceden sağlamasını gerektirir. Neyse ki Kubernetes, PersistentVolume nesnelerinin dinamik olarak oluşturulmasıyla bu işi otomatik olarak da gerçekleştirebilir.

Cluster yöneticisi, PersistentVolume oluşturmak yerine, bir PersistentVolume provider dağıtabilir ve kullanıcıların ne tür PersistentVolume istediklerini seçmelerine izin vermek için bir veya daha fazla StorageClass nesnesi tanımlayabilir. Kullanıcılar, PersistentVolumeClaims'lerinde StorageClass'a başvurabilir ve provisioner, persistence depolama alanı sağlarken bunu dikkate alır.

💡
PersistentVolume gibi, StorageClass nesneleride cluster genelinde bir nesnedir.

Kubernetes, popüler cloud providerlar için provisionerlar içerir. Bu nedenle yöneticinin her zaman bir provisioner deploy etmesi gerekmez. Ancak Kubernetes on-demand bir cluster içindeyse özel bir provisioner deploy edilmesi gerekir.

Yöneticinin bir grup PersistentVolume'u önceden oluşturması yerine, bir veya iki (veya daha fazla) StorageClass tanımlaması ve bir PersistentVolumeClaim yoluyla her istendiğinde sistemin yeni bir PersistentVolume oluşturmasına izin vermesi gerekir. Bununla ilgili harika olan şey, PersistentVolume nesnelerinin tükenmesinin imkansız olmasıdır (fakat depolama alanınız bitebilir).

6.1. StorageClass Nesnesinin Oluşturulması

Bir kullanıcının, yeni bir PersistentVolume oluşturulmasına neden olacak bir PersistentVolumeClaim oluşturabilmesi için, bir yöneticinin bir veya daha fazla StorageClass kaynağı oluşturması gerekir. Aşağıdaki bir örneğine bakalım:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-ssd
  zone: europe-west1-b

Oluşturulan StorageClass nesnesini kubectl get sc komutu ile listeleyebilirsiniz.

$ kubectl get sc
NAME                TYPE
fast                kubernetes.io/gce-pd
standard (default)  kubernetes.io/gce-pd
💡
Listeye baktığınızda göreceğiniz standard StorageClass, kullandığınız provisioner tarafından otomatik olarak oluşturulur. Böylece PVC manifestlerinizde SC belirtmezseniz kullanılacak default SC tanımlanmış olur.

StorageClass nesnesi, bir PersistentVolumeClaim bu StorageClass'ı istediğinde, PersistentVolume'u oluşturmak için hangi provisioner kullanılması gerektiğini belirtir. StorageClass tanımında tanımlanan parametreler, sağlayıcıya iletilir ve her bir provisioner eklentisine özeldir.

Örneğin burada, StorageClass, Google Compute Engine (GCE) Persistent Disk (PD) provisioner kullanır. Bu, Kubernetes'in GCE'de çalışırken kullanılabileceği anlamına gelir. Diğer bulut sağlayıcıları için diğer sağlayıcıların kullanılması gerekir.

Kullanabileceğiniz tüm provisioner listesine ulaşabilmek için tıklayınız

6.2. PersistentVolumeClaim ile StorageClass Nesnesinin Kullanılması

StorageClass nesnesi oluşturulduktan sonra, kullanıcılar kendi PersistentVolumeClaims'lerinde StorageClass adıyla istekte bulunabilirler.

Aşağıdaki YAML örneğinde yukarıda oluşturduğumuz fast isimli StorageClass nesnesinin nasıl kullanılacağını görebilirsiniz.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mongodb-pvc
spec:
  storageClassName: fast
  resources:
    requests:
      storage: 100Mi
  accessModes:
  - ReadWriteOnce

Boyut ve access mode belirtmenin yanı sıra, PersistentVolumeClaim artık kullanmak istediğiniz depolama sınıfını da belirtiyor. Talebi oluşturduğunuzda, PersistentVolume, fast StorageClass nesnesinde yer alan provisioner tarafından oluşturulur.

💡
PersistentVolumeClaim ile talep ettiğiniz kaynakları karşılayabilen ve manual eklenen bir PersistentVolume mevcut olsa bile provisioner kullanılır ve yeni bir PersistentVolume oluşturulur.

Artık PVC listemize bakarsak oluşturduğumuz PVC'nin Bound durumunda olduğunu ve kullanılan StorageClass nesnesini görebiliriz.

$ kubectl get pvc mongodb-pvc
NAME         STATUS  VOLUME        CAPACITY  ACCESSMODES  STORAGECLASS
mongodb-pvc  Bound   pvc-1e6bc048  1Gi       RWO          fast 

PV listemize bakarsakta otomatik oluşturulan PV nesnesini görebiliriz.

$ kubectl get pv
NAME          CAPACITY  ACCESSMODES  RECLAIMPOLICY  STATUS     STORAGECLASS
mongodb-pv    1Gi       RWO,ROX      Retain         Released
pvc-1e6bc048  1Gi       RWO          Delete         Bound      fast

Son olarak GKE platformuna gidip disk servisini incelerseniz oluşturulan diski görebilirsiniz.

6.3. Default StorageClass Yerine Önceden Tanımlanan PersistenceVolume Nesnelerini Kullanmak

Kullandığınız provisioner'ların otomatik olarak default bir StorageClass tanımladığını gördünüz. Eğer aşağıdaki yaml dosyasında olduğu gibi bir PVC oluşturursanız bu default SC kullanılır.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mongodb-pvc2
spec:
  resources:
    requests:
      storage: 100Mi
  accessModes:
    - ReadWriteOnce

Fakat default StorageClass kullanmak yerine 2.başlıktaki gibi kendi oluşturduğunuz PersistenceVolume nesnelerinizin kullanılmasını istiyorsanız PVC manifest dosyasına storageClassName: "" parametresini ve değerini eklemeniz gerekiyor.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mongodb-pvc2
spec:
  storageClassName: ""
  resources:
    requests:
      storage: 100Mi
  accessModes:
    - ReadWriteOnce

Böylece artık dinamik PersistenceVolume oluşturmak yerine kendi oluşturduğunuz PersistenceVolume'ları tahsis edebilirsiniz.

6.3. Dinamik PersistentVolume Oluşturulmasına Genel Bakış

Tüm bu 6. başlık altında anlattığımız dinamik PV oluşturma sürecini özetlemek gerekirse, persistence depolama alanını bir Pod'a eklemenin en iyi yolu yalnızca PVC'yi (gerekirse açıkça belirtilen bir storageClassName ile) ve Pod'u (PVC adıyla oluşturulan) oluşturmaktır. Diğer her şey, dinamik PersistentVolume provider tarafından halledilir.