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

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

Kami dengan bangga mengumumkan bahwa Flant memperluas kontribusinya terhadap alat Open Source untuk Kubernetes dengan merilisnya versi alfa dari driver CSI (Antarmuka Penyimpanan Kontainer) untuk Yandex.Cloud.

Namun sebelum beralih ke detail implementasi, mari kita jawab pertanyaan mengapa hal ini diperlukan ketika Yandex sudah memiliki layanan Layanan Terkelola untuk Kubernetes.

pengenalan

Kenapa ini?

Di dalam perusahaan kami, sejak awal penggunaan Kubernetes dalam produksi (yaitu selama beberapa tahun sekarang), kami telah mengembangkan alat kami sendiri (deckhouse), yang, kami juga berencana untuk segera menyediakannya sebagai proyek Open Source . Dengan bantuannya, kami mengonfigurasi dan mengonfigurasi semua cluster kami secara seragam, dan saat ini sudah ada lebih dari 100 cluster, pada berbagai konfigurasi perangkat keras dan di semua layanan cloud yang tersedia.

Cluster yang menggunakan deckhouse memiliki semua komponen yang diperlukan untuk pengoperasian: penyeimbang, pemantauan dengan grafik, metrik dan peringatan yang mudah digunakan, otentikasi pengguna melalui penyedia eksternal untuk akses ke semua dasbor, dan sebagainya. Tidak ada gunanya menginstal cluster yang β€œdipompa” dalam solusi terkelola, karena hal ini seringkali tidak mungkin atau akan menyebabkan perlunya menonaktifkan setengah dari komponen.

NB: Ini adalah pengalaman kami, dan ini cukup spesifik. Kami sama sekali tidak menyarankan agar setiap orang menerapkan cluster Kubernetes sendiri daripada menggunakan solusi yang sudah jadi. Omong-omong, kami tidak memiliki pengalaman nyata dalam mengoperasikan Kubernetes dari Yandex dan kami tidak akan memberikan penilaian apa pun terhadap layanan ini di artikel ini.

Apa itu dan untuk siapa?

Jadi, kita telah membicarakan tentang pendekatan modern terhadap penyimpanan di Kubernetes: bagaimana cara kerja CSI? ΠΈ bagaimana komunitas itu datang untuk pendekatan ini.

Saat ini, banyak penyedia layanan cloud besar telah mengembangkan driver untuk menggunakan cloud disk mereka sebagai Persistent Volume di Kubernetes. Jika pemasok tidak memiliki driver seperti itu, tetapi semua fungsi yang diperlukan disediakan melalui API, maka tidak ada yang menghalangi Anda untuk mengimplementasikan driver tersebut sendiri. Inilah yang terjadi dengan Yandex.Cloud.

Kami mengambil sebagai dasar untuk pengembangan 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 dan GCP, dan pada Yandex mengembalikan suatu objek Operation untuk melacak status operasi yang berjalan lama (misalnya, membuat disk baru). Untuk berinteraksi dengan Yandex.Cloud API, gunakan SDK Yandex.Cloud Go.

Hasil pekerjaan yang dilakukan dipublikasikan di GitHub dan mungkin berguna bagi mereka yang, karena alasan tertentu, menggunakan instalasi Kubernetes mereka sendiri di mesin virtual Yandex.Cloud (tetapi bukan cluster terkelola yang sudah jadi) dan ingin menggunakan (memesan) disk melalui CSI.

Implementasi

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;
  • Pengubahan ukuran offline untuk disk (Yandex.Cloud tidak mendukung meningkatkan disk yang dipasang ke mesin virtual). Untuk informasi tentang bagaimana driver harus dimodifikasi agar pengubahan ukuran menjadi semudah mungkin, lihat di bawah.

Di masa mendatang, kami berencana menerapkan dukungan untuk membuat dan menghapus snapshot disk.

Kesulitan utama dan cara mengatasinya

Kurangnya kemampuan untuk menambah disk secara real time di Yandex.Cloud API merupakan batasan yang mempersulit operasi pengubahan ukuran untuk PV (Persistent Volume): dalam hal ini, pod aplikasi yang menggunakan disk perlu dihentikan, dan hal ini dapat menyebabkan downtime aplikasi.

Menurut spesifikasi CSI, jika pengontrol CSI melaporkan bahwa ia hanya dapat mengubah ukuran disk secara "offline" (VolumeExpansion.OFFLINE), maka proses penambahan disk akan berjalan seperti ini:

Jika plugin hanya memiliki VolumeExpansion.OFFLINE kemampuan ekspansi dan volume saat ini dipublikasikan atau tersedia di node saat itu ControllerExpandVolume HARUS dipanggil HANYA setelah:

  • Plugin ini memiliki pengontrol PUBLISH_UNPUBLISH_VOLUME kemampuan dan ControllerUnpublishVolume telah berhasil dipanggil.

ATAU

  • Plugin TIDAK memiliki pengontrol PUBLISH_UNPUBLISH_VOLUME kemampuan, plugin memiliki node STAGE_UNSTAGE_VOLUME kemampuan, dan NodeUnstageVolume telah berhasil diselesaikan.

ATAU

  • Plugin TIDAK memiliki pengontrol PUBLISH_UNPUBLISH_VOLUME kemampuan, atau simpul STAGE_UNSTAGE_VOLUME kemampuan, dan NodeUnpublishVolume telah selesai dengan sukses.

