Kubernetes Volume, Pod içindeki container'ların verilerini saklamak için kullandığı depolama mekanizmasıdır. Volume, Pod'lar arasında veri paylaşımı, kalıcı depolama veya farklı kaynaklara erişim gibi farklı senaryolarda kullanılabilir.
Kubernetes Volume, Pod'ların bir bileşenidir ve bu nedenle, Container gibi, Pod manifest dosyasında tanımlanır. Standalone bir Kubernetes nesnesi değildirler ve kendi başlarına oluşturulamaz veya silinemezler. Bu nedenle
kubectl get volume gibi bir komutla görüntülenemezler.
Bir volume, bir Pod'a dahil edildiğinde, o Pod içindeki tüm Container'lar için kullanılabilir hale gelirler. Fakat Container'ların erişebilmesi için ilgili Volume'ları mount etmelri gerekir.
1. Volume'lara Neden Gerek Var?
Pod'ların, içlerinde çalışan processlerin CPU, RAM, network interface'leri ortak kullandığı logical hostlara benzer olduğunu söylemiştik. Bu processlerin aynı zamanda dosya sistemini de paylaşması beklenebilir, ancak dosya sistemi processler için ortak değildir. Bu nedenler ortak veya kalıcı dosya sistemleri oluşturmak için Volume'lara ihtiyacımız vardır.
Kubernetes Volume kullanarak, Pod içindeki container'ların verilerini saklamak, paylaşmak, taşımak ve korumak daha kolay ve güvenilir hale gelir. Bu nedenle, Kubernetes Volume kullanımı, Kubernetes platformunda önemli bir konudur.
Kubernetes Volume kullanmanın bazı temel nedenleri şunlardır:
- Verilerin korunması: Pod'lar birden fazla container'a sahip olabilir ve bu container'lar birbirleriyle etkileşimde bulunabilir. Ancak, bu container'lar arasında veri paylaşımı yapılmazsa, container'lar arasındaki bağlantı zayıflayabilir. Bu nedenle, pod'da paylaşılan bir Volume, container'lar arasındaki veri paylaşımını kolaylaştırır.
- Verilerin yedeklenmesi: Kubernetes Volume, verilerin yedeklenmesini kolaylaştırır. Bir Volume'da saklanan veriler, Pod'un farklı bir Node'a taşınması veya Pod'un kapatılması durumunda bile korunur.
- Verilerin taşınması: Kubernetes Volume, verilerin Pod'lar arasında taşınmasını kolaylaştırır. Bir Volume'da saklanan veriler, başka bir Pod'da kullanılabilir veya farklı bir Pod'a taşınabilir.
- Depolama kaynaklarının kullanımı: Kubernetes Volume, Pod'da birden fazla container'ın kullanabileceği ortak bir depolama kaynağı sağlar. Bu nedenle, aynı depolama kaynağına sahip birden fazla container için Volume kullanmak, depolama kaynaklarının daha verimli kullanılmasını sağlar.
2. Volume Kullanım Senaryosu
Volume konusunu rahat anlayabilmek için basit bir senaryo üzerinden nasıl kullanabileceğine birlikte bakalım.
Örneğin bir Pod içinde çalışan 3 adet Container olsun. Herbirini şu şekilde özetleyelim:
/var/htdocsaltındaki HTML dosyalarını çalıştırıp loglarını
/var/logsaltına koyan bir Webserver container
- Webserver container'ın çalıştıracağı HTML dosyalarını oluşturup
/var/htdocsdizinine koyacak bir ContentAgent container
/var/logsaltındaki log dosyalarını alarak rotate, analyze gibi işlemler gerçekleştiren bir LogRotator container
Eğer Volume kullanmazsanız, container'lar, diğer container'ların dosyalarının farkına varamazlar. Örneğin Webserver container'ın oluşturduğu logları LogRotator container'ı göremeyecek. Çünkü her container kendi disk alanındaki dizinlere bakıyor olacaktır.
Fakat eğer log ve HTML dosyaları için iki ayrı Volume oluşturur ve container'ların ilgili dizinlerine mount edersek, tüm container'lar aynı dosyalar üzerinde çalışmış olacak ve ortak bir disk alanı oluşturmuş oluruz.
3. Volume Tipleri
Kubernetes Volume, farklı depolama kaynaklarını kullanarak Pod'lar içinde veri saklamak için tasarlanmış bir mekanizmadır. Kubernetes Volume, birçok farklı tipi destekler ve her biri farklı bir kullanım senaryosuna sahiptir. İşte bazı yaygın Kubernetes Volume tipleri şunlardır:
emptyDir: Pod'da geçici ve boş bir depolama alanı sağlar. Pod'un yaşam döngüsü boyunca verileri saklayabilir. Ancak Pod silindiğinde veriler de silinir.
gitRepo: emptyDir olarak başlatılan bir volume, belirtilen bir Git reposuna clone ederek volume'un son halini oluşturur.
hostPath: Pod'un çalıştığı Node üzerinde bulunan dosya sistemine erişmek için kullanılır. Bu, yalnızca tek bir Node üzerinde çalışan Pod'lar için uygundur.
nfs: NFS erişimi sağlar. Pod'un farklı Node'lar arasında taşınması durumunda bile verilerin korunmasını sağlar.
gcePersistentDisk,
awsElasticBlockStore,
azureDiskve diğerleri: İlgili cloud providerlar üzerindeki storage çözümlerini Volume olarak kullanabilmenizi sağlar. Fakat hepsi deprecated olmuştur ve yerlerine
CSIveya plugin kullanmanız gerekir.
persistentVolumeClaim (PVC): Kubernetes Cluster'ındaki bir depolama alanı için bir talep oluşturur. Pod'un kapatılması veya başka bir Node'a taşınması durumunda bile verilerin korunmasını sağlar.
configMap: Pod'lar için yapılandırma verileri sağlar. Pod'ların çalışma zamanı yapılandırmasını ayarlamak için kullanılır.
secret: Pod'lar için hassas verileri sağlar. Örneğin, kullanıcı adları ve şifreler gibi verileri saklayabilir.
downwardAPI: Pod'da çalışan container'ların environment variabler'larını, CPU ve bellek limitlerini ve diğer verileri sağlar.
Bu, yalnızca yaygın kullanılan bazı Kubernetes Volume tiplerinin bir listesidir. Her biri farklı bir kullanım senaryosuna sahiptir ve Kubernetes platformunda depolama için farklı seçenekler sunar.
3.1. emptyDir Volume Tipi
emptyDir, Kubernetes Volume'lerinden biridir ve Pod'un yaşam döngüsü boyunca geçici bir depolama alanı sağlar. emptyDir, Pod'un Node'una bağlı bir diskte oluşturulur ve Pod kapatıldığında veya silindiğinde hem Volume hem de içindeki veriler silinir.
Bir emptyDir oluşturmak için, aşağıdaki gibi bir YAML dosyası örneğini kullanabilirsiniz:
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: my-container image: my-image volumeMounts: - name: my-volume mountPath: /data volumes: - name: my-volume emptyDir: {}
Manifest dosyası hazır olduktan sonra
kubectl create veya
kubectl apply komutlarından birisi ile pod'u oluşturabilirsiniz.
kubectl create -f pod-with-emptydir-volume.yaml
emptyDir, Pod'unuzu barındıran node'un üzerindeki fiziksel diskte oluşturulduğu için dosya okuma ve yazma performansı node'un bu fiziksel diskine bağlıdır. Ancak Kubernetes'e emptyDir'i bir
tmpfs dosya sisteminde (disk yerine bellekte) oluşturmasını söyleyebilirsiniz. Bunu yapmak için emptyDir ortamını şu şekilde
Memory olarak ayarlamalısınız:
volumes: - name: my-volume emptyDir: medium: Memory
Böylece dosya okuma yazma gözle görülür şekilde artacaktır. Fakat depolayacağınız dosyalar için RAM boyutuna dikkate almalısınız.
3.2. gitRepo Volume Tipi
gitRepo, public Git reposundan kaynak kodu otomatik olarak kopyalayan bir emptyDir volume tipidir. Private repolar için yapılandırma seçenekleri içermez.
Bir gitRepo oluşturmak için aşağıdaki gibi bir YAML dosyası örneği kullanabilirsiniz:
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: my-container image: my-image volumeMounts: - name: my-volume mountPath: /app volumes: - name: my-volume gitRepo: repository: https://github.com/my-repo/my-app.git revision: master directory: .
Manifest dosyası hazır olduktan sonra
kubectl create veya
kubectl apply komutlarından birisi ile pod'u oluşturabilirsiniz.
kubectl create -f pod-with-gitrepo-volume.yaml
Eğer
directory isimli parametreyi kullanmazsanız ilgili repo
/app dizini altında
my-app isimli alt dizine clone edilir.
3.3. hostPath Volume Tipi
hostPath, Kubernetes Volume'lerinden biridir ve Pod'un üzerinde çalıştığı node'un dosya veya dizinlere erişimini sağlar.
Eğer bir Pod üzerinde çalıştığı node'un dosya sistemini kullanırken sonlanır ve yeni oluşan node farklı bir node üzerinde çalışmaya başlarsa aynı dizini kullansa bile aynı dosyaları göremez. Bu nedenle hostPath volume kalıcı depolama çözümü olarak kullanılmamalıdır.
Bir hostPath oluşturmak için aşağıdaki gibi bir YAML dosyası örneği kullanabilirsiniz:
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: my-container image: my-image volumeMounts: - name: my-volume mountPath: /data volumes: - name: my-volume hostPath: path: /var/log
Manifest dosyası hazır olduktan sonra
kubectl create veya
kubectl apply komutlarından birisi ile pod'u oluşturabilirsiniz.
kubectl create -f pod-with-hostpath-volume.yaml
3.4. gcePersistentDisk, awsElasticBlockStore, azureDisk ve CloudProviderVolume Tipi
Birçok cloud provider, kalıcı depolama alanı sunabilmek için, kendi bünyelerinde bulunan disk çözümlerini Volume bileşeni olarak sunarlar. Cloud provider'lar üzerinden ilgili disk servislerini oluşturduktan sonra Pod'larınız ile Volume olarak kullanmaya başlayabilirsiniz.
Cloud provider Volume tiplerinden herhangi birini kullandığınızda, node'larınız çökse, Pod'larınız silinip yeniden oluşturulsa bile yeni Pod'lar mount ettikleri dizindeki eski verilere ulaşabilirler. Çünkü tüm dosyalar, bu providerların cloud üzerindeki depolama çözümleri içinde saklanır.
Örnek olarak Google Cloud Engine (GCE) üzerinde çalışan cluster'ımızda GCE persistent disk objesini Volume olarak kullanabileceğimiz bir database YAML örneğini görelim.
apiVersion: v1 kind: Pod metadata: name: mongodb spec: containers: - name: mongodb image: mongo volumeMounts: - name: mongodb-data mountPath: /data/db volumes: - name: mongodb-data gcePersistentDisk: pdName: my-disk fsType: ext4
kubectl create veya
kubectl apply komutlarından birisi ile pod'u oluşturabilirsiniz.
kubectl create -f pod-with-gcepersistentdisk-volume.yaml
Bu örnekte Pod'umuz tek bir container ve GCP üzerinde oluşturduğunuz GCE persistence disk'e depolama yapan bir volume içerir.
Aynı örneği AWS EBS kullanacak şekilde yapılandıracak olursakta tek yapacağımız şey volume tipini ve değerlerini değiştirmek olacaktır.
spec: volumes: - name: mongodb-data awsElasticBlockStore: volumeId: my-volume fsType: ext4
gcePersistentDisk,
awsElasticBlockStore,
azureDiskve daha birçok cloud provider Volume tipi deprecated edilmiştir. Bu tip cloud provider volume tiplerini kullanabilmek için Container Storage Interface (CSI) kullanmanız gerekir. Detaylar için ilgili Volume tipinin migration açıklamasına bakabilirsiniz: https://kubernetes.io/docs/concepts/storage/volumes
3.5. NFS Volume Tipi
Eğer Kuberntes cluster'ınız cloud providerlar yerine kendi sunucularınızda çalışıyorsa, Volume içine harici depolamayı mount etmek için desteklenen çok sayıda başka seçeneğiniz vardır. Örneğin, basit bir NFS paylaşımına bağlanmak için, aşağıdaki gösterildiği gibi yalnızca NFS sunucusunu ve sunucu tarafından dışa aktarılan pathi belirtmeniz gerekir.
volumes: - name: mongodb-data nfs: server: 184.108.40.206 path: /some/path
3.6. PersistentVolume ve PersistentVolumeClaim Volume Tipi
PersistentVolume ve PersistentVolumeClaim oldukça önemli ve detaylı bir içeriğe sahip olduğu için ayrı bir yazıda inceledik. İlgili yazıya aşağıdaki bağlantı ile gidebilirsiniz.
3.7. configMap ve Secret Volume Tipi
configMap ve Secret oldukça önemli ve detaylı bir içeriğe sahip olduğu için ayrı bir yazıda inceledik. İlgili yazıya aşağıdaki bağlantı ile gidebilirsiniz.
4. Volume Yaşam Döngüleri
Bir önceki altında birçok farklı Volume tipi gördük. Hangisini kullanacağınızı seçerken düşünmeniz gereken bir önemli konuda ilgili Volume tiplerinin life cycle'larıdır. Şimdi bu tiplerin herbirine hızlıca bakalım:
- İlk olarak emptyDir ile başlayalım. Pod sonlandırıldığında emptyDir volume'larda sonlandırılır ve içindeki veri silinir.
- hostPath tipindeki Volume'ler ise Pod'lar sonlandırıldığında etkilenmez. Fakat node hata verir ve çökerse hostPath volume'lerde erişelemez hale gelir.
- NFS, cloud provider disk sistemleri, PersistentVolume ve PersistentVolumeClaim Volume tipleri ise kendileri direkt olarak sonlandırılana kadar node ve pod nesnelerinin durumlarından bağımsız olarak kalıcı bir volume sistemi sunarlar.
Sıradaki yazı ile eğitim serisine devam edebilirsiniz.