Kubernetes Storage

Selçuk Şan
Turk Telekom Bulut Teknolojileri
6 min readFeb 25, 2024

Kubernetes başlangıçta stateless iş yükleri için tasarlanmış olsa da stateful servislerin çalıştırılması giderek daha yaygın hale gelmiş durumda.

Kubernetes’in, bu iş yüklerini desteklemek için ephemeral (geçici) seçeneklerin ötesinde depolama özellikleri sağlaması gerekiyor. Yani, bir uygulamanın çökmesi veya bir iş yükünün farklı bir hostta yeniden ayağa kalkması gibi çeşitli olaylar karşısında daha fazla esneklik ve kullanılabilirlik sağlayabilmesi gerekmekte.

Bu yazıda platformumuzun uygulamalara nasıl depolama hizmetleri sunabileceğini konuşacağız. İlk olarak uygulama kalıcılığı ve storage system beklentileri ile ilgili temel endişeleri ele alarak başlayacak; Kubernetes’te mevcut olan depolama temellerini konuşacağız. Daha gelişmiş depolama ihtiyaçlarına girdiğimizde ise çeşitli storage providerlarla entegrasyonumuzu sağlayan Container Storage Interface (CSI) kavramına bakacağız.

Depolama başlı başına geniş bir konu. Bu yazıda amacım, iş yüklerine sunabileceğiniz depolama alanları hakkında bilinçli kararlar vermenize yardımcı olmaya çalışmak. Bu kavramları altyapı/depolama ekipleriyle birlikte gözden geçirmek çok daha sağlıklı olacaktır. Kubernetes birçok derde deva olsa da depolama uzmanlığı ihtiyacını ortadan kaldırmıyor maalesef…

Depolama Temelleri

Kubernetes depolama modellerine ve seçeneklerine geçmeden önce potansiyel depolama ihtiyaçlarıyla ilgili bazı temel hususları analiz etmeliyiz. Altyapı ve uygulama düzeyinde, aşağıdaki gereksinimler üzerinde düşünmek değerli olacaktır.

  • Access mode
  • Volume expansion
  • Dynamic provisioning
  • Block, file, object storage
  • Ephemeral Volume
  • Storage Provider

Access Modes

Uygulamalar için desteklenebilecek üç erişim modu bulunuyor:

  • ReadWriteOnce (RWO): Tek bir Pod volume’ü okuyabilir ve yazabilir.
  • ReadOnlyMany (ROX): Birden fazla Pod volume’ü okuyabilir.
  • ReadWriteMany (RWX): Birden fazla Pod volume’ü okuyabilir ve yazabilir.

Cloud Native Uygulamalar için RWO en yaygın modeldir diyebiliriz. Amazon Elastic Block Storage (EBS) veya Azure Disk Storage gibi yaygın providerlardan yararlanırken, disk yalnızca bir node’a bağlı olabileceğinden RWO ile sınırlı kalınır. Bu sınırlama bir sıkıntı gibi görünse de, çoğu Cloud Native uygulama, volume’ün yalnızca kendilerine ait olduğu ve yüksek performanslı Read/Write sunduğu bu tür bir depolama ile en iyi şekilde çalışır.

Çoğu zaman, RWX gereksinimi olan eski uygulamalarla karşılaşıyoruz. Bu uygulamalar genellikle bir Network File System (NFS) erişim ihtiyacı varsayılarak tasarlanmıştır. NFS, bir ağ üzerinden dosya paylaşımı için kullanılan bir protokol. Bu protokol ile bir sunucu üzerinde bulunan dosyalar, ağdaki diğer bilgisayarlar tarafından sanki yerel bir diskteymiş gibi erişilebilir olabiliyor.

Servislerin statelerini paylaşması gerektiğinde, genellikle Network File System üzerinden veri paylaşmaktan daha modern çözümler bulunuyor; Message Queueların veya databaselerin kullanılması gibi. Ayrıca, bir uygulama veri paylaşmak isterse, file system’a erişim vermek yerine bunu bir API üzerinden expose etmek genellikle en iyisidir diyebiliriz. Bu da RWX için birçok use case’i zaman zaman sorgulanabilir hale getiriyor.