Ini pada dasarnya berarti Anda perlu melepaskan disk dari mesin virtual sebelum mengembangkannya.

Namun sayangnya implementasi Spesifikasi CSI melalui sidecar tidak memenuhi persyaratan berikut:

  • Dalam wadah sespan csi-attacher, yang seharusnya bertanggung jawab atas adanya celah yang diperlukan antar mount, fungsi ini tidak diterapkan dalam pengubahan ukuran offline. Diskusi mengenai hal ini pun dimulai di sini.
  • Apa sebenarnya wadah sespan dalam konteks ini? Plugin CSI sendiri tidak berinteraksi dengan API Kubernetes, tetapi hanya merespons panggilan gRPC yang dikirimkan melalui container sidecar. Terbaru sedang dikembangkan oleh komunitas Kubernetes.

Dalam kasus kami (plugin CSI), operasi peningkatan disk terlihat seperti ini:

  1. Kami menerima panggilan gRPC ControllerExpandVolume;
  2. Kami mencoba meningkatkan disk di API, tetapi kami menerima kesalahan tentang ketidakmungkinan melakukan operasi karena disk sudah terpasang;
  3. Kami menyimpan pengidentifikasi disk di peta, yang berisi disk yang perlu dilakukan operasi peningkatan. Di bawah ini, untuk singkatnya, kami akan menyebut peta ini sebagai volumeResizeRequired;
  4. Hapus pod yang menggunakan disk secara manual. Kubernetes akan memulainya kembali. Sehingga disk tidak punya waktu untuk dipasang (ControllerPublishVolume) sebelum menyelesaikan operasi peningkatan saat mencoba memasang, kami memeriksa apakah disk yang diberikan masih ada volumeResizeRequired dan mengembalikan kesalahan;
  5. Pengandar CSI mencoba menjalankan kembali operasi pengubahan ukuran. Jika operasi berhasil, keluarkan disk dari volumeResizeRequired;
  6. Karena ID Disk tidak ada volumeResizeRequired, ControllerPublishVolume berhasil lolos, disk dipasang, pod dimulai.

Semuanya terlihat cukup sederhana, tapi seperti biasa selalu ada kendala. Memperbesar disk pengubah ukuran eksternal, yang jika terjadi kesalahan selama operasi menggunakan antrian dengan peningkatan waktu tunggu yang eksponensial hingga 1000 detik:

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

Hal ini secara berkala dapat mengakibatkan operasi perluasan disk diperpanjang selama 15+ menit dan, dengan demikian, pod terkait tidak tersedia.

Satu-satunya pilihan yang cukup mudah dan tanpa rasa sakit memungkinkan kami mengurangi potensi downtime adalah penggunaan versi resizer eksternal kami dengan batas waktu habis maksimum dalam 5 detik:

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

Kami tidak menganggap perlu untuk segera memulai diskusi dan menambal pengubah ukuran eksternal, karena pengubahan ukuran disk secara offline adalah sebuah kemunduran yang akan segera hilang dari semua penyedia cloud.

Bagaimana cara mulai menggunakannya?

Driver ini didukung pada Kubernetes versi 1.15 dan lebih tinggi. Agar pengemudi dapat bekerja, persyaratan berikut harus dipenuhi:

  • Bendera --allow-privileged ditetapkan ke nilai true untuk server API dan kubelet;
  • Termasuk --feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=true untuk server API dan kubelet;
  • Gunung propagasi (mount propagasi) harus diaktifkan di cluster. Saat menggunakan Docker, daemon harus dikonfigurasi untuk mengizinkan pemasangan bersama.

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

Agar driver dapat berfungsi, Anda memerlukan yang berikut ini:

  • Tentukan pengidentifikasi direktori dalam manifes (folder-id) Yandex.Cloud (lihat dokumentasi);
  • Untuk berinteraksi dengan Yandex.Cloud API, driver CSI menggunakan akun layanan. Dalam manifes, Rahasia harus disahkan kunci resmi dari akun layanan. Dalam dokumentasi dijelaskan, cara membuat akun layanan dan mendapatkan kunci.

Semua seutuhnya - coba, dan kami akan dengan senang hati menerima masukan dan masalah barujika Anda menemui masalah!

Dukungan lebih lanjut

Oleh karena itu, kami ingin mencatat bahwa kami mengimplementasikan driver CSI ini bukan karena keinginan besar untuk bersenang-senang menulis aplikasi di Go, tetapi karena kebutuhan mendesak dalam perusahaan. Tampaknya tidak praktis bagi kami untuk mempertahankan implementasi kami sendiri, jadi jika Yandex menunjukkan minat dan memutuskan untuk terus mendukung driver, kami akan dengan senang hati mentransfer repositori kepada mereka.

Selain itu, Yandex mungkin memiliki implementasi driver CSI sendiri di cluster Kubernetes yang dikelolanya, yang dapat dirilis dalam Open Source. Kami juga melihat opsi pengembangan ini menguntungkan - komunitas akan dapat menggunakan driver yang sudah terbukti dari penyedia layanan, dan bukan dari perusahaan pihak ketiga.

PS

Baca juga di blog kami:

Sumber: www.habr.com

Tambah komentar