Yandex.Cloud için Kubernetes'te bir CSI sürücüsü geliştirme deneyimimiz

Yandex.Cloud için Kubernetes'te bir CSI sürücüsü geliştirme deneyimimiz

Flant'ın Kubernetes için Açık Kaynak araçlarına olan katkısını şu sürümlerle genişlettiğini duyurmaktan mutluluk duyuyoruz: CSI sürücüsünün alfa sürümü Yandex.Cloud için (Konteyner Depolama Arayüzü).

Ancak uygulama ayrıntılarına geçmeden önce, Yandex'in zaten bir hizmeti varken buna neden ihtiyaç duyulduğu sorusunu cevaplayalım. Kubernetes için Yönetilen Hizmet.

Giriş

Neden ki?

Şirketimiz bünyesinde, Kubernetes'i üretimde kullanmaya başladığımızdan bu yana (yani birkaç yıldır), kendi aracımızı (deckhouse) geliştiriyoruz; bu arada, onu da yakında Açık Kaynak projesi olarak kullanıma sunmayı planlıyoruz. . Onun yardımıyla, tüm kümelerimizi aynı şekilde yapılandırıyor ve yapılandırıyoruz ve şu anda çok çeşitli donanım yapılandırmalarında ve mevcut tüm bulut hizmetlerinde 100'den fazla küme var.

Güverte evini kullanan kümeler operasyon için gerekli tüm bileşenlere sahiptir: dengeleyiciler, kullanışlı grafikler, ölçümler ve uyarılarla izleme, tüm kontrol panellerine erişim için harici sağlayıcılar aracılığıyla kullanıcı kimlik doğrulaması vb. Yönetilen bir çözüme böylesine "yükseltilmiş" bir küme kurmanın hiçbir anlamı yoktur, çünkü bu genellikle ya imkansızdır ya da bileşenlerin yarısının devre dışı bırakılması ihtiyacına yol açacaktır.

NB: Bu bizim deneyimimiz ve oldukça spesifik. Hiçbir şekilde herkesin hazır çözümler kullanmak yerine Kubernetes kümelerini kendi başına kurmasını önermiyoruz. Bu arada, Kubernetes'i Yandex'den çalıştırma konusunda gerçek bir tecrübemiz yok ve bu yazıda bu hizmete ilişkin herhangi bir değerlendirme yapmayacağız.

Nedir ve kimin için?

Kubernetes'te depolamaya yönelik modern yaklaşımdan zaten bahsetmiştik: CSI nasıl çalışır? и topluluk nasıl geldi bu yaklaşıma.

Şu anda birçok büyük bulut hizmeti sağlayıcısı, bulut disklerini Kubernetes'te Kalıcı Birim olarak kullanmak için sürücüler geliştirmiştir. Tedarikçinin böyle bir sürücüsü yoksa ancak gerekli tüm işlevler API aracılığıyla sağlanıyorsa, hiçbir şey sürücüyü kendiniz uygulamanızı engellemez. Yandex.Cloud'da olan da buydu.

Gelişimi temel aldık DigitalOcean bulutu için CSI sürücüsü ve birkaç fikir GCP için sürücüler, çünkü bu bulutların (Google ve Yandex) API'si ile etkileşimin bir takım benzerlikleri vardır. Özellikle API ve GSOve Yandex bir nesneyi döndürmek Operation uzun süren işlemlerin durumunu izlemek için (örneğin, yeni bir disk oluşturma). Yandex.Cloud API ile etkileşim kurmak için şunu kullanın: Yandex.Cloud Go SDK'sı.

Yapılan işin sonucu GitHub'da yayınlandı ve herhangi bir nedenle Yandex.Cloud sanal makinelerinde kendi Kubernetes kurulumlarını kullanan (ancak hazır yönetilen bir küme olmayan) ve diskleri CSI aracılığıyla kullanmak (sipariş etmek) isteyenler için yararlı olabilir.

uygulama

Ana özellikleri

