Plugin volume untuk penyimpanan Kubernetes: dari Flexvolume hingga CSI

Plugin volume untuk penyimpanan Kubernetes: dari Flexvolume hingga CSI

Dulu ketika Kubernetes masih v1.0.0, ada plugin volume. Mereka diperlukan untuk menghubungkan sistem ke Kubernetes untuk menyimpan data container yang persisten (permanen). Jumlahnya kecil, dan yang pertama adalah penyedia penyimpanan seperti GCE PD, Ceph, AWS EBS, dan lainnya.

Plugin ini dikirimkan bersama dengan Kubernetes, itulah sebabnya mereka mendapatkan namanya - in-tree. Namun, bagi banyak orang, rangkaian plugin yang ada ternyata tidak cukup. Pengrajin menambahkan plugin sederhana ke inti Kubernetes menggunakan patch, setelah itu mereka merakit Kubernetes mereka sendiri dan menginstalnya di server mereka. Namun seiring berjalannya waktu, pengembang Kubernetes menyadari hal itu ikan masalahnya tidak dapat diselesaikan. Orang membutuhkan pancing. Dan di rilis Kubernetes v1.2.0 muncul...

Plugin Flexvolume: pancing minimal

Pengembang Kubernetes membuat plugin FlexVolume, yang merupakan kerangka logis dari variabel dan metode untuk bekerja dengan driver Flexvolume yang diterapkan oleh pengembang pihak ketiga.

Mari kita berhenti dan melihat lebih dekat apa itu driver FlexVolume. Ini adalah suatu hal yang pasti file yang dapat dieksekusi (file biner, skrip Python, skrip Bash, dll.), yang, ketika dijalankan, mengambil argumen baris perintah sebagai input dan mengembalikan pesan dengan bidang yang telah diketahui sebelumnya dalam format JSON. Berdasarkan konvensi, argumen baris perintah pertama selalu berupa metode, dan argumen lainnya adalah parameternya.

Plugin volume untuk penyimpanan Kubernetes: dari Flexvolume hingga CSI
Diagram koneksi untuk Saham CIFS di OpenShift. Flexvolume Driver - Tepat di Tengah

Kumpulan metode minimum Ini terlihat seperti ini:

flexvolume_driver mount # ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚ Π·Π° присоСдинСниС Ρ‚ΠΎΠΌΠ° ΠΊ pod'Ρƒ
# Π€ΠΎΡ€ΠΌΠ°Ρ‚ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ³ΠΎ сообщСния:
{
  "status": "Success"/"Failure"/"Not supported",
  "message": "По ΠΊΠ°ΠΊΠΎΠΉ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π΅ Π±Ρ‹Π» Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π΅Π½ ΠΈΠΌΠ΅Π½Π½ΠΎ Ρ‚Π°ΠΊΠΎΠΉ статус",
}

flexvolume_driver unmount # ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚ Π·Π° отсоСдинСниС Ρ‚ΠΎΠΌΠ° ΠΎΡ‚ pod'Π°
# Π€ΠΎΡ€ΠΌΠ°Ρ‚ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ³ΠΎ сообщСния:
{
  "status": "Success"/"Failure"/"Not supported",
  "message": "По ΠΊΠ°ΠΊΠΎΠΉ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π΅ Π±Ρ‹Π» Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π΅Π½ ΠΈΠΌΠ΅Π½Π½ΠΎ Ρ‚Π°ΠΊΠΎΠΉ статус",
}

flexvolume_driver init # ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚ Π·Π° ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ ΠΏΠ»Π°Π³ΠΈΠ½Π°
# Π€ΠΎΡ€ΠΌΠ°Ρ‚ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ³ΠΎ сообщСния:
{
  "status": "Success"/"Failure"/"Not supported",
  "message": "По ΠΊΠ°ΠΊΠΎΠΉ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π΅ Π±Ρ‹Π» Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π΅Π½ ΠΈΠΌΠ΅Π½Π½ΠΎ Ρ‚Π°ΠΊΠΎΠΉ статус",
  // ΠžΠΏΡ€Π΅Π΄Π΅Π»ΡΠ΅Ρ‚, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Π»ΠΈ Π΄Ρ€Π°ΠΉΠ²Π΅Ρ€ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ attach/deatach
  "capabilities":{"attach": True/False}
}