File System doğru tasarım tercihi olmadığı sürece, platform ekipleri RWX uyumlu depolama alanı sunma ya da geliştiricilerden uygulamaları yeniden tasarlamalarını talep etme gibi zor bir seçimle karşı karşıya kalabiliyor🤦‍♂️

ROX ya da RWX desteğinin gerekli olduğuna karar verilmesi halinde, Amazon Elastic File System (EFS), Azure File Share gibi çeşitli managed servisler veya Ceph ve Portworx gibi entegre edilebilecek on-premise storage çözümleri bulunuyor.

Volume Expansion

Zamanla bir uygulama kendi volume’ünü doldurmaya başlayabilir. Volume’ün daha büyük bir Volume ile değiştirilmesi data migration işlemi gerektireceğinden bu durum zorluk yaratacaktır. Buna bir çözüm, volume genişletmedir. Bu özellik Kubernetes kullanıcılarının PersistentVolumeClaim objelerini basitçe düzenlemelerine ve PVC Spec’te yeni boyut belirtmelerine olanak tanır. Kubernetes storage, backend’ini kullanarak volume’ü otomatik olarak genişletir. Elbette bu özellik, storage backend’i seçimimize de bağlıdır. Her storage backendi bunu desteklemiyor olabilir.

Volume Provisioning

Kuberneteste Volume sağlarken kullanabileceğimiz iki provision modeli vardır: Dynamic ve Static provisioning.

Static provisioning, Kubernetes’in kullanması için nodelar’da volumeların manuel olarak oluşturulduğunu varsayar. Dynamic provisioning ise, bir driver’ın cluster içinde çalıştığı ve bir storage provider ile konuşarak iş yüklerinin depolama isteklerini karşılayabildiği durumdur. Bu iki yöntemden mümkün olduğunda Dynamic provisioning tercih edilir. Genellikle ikisi arasındaki seçim, temel depolama sisteminin Kubernetes için uyumlu bir driver’a sahip olup olmadığına bağlıdır.

Block Device, File ve Object Storage

Uygulamalarımızın beklediği depolama türleri, uygun depolama ve Kubernetes entegrasyonunun seçilmesinde kilit öneme sahiptir. Uygulamalar tarafından kullanılan en yaygın depolama türü file storage’tır. File storage, üzerinde file system bulunan bir block device’tır aslında. Bu, herhangi bir işletim sisteminde aşina olduğumuz şekilde, uygulamaların dosyalara yazmasını sağlar.

Bir file system’in altında bir block device bulunur. Üstüne bir file system kurmak yerine, block device’ı uygulamaların doğrudan iletişim kurabileceği şekilde sunabiliriz. File system doğası gereği veri yazmaya ek yük getirir ama modern yazılım geliştirmede, bu ek yük hakkında endişe duymak oldukça nadirdir. Tabii, use case block device ile doğrudan etkileşim gerektiriyorsa, bu yalnızca bazı storage sistemlerinin destekleyebileceği bir şeydir.

Son depolama türü ise Object Storage. Nesne depolama, geleneksel hiyerarşinin olmaması bakımından file systemdan ayrılır. Nesne depolama, geliştiricilerin yapılandırılmamış verileri almasına, benzersiz bir identifier vermesine, etrafına bazı metadatalar eklemesine ve depolamasına olanak tanır. Ceph Rados Gateway, Amazon S3, Red Hat Multi Cloud Gateway (Noobaa) gibi Object Storage çözümleri, image, binary file ve daha fazlasını barındırmak için popüler araçlar haline gelmiştir. Bu popülerlik, web API’si ve Access Control Policyleri sayesinde de oldukça hızlanmıştır.

Ephemeral Volumes

Kubernetes’te en temel depolama türü, Ephemeral olarak da bilinen kalıcı olmayan depolamadır. Her container’in varsayılan olarak geçici depolama alanı vardır; bu depolama, Kubernetes pod’unun bulunduğu host’taki geçici bir dizini kullanır. Taşınabilirdir ancak durable (dayanıklı) değildir.