Şu anda sürücü aşağıdaki işlevleri desteklemektedir:

  • Kümenin tüm bölgelerindeki disklerin kümedeki düğümlerin topolojisine göre sıralanması;
  • Daha önce sipariş edilen disklerin çıkarılması;
  • Diskler için çevrimdışı yeniden boyutlandırma (Yandex.Cloud) desteklemiyor sanal makineye bağlanan disklerin sayısını artırmak). Yeniden boyutlandırmayı olabildiğince sorunsuz hale getirmek için sürücünün nasıl değiştirilmesi gerektiği hakkında bilgi için aşağıya bakın.

Gelecekte disk anlık görüntüleri oluşturmaya ve silmeye yönelik desteği uygulamayı planlıyoruz.

Ana zorluk ve bunun üstesinden nasıl gelineceği

Yandex.Cloud API'de diskleri gerçek zamanlı olarak artırma yeteneğinin olmaması, PV (Kalıcı Birim) için yeniden boyutlandırma işlemini zorlaştıran bir sınırlamadır: bu durumda, diski kullanan uygulama bölmesinin durdurulması gerekir; ve bu durum kesinti uygulamalarına neden olabilir.

Göre CSI spesifikasyonları, CSI denetleyicisi diskleri yalnızca "çevrimdışı" olarak yeniden boyutlandırabileceğini bildirirse (VolumeExpansion.OFFLINE), o zaman diski artırma işlemi şu şekilde ilerlemelidir:

Eklenti yalnızca varsa VolumeExpansion.OFFLINE genişletme yeteneği ve birimin şu anda bir düğümde yayınlanmış veya mevcut olması durumunda ControllerExpandVolume YALNIZCA aşağıdakilerden birinin ardından çağrılmalıdır:

  • Eklentinin denetleyicisi var PUBLISH_UNPUBLISH_VOLUME yetenek ve ControllerUnpublishVolume başarıyla çağrıldı.

VEYA BAŞKA

  • Eklentinin denetleyicisi YOK PUBLISH_UNPUBLISH_VOLUME yeteneği, eklentinin düğümü var STAGE_UNSTAGE_VOLUME yeteneği ve NodeUnstageVolume başarıyla tamamlandı.

VEYA BAŞKA

  • Eklentinin denetleyicisi YOK PUBLISH_UNPUBLISH_VOLUME yetenek veya düğüm STAGE_UNSTAGE_VOLUME yeteneği ve NodeUnpublishVolume başarıyla tamamlandı.

Bu aslında diski genişletmeden önce sanal makineden ayırmanız gerektiği anlamına gelir.

Ancak ne yazık ki uygulama Sepetler yoluyla CSI spesifikasyonu şu gereksinimleri karşılamıyor:

  • Bir sepet konteynerinde csi-attacherMontajlar arasında gerekli boşluğun varlığından sorumlu olması gereken bu işlevsellik, çevrimdışı yeniden boyutlandırmada uygulanmaz. Bu konuyla ilgili tartışma başlatıldı burada.
  • Bu bağlamda sepet konteyneri tam olarak nedir? CSI eklentisinin kendisi Kubernetes API ile etkileşime girmez, yalnızca sepet konteynerleri tarafından kendisine gönderilen gRPC çağrılarına yanıt verir. En sonuncu geliştiriliyor Kubernetes topluluğu tarafından.

Bizim durumumuzda (CSI eklentisi), diski artırma işlemi şöyle görünür:

  1. Bir gRPC çağrısı alıyoruz ControllerExpandVolume;
  2. API'de diski artırmaya çalışıyoruz ancak disk takılı olduğundan işlemin gerçekleştirilemeyeceğine dair bir hata alıyoruz;
  3. Arttırma işleminin yapılması gereken diskleri içeren disk tanımlayıcısını haritada saklıyoruz. Aşağıda kısaca bu haritayı şu şekilde adlandıracağız: volumeResizeRequired;
  4. Diski kullanan bölmeyi manuel olarak çıkarın. Kubernetes onu yeniden başlatacak. Böylece diskin montaj için zamanı kalmaz (ControllerPublishVolume) takmaya çalışırken artırma işlemini tamamlamadan önce, verilen diskin hala takılı olup olmadığını kontrol ederiz. volumeResizeRequired ve bir hata döndürün;
  5. CSI sürücüsü yeniden boyutlandırma işlemini yeniden yürütmeyi dener. İşlem başarılıysa diski çıkarın. volumeResizeRequired;
  6. Çünkü Disk kimliği eksik volumeResizeRequired, ControllerPublishVolume başarıyla geçer, disk takılır, bölme başlatılır.