Menggunakan Metode attach ΠΈ detach akan menentukan skenario dimana kubelet akan bertindak di masa depan ketika memanggil driver. Ada juga metode khusus expandvolume ΠΈ expandfs, yang bertanggung jawab untuk mengubah ukuran volume secara dinamis.

Sebagai contoh perubahan yang ditambahkan metode expandvolume, dan dengan itu kemampuan untuk mengubah ukuran volume secara real time, Anda dapat membiasakan diri dengannya permintaan tarik kami di Operator Benteng Ceph.

Dan berikut contoh implementasi driver Flexvolume untuk bekerja dengan NFS:

usage() {
    err "Invalid usage. Usage: "
    err "t$0 init"
    err "t$0 mount <mount dir> <json params>"
    err "t$0 unmount <mount dir>"
    exit 1
}

err() {
    echo -ne $* 1>&2
}

log() {
    echo -ne $* >&1
}

ismounted() {
    MOUNT=`findmnt -n ${MNTPATH} 2>/dev/null | cut -d' ' -f1`
    if [ "${MOUNT}" == "${MNTPATH}" ]; then
        echo "1"
    else
        echo "0"
    fi
}

domount() {
    MNTPATH=$1

    NFS_SERVER=$(echo $2 | jq -r '.server')
    SHARE=$(echo $2 | jq -r '.share')

    if [ $(ismounted) -eq 1 ] ; then
        log '{"status": "Success"}'
        exit 0
    fi

    mkdir -p ${MNTPATH} &> /dev/null

    mount -t nfs ${NFS_SERVER}:/${SHARE} ${MNTPATH} &> /dev/null
    if [ $? -ne 0 ]; then
        err "{ "status": "Failure", "message": "Failed to mount ${NFS_SERVER}:${SHARE} at ${MNTPATH}"}"
        exit 1
    fi
    log '{"status": "Success"}'
    exit 0
}

unmount() {
    MNTPATH=$1
    if [ $(ismounted) -eq 0 ] ; then
        log '{"status": "Success"}'
        exit 0
    fi

    umount ${MNTPATH} &> /dev/null
    if [ $? -ne 0 ]; then
        err "{ "status": "Failed", "message": "Failed to unmount volume at ${MNTPATH}"}"
        exit 1
    fi

    log '{"status": "Success"}'
    exit 0
}

op=$1

if [ "$op" = "init" ]; then
    log '{"status": "Success", "capabilities": {"attach": false}}'
    exit 0
fi

if [ $# -lt 2 ]; then
    usage
fi

shift

case "$op" in
    mount)
        domount $*
        ;;
    unmount)
        unmount $*
        ;;
    *)
        log '{"status": "Not supported"}'
        exit 0
esac

exit 1

Jadi, setelah menyiapkan file eksekusi sebenarnya, Anda perlu melakukannya unggah driver ke cluster Kubernetes. Driver harus ditempatkan pada setiap node cluster sesuai jalur yang telah ditentukan. Secara default dipilih:

/usr/libexec/kubernetes/kubelet-plugins/volume/exec/имя_поставщика_Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π°~имя_Π΄Ρ€Π°ΠΉΠ²Π΅Ρ€Π°/

... tetapi ketika menggunakan distribusi Kubernetes yang berbeda (OpenShift, Rancher...) jalurnya mungkin berbeda.

Masalah Flexvolume: bagaimana cara melemparkan joran dengan benar?

Mengunggah driver Flexvolume ke node cluster ternyata merupakan tugas yang tidak sepele. Setelah melakukan operasi secara manual sekali, mudah untuk menghadapi situasi di mana node baru muncul di cluster: karena penambahan node baru, penskalaan horizontal otomatis, atau - yang lebih buruk - penggantian node karena kegagalan fungsi. Dalam hal ini, pekerjaan dengan penyimpanan pada node ini harus dilakukan tidak mungkin, hingga Anda masih menambahkan driver Flexvolume secara manual ke dalamnya.

Solusi untuk masalah ini adalah salah satu primitif Kubernetes - DaemonSet. Ketika sebuah node baru muncul di cluster, secara otomatis berisi sebuah pod dari DaemonSet kami, yang mana volume lokal terpasang di sepanjang jalur untuk menemukan driver Flexvolume. Setelah pembuatan berhasil, pod akan menyalin file yang diperlukan agar driver dapat berfungsi ke disk.

Berikut adalah contoh DaemonSet untuk meletakkan plugin Flexvolume:

apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: flex-set
spec:
  template:
    metadata:
      name: flex-deploy
      labels:
        app: flex-deploy
    spec:
      containers:
        - image: <deployment_image>
          name: flex-deploy
          securityContext:
              privileged: true
          volumeMounts:
            - mountPath: /flexmnt
              name: flexvolume-mount
      volumes:
        - name: flexvolume-mount
          hostPath:
            path: <host_driver_directory>

... dan contoh skrip Bash untuk meletakkan driver Flexvolume:

#!/bin/sh

set -o errexit
set -o pipefail

VENDOR=k8s.io
DRIVER=nfs

driver_dir=$VENDOR${VENDOR:+"~"}${DRIVER}
if [ ! -d "/flexmnt/$driver_dir" ]; then
  mkdir "/flexmnt/$driver_dir"
fi

cp "/$DRIVER" "/flexmnt/$driver_dir/.$DRIVER"
mv -f "/flexmnt/$driver_dir/.$DRIVER" "/flexmnt/$driver_dir/$DRIVER"

while : ; do
  sleep 3600
done

Penting untuk tidak melupakan operasi penyalinan bukan atom. Ada kemungkinan besar kubelet akan mulai menggunakan driver sebelum proses penyediaannya selesai, yang akan menyebabkan kesalahan pada sistem. Pendekatan yang benar adalah dengan terlebih dahulu menyalin file driver dengan nama yang berbeda, dan kemudian menggunakan operasi penggantian nama atom.

Plugin volume untuk penyimpanan Kubernetes: dari Flexvolume hingga CSI
Diagram bekerja dengan Ceph di operator Benteng: driver Flexvolume dalam diagram terletak di dalam agen Benteng

Masalah selanjutnya saat menggunakan driver Flexvolume adalah sebagian besar penyimpanan pada node cluster perangkat lunak yang diperlukan untuk ini harus diinstal (misalnya, paket ceph-common untuk Ceph). Awalnya, plugin Flexvolume tidak dirancang untuk mengimplementasikan sistem yang rumit seperti itu.

Solusi orisinal untuk masalah ini dapat dilihat pada implementasi driver Flexvolume dari operator Benteng:

Drivernya sendiri dirancang sebagai klien RPC. Soket IPC untuk komunikasi terletak di direktori yang sama dengan driver itu sendiri. Kami ingat bahwa untuk menyalin file driver sebaiknya menggunakan DaemonSet, yang menghubungkan direktori dengan driver sebagai volume. Setelah menyalin file driver benteng yang diperlukan, pod ini tidak mati, tetapi terhubung ke soket IPC melalui volume terlampir sebagai server RPC lengkap. Paket ceph-common sudah terinstal di dalam wadah pod. Soket IPC memastikan bahwa kubelet akan berkomunikasi dengan pod yang terletak di node yang sama. Segala sesuatu yang cerdik itu sederhana!..

Selamat tinggal, plugin in-tree kami yang penuh kasih sayang!

Pengembang Kubernetes menemukan bahwa jumlah plugin untuk penyimpanan di dalam inti adalah dua puluh. Dan perubahan pada masing-masingnya, dengan satu atau lain cara, terjadi melalui siklus rilis penuh Kubernetes.

Ternyata untuk menggunakan plugin penyimpanan versi baru, Anda perlu memperbarui seluruh cluster. Selain itu, Anda mungkin terkejut bahwa versi baru Kubernetes tiba-tiba menjadi tidak kompatibel dengan kernel Linux yang Anda gunakan... Jadi, Anda menghapus air mata Anda dan, sambil mengertakkan gigi, berkoordinasi dengan manajemen dan pengguna Anda waktu untuk perbarui kernel Linux dan cluster Kubernetes. Dengan kemungkinan downtime dalam penyediaan layanan.

Situasinya lebih dari sekadar lucu, bukan begitu? Menjadi jelas bagi seluruh masyarakat bahwa pendekatan ini tidak berhasil. Dengan keputusan yang disengaja, pengembang Kubernetes mengumumkan bahwa plugin baru untuk bekerja dengan penyimpanan tidak lagi diterima di kernel. Selain itu, seperti yang telah kita ketahui, sejumlah kekurangan teridentifikasi dalam implementasi plugin Flexvolume...

