Pengalaman kami dalam membangunkan pemacu CSI dalam Kubernetes untuk Yandex.Cloud

Pengalaman kami dalam membangunkan pemacu CSI dalam Kubernetes untuk Yandex.Cloud

Kami berbesar hati untuk mengumumkan bahawa Flant sedang mengembangkan sumbangannya kepada alatan Sumber Terbuka untuk Kubernetes dengan mengeluarkan versi alfa pemacu CSI (Antara Muka Penyimpanan Bekas) untuk Yandex.Cloud.

Tetapi sebelum beralih kepada butiran pelaksanaan, mari jawab soalan mengapa ini diperlukan sama sekali apabila Yandex sudah mempunyai perkhidmatan Perkhidmatan Terurus untuk Kubernetes.

Pengenalan

kenapa ni?

Dalam syarikat kami, sejak awal penggunaan Kubernetes dalam pengeluaran (iaitu selama beberapa tahun sekarang), kami telah membangunkan alat kami sendiri (deckhouse), yang, dengan cara itu, kami juga merancang untuk menyediakannya sebagai projek Sumber Terbuka tidak lama lagi. . Dengan bantuannya, kami mengkonfigurasi dan mengkonfigurasi semua kluster kami secara seragam, dan pada masa ini sudah terdapat lebih daripada 100 daripadanya, pada pelbagai jenis konfigurasi perkakasan dan dalam semua perkhidmatan awan yang tersedia.

Kluster yang menggunakan deckhouse mempunyai semua komponen yang diperlukan untuk operasi: pengimbang, pemantauan dengan carta yang mudah, metrik dan makluman, pengesahan pengguna melalui pembekal luaran untuk akses kepada semua papan pemuka dan sebagainya. Tidak ada gunanya memasang gugusan "dipam" sedemikian dalam penyelesaian terurus, kerana ini selalunya mustahil atau akan membawa kepada keperluan untuk melumpuhkan separuh daripada komponen.

NB: Ini adalah pengalaman kami, dan ia agak khusus. Kami sama sekali tidak mencadangkan agar semua orang menggunakan kluster Kubernetes sendiri dan bukannya menggunakan penyelesaian siap sedia. Ngomong-ngomong, kami tidak mempunyai pengalaman sebenar dalam mengendalikan Kubernetes dari Yandex dan kami tidak akan memberikan sebarang penilaian terhadap perkhidmatan ini dalam artikel ini.

Apa itu dan untuk siapa?

Jadi, kita telah bercakap tentang pendekatan moden untuk penyimpanan di Kubernetes: bagaimana CSI berfungsi? ΠΈ bagaimana masyarakat datang kepada pendekatan ini.

Pada masa ini, banyak penyedia perkhidmatan awan besar telah membangunkan pemacu untuk menggunakan cakera awan mereka sebagai Volume Berterusan dalam Kubernetes. Jika pembekal tidak mempunyai pemandu sedemikian, tetapi semua fungsi yang diperlukan disediakan melalui API, maka tiada apa yang menghalang anda daripada melaksanakan pemandu itu sendiri. Inilah yang berlaku dengan Yandex.Cloud.

Kami mengambil sebagai asas untuk pembangunan Pemacu CSI untuk awan DigitalOcean dan beberapa idea daripada pemacu untuk GCP, kerana interaksi dengan API awan ini (Google dan Yandex) mempunyai beberapa persamaan. Khususnya, API dan GCP, dan pada Yandex mengembalikan objek Operation untuk menjejak status operasi yang berjalan lama (contohnya, mencipta cakera baharu). Untuk berinteraksi dengan API Yandex.Cloud, gunakan Yandex.Cloud Go SDK.

Hasil kerja yang dilakukan diterbitkan di GitHub dan mungkin berguna bagi mereka yang, atas sebab tertentu, menggunakan pemasangan Kubernetes mereka sendiri pada mesin maya Yandex.Cloud (tetapi bukan kluster terurus siap sedia) dan ingin menggunakan (pesanan) cakera melalui CSI.