Her şey yeterince basit görünüyor, ancak her zaman olduğu gibi tuzaklar var. Diskleri büyütür harici yeniden boyutlandırıcıişlem sırasında bir hata olması durumunda kuyruk kullanır Zaman aşımı süresinde 1000 saniyeye kadar üstel bir artışla:

func DefaultControllerRateLimiter() RateLimiter {
  return NewMaxOfRateLimiter(
  NewItemExponentialFailureRateLimiter(5*time.Millisecond, 1000*time.Second),
  // 10 qps, 100 bucket size.  This is only for retry speed and its only the overall factor (not per item)
  &BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(10), 100)},
  )
}

Bu, periyodik olarak disk genişletme işleminin 15 dakikadan fazla uzatılmasına ve dolayısıyla ilgili bölmenin kullanılamamasına neden olabilir.

Potansiyel kesinti sürelerini oldukça kolay ve sorunsuz bir şekilde azaltmamıza olanak tanıyan tek seçenek, maksimum zaman aşımı sınırına sahip harici yeniden boyutlandırıcı sürümümüzün kullanılmasıydı. 5 saniye içinde:

workqueue.NewItemExponentialFailureRateLimiter(5*time.Millisecond, 5*time.Second)

Acilen bir tartışma başlatmanın ve harici yeniden boyutlandırıcıya yama yapmanın gerekli olduğunu düşünmedik, çünkü disklerin çevrimdışı yeniden boyutlandırılması, yakında tüm bulut sağlayıcılarından kaybolacak bir gerilemedir.

Kullanmaya nasıl başlanır?

Sürücü, Kubernetes sürüm 1.15 ve üzeri sürümlerde desteklenir. Sürücünün çalışması için aşağıdaki gereksinimlerin karşılanması gerekir:

  • Bayrak --allow-privileged değere ayarla true API sunucusu ve kubelet için;
  • Dahil --feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=true API sunucusu ve kubelet için;
  • Dağın yayılması (montaj yayılımı) kümede etkinleştirilmelidir. Docker kullanılırken arka plan programının paylaşılan montajlara izin verecek şekilde yapılandırılması gerekir.

Kurulumun kendisi için gerekli tüm adımlar README'de anlatıldı. Kurulum, Kubernetes'te manifestlerden nesneler oluşturmayı içerir.

Sürücünün çalışması için aşağıdakilere ihtiyacınız olacak:

  • Bildiride dizin tanımlayıcısını belirtin (folder-id) Yandex.Bulut (belgelere bakın);
  • CSI sürücüsü, Yandex.Cloud API ile etkileşim kurmak için bir hizmet hesabı kullanır. Manifestte Secret'in iletilmesi gerekiyor yetkili anahtarlar hizmet hesabından. Belgelerde tarif, bir hizmet hesabının nasıl oluşturulacağı ve anahtarların nasıl alınacağı.

Her şeyi hesaba katarak - Denemekgeri bildirim almaktan mutluluk duyacağız ve yeni sorunlarherhangi bir sorunla karşılaşırsanız!

Daha fazla destek

Sonuç olarak, bu CSI sürücüsünü Go'da uygulama yazarken eğlenme arzusundan değil, şirket içindeki acil bir ihtiyaçtan dolayı uyguladığımızı belirtmek isteriz. Kendi uygulamamızı sürdürmek bizim için pratik görünmüyor, bu nedenle Yandex ilgi gösterirse ve sürücüyü desteklemeye devam etmeye karar verirse, depoyu onlara aktarmaktan memnuniyet duyarız.

Ek olarak, Yandex'in muhtemelen yönetilen Kubernetes kümesinde Açık Kaynak olarak yayınlanabilecek kendi CSI sürücüsü uygulaması vardır. Bu geliştirme seçeneğini de olumlu olarak görüyoruz - topluluk, üçüncü taraf bir şirketten değil, bir hizmet sağlayıcıdan kanıtlanmış bir sürücüyü kullanabilecek.

PS

Blogumuzda da okuyun:

Kaynak: habr.com

Yorum ekle