Pengalaman kami dalam mengembangkan driver CSI di Kubernetes untuk Yandex.Cloud



Kami dengan senang hati mengumumkan bahwa perusahaan Flant sedang mengisi kembali kontribusinya pada alat Open Source untuk Kubernetes dengan merilis versi alpha dari driver CSI (Container Storage Interface) untuk Yandex.Cloud.

Tapi sebelum beralih ke detail implementasi, kami akan menjawab pertanyaan mengapa ini diperlukan sama sekali ketika Yandex sudah memiliki Layanan Terkelola untuk layanan Kubernetes .

pengantar


Kenapa ini?


Di dalam perusahaan kami, sejak awal pengoperasian Kubernetes dalam produksi (mis. Selama beberapa tahun), alat kami sendiri (deckhouse) telah berkembang, yang, omong-omong, kami juga berencana untuk segera menyediakannya sebagai proyek Open Source. Dengan bantuannya, kami secara seragam mengonfigurasi dan mengonfigurasi semua cluster kami, dan saat ini ada lebih dari 100 dari mereka, apalagi, pada konfigurasi besi yang paling beragam dan di semua layanan cloud yang tersedia.

Cluster di mana deckhouse digunakan memiliki semua komponen yang diperlukan untuk pekerjaan: penyeimbang, pemantauan dengan bagan yang nyaman, metrik dan peringatan, otentikasi pengguna melalui penyedia eksternal untuk mengakses semua dasbor, dan sebagainya. Tidak masuk akal untuk menempatkan kluster "dipompa" ke dalam solusi yang dikelola, karena seringkali tidak mungkin atau akan mengarah pada kebutuhan untuk menonaktifkan setengah dari komponen.

NB : Ini adalah pengalaman kami, dan ini cukup spesifik. Kami sama sekali tidak mengklaim bahwa setiap orang harus secara independen terlibat dalam penyebaran cluster Kubernetes alih-alih menggunakan solusi yang sudah jadi. Omong-omong, kami tidak memiliki pengalaman nyata dalam mengoperasikan Kubernetes dari Yandex dan kami tidak akan memberikan penilaian atas layanan ini dalam artikel ini.

Apa itu dan untuk siapa?


Jadi, kita sudah membicarakan tentang pendekatan modern terhadap penyimpanan di Kubernetes: bagaimana CSI bekerja dan bagaimana masyarakat sampai pada pendekatan ini.

Saat ini, banyak penyedia layanan cloud besar telah mengembangkan driver untuk menggunakan drive cloud mereka sebagai Volume Persisten di Kubernetes. Jika pemasok tidak memiliki driver seperti itu, tetapi pada saat yang sama semua fungsi yang diperlukan disediakan melalui API, maka tidak ada yang mencegah pengemudi dari mengimplementasikan sumber dayanya sendiri. Dan begitulah yang terjadi dengan Yandex.Cloud.

Sebagai dasar untuk pengembangan, kami mengambil driver CSI untuk cloud DigitalOcean dan beberapa ide dari driver untuk GCP , karena interaksi dengan API cloud ini (Google dan Yandex) memiliki sejumlah kesamaan. Secara khusus, API danGCP , dan Yandex mengembalikan objek Operationuntuk melacak status operasi yang panjang (misalnya, membuat disk baru). Untuk berinteraksi dengan Yandex.Cloud API, SDK Yandex.Cloud Go digunakan .

Hasil dari pekerjaan yang dilakukan dipublikasikan pada GitHub dan mungkin bermanfaat bagi mereka yang karena alasan tertentu menggunakan instalasi Kubernet mereka sendiri di Yandex. Mesin virtual Cloud (tetapi bukan cluster terkelola yang siap pakai) dan ingin menggunakan disk (pesanan) melalui CSI.

Penerapan


Fitur utama


Saat ini, driver mendukung fungsi-fungsi berikut:

  • Memesan disk di semua zona cluster sesuai dengan topologi node di cluster
  • Menghapus disk yang dipesan sebelumnya;
  • Ubah ukuran offline untuk disk (Yandex. Cloud tidak mendukung peningkatan dalam disk yang dipasang pada mesin virtual). Tentang cara memodifikasi driver untuk mengubah ukuran tanpa rasa sakit mungkin, lihat di bawah.

Di masa depan, direncanakan untuk mengimplementasikan dukungan untuk pembuatan dan penghapusan snapshot disk.

Kesulitan utama dan penanggulangannya


Kurangnya kemampuan untuk memperluas disk secara real time di Yandex.Cloud API adalah batasan yang mempersulit operasi mengubah ukuran untuk PV (Persistent Volume): dalam hal ini, perlu bahwa pod aplikasi yang menggunakan disk dihentikan, dan ini dapat menyebabkan sederhana aplikasi.

Menurut spesifikasi CSI , jika pengontrol CSI melaporkan bahwa itu hanya dapat mengubah ukuran disk "offline" ( VolumeExpansion.OFFLINE), maka proses peningkatan disk harus seperti ini:

Jika plugin hanya memiliki VolumeExpansion.OFFLINEkemampuan ekspansi dan volume saat ini diterbitkan atau tersedia pada sebuah node maka ControllerExpandVolumeHARUS dipanggil HANYA setelah:

  • Plugin memiliki PUBLISH_UNPUBLISH_VOLUMEkemampuan pengontrol dan ControllerUnpublishVolumeberhasil dijalankan.

ATAU

  • Plugin TIDAK memiliki PUBLISH_UNPUBLISH_VOLUMEkemampuan pengontrol , plugin memiliki STAGE_UNSTAGE_VOLUMEkemampuan node , dan NodeUnstageVolumetelah berhasil diselesaikan.