РСализация

Ciri-ciri utama

Pada masa ini pemandu menyokong fungsi berikut:

  • Memesan cakera dalam semua zon kluster mengikut topologi nod dalam kluster;
  • Mengeluarkan cakera yang dipesan sebelum ini;
  • Ubah saiz luar talian untuk cakera (Yandex.Cloud tidak menyokong meningkatkan cakera yang dipasang pada mesin maya). Untuk maklumat tentang cara pemandu perlu diubah suai untuk menjadikan saiz semula semudah mungkin, lihat di bawah.

Pada masa hadapan, kami merancang untuk melaksanakan sokongan untuk mencipta dan memadam gambar cakera.

Kesukaran utama dan cara mengatasinya

Kekurangan keupayaan untuk meningkatkan cakera dalam masa nyata dalam Yandex.Cloud API adalah had yang merumitkan operasi ubah saiz untuk PV (Volume Berterusan): dalam kes ini, pod aplikasi yang menggunakan cakera perlu dihentikan, dan ini boleh menyebabkan aplikasi masa henti.

Menurut Spesifikasi CSI, jika pengawal CSI melaporkan bahawa ia boleh mengubah saiz cakera hanya "luar talian" (VolumeExpansion.OFFLINE), maka proses meningkatkan cakera sepatutnya seperti ini:

Jika pemalam hanya mempunyai VolumeExpansion.OFFLINE keupayaan pengembangan dan volum pada masa ini diterbitkan atau tersedia pada nod kemudian ControllerExpandVolume MESTI dipanggil SAHAJA selepas sama ada:

  • Pemalam mempunyai pengawal PUBLISH_UNPUBLISH_VOLUME keupayaan dan ControllerUnpublishVolume telah berjaya dipanggil.

ATAU LAIN

  • Pemalam TIDAK mempunyai pengawal PUBLISH_UNPUBLISH_VOLUME keupayaan, pemalam mempunyai nod STAGE_UNSTAGE_VOLUME keupayaan, dan NodeUnstageVolume telah berjaya diselesaikan.

ATAU LAIN

  • Pemalam TIDAK mempunyai pengawal PUBLISH_UNPUBLISH_VOLUME keupayaan, mahupun nod STAGE_UNSTAGE_VOLUME keupayaan, dan NodeUnpublishVolume telah selesai dengan jayanya.

Ini pada asasnya bermakna anda perlu menanggalkan cakera daripada mesin maya sebelum mengembangkannya.

Namun, malangnya pelaksanaan Spesifikasi CSI melalui sidecars tidak memenuhi keperluan ini:

  • Dalam bekas kereta sampingan csi-attacher, yang sepatutnya bertanggungjawab untuk kehadiran jurang yang diperlukan antara pelekap, fungsi ini tidak dilaksanakan dalam saiz semula luar talian. Perbincangan mengenai perkara ini telah dimulakan di sini.
  • Apakah sebenarnya bekas kereta sampingan dalam konteks ini? Pemalam CSI itu sendiri tidak berinteraksi dengan API Kubernetes, tetapi hanya membalas panggilan gRPC yang dihantar kepadanya oleh bekas kereta sampingan. Terkini sedang dibangunkan oleh komuniti Kubernetes.

Dalam kes kami (pemalam CSI), operasi meningkatkan cakera kelihatan seperti ini:

  1. Kami menerima panggilan gRPC ControllerExpandVolume;
  2. Kami cuba meningkatkan cakera dalam API, tetapi kami menerima ralat tentang kemustahilan melaksanakan operasi kerana cakera dipasang;
  3. Kami menyimpan pengecam cakera dalam peta, yang mengandungi cakera yang operasi peningkatan perlu dilakukan. Di bawah, untuk ringkasnya, kami akan memanggil peta ini sebagai volumeResizeRequired;
  4. Keluarkan pod yang menggunakan cakera secara manual. Kubernetes akan memulakannya semula. Supaya cakera tidak mempunyai masa untuk melekap (ControllerPublishVolume) sebelum melengkapkan operasi peningkatan apabila cuba melekap, kami menyemak sama ada cakera yang diberikan masih ada volumeResizeRequired dan mengembalikan ralat;
  5. Pemacu CSI cuba melaksanakan semula operasi ubah saiz. Jika operasi berjaya, kemudian keluarkan cakera daripada volumeResizeRequired;
  6. Kerana ID cakera tiada dari volumeResizeRequired, ControllerPublishVolume lulus dengan jayanya, cakera dipasang, pod bermula.