Plugin terbaru yang ditambahkan untuk volume di Kubernetes, CSI, digunakan untuk mengatasi masalah penyimpanan data persisten untuk selamanya. Versi alfanya, yang lebih lengkap disebut sebagai Plugin Volume CSI Out-of-Tree, diumumkan pada rilis Kubernet 1.9.

Antarmuka Penyimpanan Kontainer, atau batang pemintal CSI 3000!

Pertama-tama, saya ingin mencatat bahwa CSI bukan hanya plugin volume, tetapi nyata standar tentang membuat komponen khusus untuk bekerja dengan gudang data. Sistem orkestrasi container seperti Kubernetes dan Mesos seharusnya β€œmempelajari” cara bekerja dengan komponen yang diimplementasikan sesuai standar ini. Dan sekarang saya sudah mempelajari Kubernetes.

Bagaimana struktur plugin CSI di Kubernetes? Plugin CSI bekerja dengan driver khusus (driver CSI) ditulis oleh pengembang pihak ketiga. Driver CSI di Kubernetes minimal terdiri dari dua komponen (pod):

  • pengawas β€” mengelola penyimpanan persisten eksternal. Ini diimplementasikan sebagai server gRPC, yang menggunakan primitif StatefulSet.
  • Node β€” bertanggung jawab untuk memasang penyimpanan persisten ke node cluster. Ini juga diimplementasikan sebagai server gRPC, tetapi menggunakan versi primitif DaemonSet.

Plugin volume untuk penyimpanan Kubernetes: dari Flexvolume hingga CSI
Cara kerja plugin CSI di Kubernetes

Anda dapat mempelajari beberapa detail lain dari pekerjaan CSI, misalnya dari artikel β€œMemahami C.S.I.' terjemahan yang mana kami menerbitkannya setahun yang lalu.

Keuntungan dari implementasi tersebut

  • Untuk hal-hal dasar seperti mendaftarkan driver untuk sebuah node, pengembang Kubernetes mengimplementasikan sekumpulan container. Anda tidak perlu lagi membuat respons JSON dengan kemampuan sendiri, seperti yang dilakukan untuk plugin Flexvolume.
  • Daripada β€œmenyelipkan” file yang dapat dieksekusi ke node, kami sekarang mengunggah pod ke cluster. Inilah yang awalnya kami harapkan dari Kubernetes: semua proses terjadi di dalam container yang di-deploy menggunakan primitif Kubernetes.
  • Anda tidak perlu lagi mengembangkan server RPC dan klien RPC untuk mengimplementasikan driver yang rumit. Klien ini diimplementasikan untuk kami oleh pengembang Kubernetes.
  • Melewati argumen untuk bekerja melalui protokol gRPC jauh lebih nyaman, fleksibel, dan andal dibandingkan meneruskannya melalui argumen baris perintah. Untuk memahami cara menambahkan dukungan metrik penggunaan volume ke CSI dengan menambahkan metode gRPC standar, Anda dapat membaca: permintaan tarik kami untuk driver vsphere-csi.
  • Komunikasi terjadi melalui soket IPC, sehingga tidak bingung apakah kubelet mengirimkan permintaan ke pod yang benar.

Apakah daftar ini mengingatkan Anda pada sesuatu? Kelebihan CSI adalah memecahkan masalah yang sama, yang tidak diperhitungkan saat mengembangkan plugin Flexvolume.

Temuan

CSI sebagai standar implementasi plugin khusus untuk berinteraksi dengan data warehouse diterima dengan sangat hangat oleh komunitas. Selain itu, karena kelebihan dan keserbagunaannya, driver CSI dibuat bahkan untuk sistem penyimpanan seperti Ceph atau AWS EBS, plugin untuk bekerja yang ditambahkan pada versi pertama Kubernetes.

Di awal tahun 2019, plugin in-tree telah dinyatakan usang. Kami berencana untuk terus mendukung plugin Flexvolume, tetapi tidak akan mengembangkan fungsionalitas baru untuk plugin tersebut.

Kami sendiri sudah berpengalaman menggunakan ceph-csi, vsphere-csi dan siap menambah daftar ini! Sejauh ini, CSI mengatasi tugas yang diberikan kepadanya dengan baik, tapi kita akan menunggu dan melihat.

Jangan lupa bahwa segala sesuatu yang baru adalah pemikiran ulang yang baik atas yang lama!

PS

Baca juga di blog kami:

Sumber: www.habr.com

Tambah komentar