Storage Provider

Kullanılabilecek storage providerlarının sayısı çok fazla. Ceph veya Portworx gibi kendimizin yönetebileceği depolama çözümlerinden Google veya AWS gibi fully managed servisler providerlarına kadar birçok opsiyon mevcut. Burada, bu depolama sistemlerinin kapasitelerini anlamak ve hangilerinin Kubernetes ile kolayca entegre edilebileceğini bilmek çok değerli olacaktır. Bu, bir çözümün diğerine göre uygulama gereksinimlerinizi ne kadar iyi karşılayabileceğine dair bir perspektif sunacaktır.

Kubernetes Storage Kavramları

Persistent Volume — Persistent Volume Claim

Kubernetes’te depolamanın temelinde Volumeler ve Claimler yer alır.

Persistent Volume (PV), bir cluster admin tarafından statik olarak veya storage class kullanılarak dinamik olarak sağlanan bir depolama alanını temsil eder. Bu alan bir disk, bir cloud storage volume’ü veya başka bir depolama türü olabilir.

Persistent Volume Claim (PVC) ise bir kullanıcı tarafından depolama için yapılan bir taleptir. Bir Pod’a benzer. Pod’lar node kaynaklarını, PVC’ler ise PV kaynaklarını tüketir. Cluster adminlerinin, kullanıcıları bu volumelerin nasıl uygulandığına ilişkin ayrıntılara maruz bırakmadan, boyut ve access modlarından daha fazla şekilde farklılık gösteren çeşitli PersistentVolumelar sunabilmesi gerekir. Bu ihtiyaçlar için StorageClass resource’u bulunmaktadır.

Storage Class

Bir StorageClass bir depolama türünü temsil eder. Örneğin, bir StorageClass hızlı SSD depolamayı temsil ederken, diğeri manyetik sürücüleri veya uzak bulut depolamayı temsil edebilir. Bu, Kubernetes clusterlarının iş yükü gereksinimlerine göre çeşitli depolama türlerini sağlamasına olanak tanır.

Kubernetes dinamik volume provisioningi destekleyerek talep üzerine depolama birimleri oluşturmanıza olanak tanır. Bu nedenle, yöneticilerin manuel olarak yeni depolama birimleri oluşturması ve ardından clusterda kullanılmak üzere bir PersistentVolume objesi oluşturması gerekmez. Kullanıcı belirli bir depolama türü talep ettiğinde, tüm süreç otomatik olarak çalışır.

Cluster admin gerektiğinde storage class objelerini tanımlar. Her Storage Class, provisioner olarak da adlandırılan bir volume plugin’e başvurur. Kullanıcı bir PVC oluşturduğunda, provisioner gerekli depolama kriterlerine göre otomatik olarak bir volume hazırlar.

Container Storage Interface (CSI)

CSI, depolama sistemleri ile Kubernetes arasında bağlantı sağlayan bir standart sağlar ve Kubernetes depolama yönetiminin temelidir. Third-party storage providerları, Kubernetes’in core kodunu düzenlemek zorunda kalmadan Kubernetes’in yeni depolama sistemleriyle çalışmasını sağlamak için plugin oluşturmak ve bunları deploy için CSI standardını kullanabilir.

CSI, Kubernetes’in içinde Ceph, GlusterFS ve NFS gibi farklı depolama driverlarını entegre etme yeteneği sağlar.

CSI driver listesi için:
https://kubernetes-csi.github.io/docs/drivers.html

Sonuç olarak

PV, PVC, Storage Class ve CSI gibi temel kavramları ve Ephemeral Volume, Volume Expansion, Dynamic Provisioning, Block Device, File ve Object Storage gibi depolama seçeneklerini inceledik.

Kubernetes Storage karmaşık ve çok yönlü bir konudur. Bu yazıda anlattığım bilgiler, Kubernetes’te depolama ile ilgili temel bir anlayış sunmakta. Daha ayrıntılı bilgi için, Kubernetes’in ve storage providerların dokümanlarına göz atmak faydalı olacaktır.

Kaynak

--

--