Segala-galanya kelihatan cukup mudah, tetapi seperti biasa terdapat perangkap. Membesarkan cakera luaran-resizer, yang sekiranya berlaku ralat semasa operasi menggunakan baris gilir dengan peningkatan eksponen dalam masa tamat sehingga 1000 saat:

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)},
  )
}

Ini secara berkala boleh mengakibatkan operasi pengembangan cakera dilanjutkan selama 15+ minit dan, dengan itu, pod yang sepadan tidak tersedia.

Satu-satunya pilihan yang agak mudah dan tanpa rasa sakit membolehkan kami mengurangkan potensi masa henti adalah penggunaan versi luaran-resizer kami dengan had tamat masa maksimum dalam 5 saat:

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

Kami tidak menganggap perlu untuk segera memulakan perbincangan dan menampal penyubah luaran, kerana saiz semula cakera luar talian adalah lontaran yang tidak lama lagi akan hilang daripada semua penyedia awan.

Bagaimana untuk mula menggunakan?

Pemacu disokong pada Kubernetes versi 1.15 dan lebih tinggi. Untuk pemandu bekerja, keperluan berikut mesti dipenuhi:

  • Π€Π»Π°Π³ --allow-privileged ditetapkan kepada nilai true untuk pelayan API dan kubelet;
  • Termasuk --feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=true untuk pelayan API dan kubelet;
  • Pembiakan gunung (penyebaran gunung) mesti didayakan pada kluster. Apabila menggunakan Docker, daemon mesti dikonfigurasikan untuk membenarkan pemasangan dikongsi.

Semua langkah yang diperlukan untuk pemasangan itu sendiri diterangkan dalam README. Pemasangan melibatkan mencipta objek dalam Kubernetes daripada manifes.

Untuk pemandu bekerja, anda memerlukan yang berikut:

  • Tentukan pengecam direktori dalam manifes (folder-id) Yandex.Cloud (lihat dokumentasi);
  • Untuk berinteraksi dengan API Yandex.Cloud, pemacu CSI menggunakan akaun perkhidmatan. Dalam manifes, Rahsia mesti diluluskan kunci yang dibenarkan daripada akaun perkhidmatan. Dalam dokumentasi diterangkan, cara membuat akaun perkhidmatan dan mendapatkan kunci.

Semuanya - cuba, dan kami akan gembira menerima maklum balas dan isu barujika anda menghadapi sebarang masalah!

Sokongan lanjut

Akibatnya, kami ingin ambil perhatian bahawa kami melaksanakan pemacu CSI ini bukan kerana keinginan besar untuk berseronok menulis aplikasi dalam Go, tetapi kerana keperluan mendesak dalam syarikat. Nampaknya tidak praktikal bagi kami untuk mengekalkan pelaksanaan kami sendiri, jadi jika Yandex menunjukkan minat dan memutuskan untuk terus menyokong pemandu, kami dengan senang hati akan memindahkan repositori kepada mereka.

Di samping itu, Yandex mungkin mempunyai pelaksanaan sendiri pemacu CSI dalam kelompok Kubernetes terurusnya, yang boleh dikeluarkan dalam Sumber Terbuka. Kami juga melihat pilihan pembangunan ini sebagai baik - komuniti akan dapat menggunakan pemandu yang terbukti daripada pembekal perkhidmatan, dan bukan daripada syarikat pihak ketiga.

PS

Baca juga di blog kami:

Sumber: www.habr.com

Tambah komen