ATAU

  • Plugin TIDAK memiliki PUBLISH_UNPUBLISH_VOLUMEkemampuan pengontrol , atau STAGE_UNSTAGE_VOLUMEkemampuan simpul , dan NodeUnpublishVolumetelah selesai dengan sukses.

Pada dasarnya, ini berarti kebutuhan untuk melepaskan disk dari mesin virtual sebelum meningkatkannya.

Namun, sayangnya, implementasi spesifikasi CSI melalui sespan tidak memenuhi persyaratan ini:

  • Dalam wadah sespan csi-attacher, yang harus bertanggung jawab atas keberadaan celah yang diperlukan antara tunggangan, fungsi ini sama sekali tidak diimplementasikan dengan offline-resize. Diskusi tentang ini telah dimulai di sini .
  • Apa wadah sespan dalam konteks ini? Plugin CSI itu sendiri tidak berinteraksi dengan Kubernetes API, tetapi hanya menanggapi panggilan gRPC yang dikirim oleh kontainer sespan. Yang terakhir sedang dikembangkan oleh komunitas Kubernetes.

Dalam kasus kami (plugin CSI), operasi untuk meningkatkan disk adalah sebagai berikut:

  1. Kami menerima panggilan gRPC ControllerExpandVolume;
  2. Kami mencoba untuk meningkatkan disk di API, tetapi kami mendapatkan kesalahan tentang ketidakmungkinan operasi, karena disk sudah terpasang;
  3. Kami menyimpan pengidentifikasi disk di peta yang berisi disk yang Anda perlukan untuk melakukan operasi peningkatan. Selanjutnya untuk singkatnya kita akan menyebut peta ini sebagai volumeResizeRequired;
  4. Hapus pod secara manual yang menggunakan disk. Kubernetes akan memulai kembali. Agar disk tidak punya waktu untuk memasang ( ControllerPublishVolume) sebelum penyelesaian operasi peningkatan ketika mencoba memasang, kami memeriksa bahwa disk ini masih dalam volumeResizeRequireddan mengembalikan kesalahan;
  5. Driver CSI sedang mencoba menjalankan kembali operasi pengubahan ukuran. Jika operasi berhasil, maka hapus disk dari volumeResizeRequired;
  6. Karena pengidentifikasi disk tidak ada volumeResizeRequired, ControllerPublishVolumeberhasil, disk sudah terpasang, pod dimulai.

Semuanya terlihat cukup sederhana, tetapi seperti biasa ada jebakan. Eksternal-resizer terlibat dalam ekspansi disk , yang, jika terjadi kesalahan selama operasi, menggunakan antrian dengan peningkatan waktu tunggu hingga 1000 detik secara eksponensial:

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 dapat mengarah pada fakta bahwa operasi peningkatan disk direntangkan selama 15+ menit dan, dengan demikian, tidak dapat diaksesnya pod yang sesuai.

Satu-satunya opsi yang memungkinkan kami untuk mengurangi potensi downtime dengan mudah dan tanpa rasa sakit adalah menggunakan versi eksternal-resizer kami dengan batas waktu maksimum 5 detik :

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

Kami tidak menganggap perlu untuk segera memulai diskusi dan menambal-resizer eksternal, karena disk pengubahan ukuran offline adalah atavisme yang akan segera menghilang dari semua penyedia cloud.

Bagaimana cara mulai menggunakan?


Pengemudi didukung di Kubernetes versi 1.15 dan lebih tinggi. Agar pengemudi dapat bekerja, persyaratan berikut harus dipenuhi:

  • Bendera --allow-privilegeddiatur ke nilai trueuntuk server API dan kubelet;
  • Termasuk --feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=trueuntuk server API dan kubelet;
  • Mount propagasi ( mount propagation ) harus dimasukkan dalam cluster. Saat menggunakan Docker, daemon harus dikonfigurasikan agar mount bersama diizinkan.

Semua langkah yang diperlukan untuk instalasi itu sendiri dijelaskan dalam README . Instalasi adalah pembuatan objek di Kubernetes dari manifes.

Agar pengemudi dapat bekerja, Anda memerlukan yang berikut ini:

  • Tunjukkan pengidentifikasi direktori katalog Yandex.Cloud ( folder-id) dalam manifes ( lihat dokumentasi );
  • Untuk berinteraksi dengan Yandex.Cloud API di driver CSI, akun layanan digunakan. Di manifes Rahasia, Anda harus memberikan kunci yang diotorisasi ke akun layanan. Dokumentasi menjelaskan cara membuat akun layanan dan mendapatkan kunci.

Secara umum - cobalah , dan kami akan dengan senang hati menerima umpan balik dan masalah baru jika Anda menemui masalah!

Dukungan lebih lanjut


Sebagai hasilnya, kami ingin mencatat bahwa kami menerapkan driver CSI ini bukan dari keinginan besar untuk bersenang-senang menulis aplikasi di Go, tetapi karena kebutuhan mendesak di dalam perusahaan. Tampaknya tidak disarankan untuk mendukung implementasi kami sendiri, oleh karena itu, jika Yandex menunjukkan minat dan memutuskan untuk terus mendukung pengemudi, kami dengan senang hati akan memindahkan repositori ke pembuangan mereka.

Selain itu, mungkin, Yandex di kluster yang dikelola Kubernetes memiliki implementasi sendiri dari driver CSI, yang dapat dirilis di Open Source. Opsi pengembangan ini juga tampaknya menguntungkan bagi kami - komunitas akan dapat menggunakan driver yang telah terbukti dari penyedia layanan, dan bukan dari perusahaan pihak ketiga.

PS


Baca juga di blog kami:

Source: https://habr.com/ru/post/undefined/


All Articles