Kubernetes PersistentVolume, PersistentVolumeClaim ve StorageClass Nedir?
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.
İ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
veyaReadOnlyMany
gibi, PersistentVolume ile kullanılacak Pod'ların "access mode" ayarını belirtir.persistentVolumeReclaimPolicy
: PersistentVolume silindiğinde,Retain
(yani verilerin korunması için) veyaDelete
(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.
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.
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
veyaReadOnlyMany
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.
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.
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
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.
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.
Sıradaki yazı ile eğitim serisine devam edebilirsiniz.