1 - Penjadwal Kubernetes

Dalam Kubernetes, scheduling atau penjadwalan ditujukan untuk memastikan Pod mendapatkan Node sehingga Kubelet dapat menjalankannya.

Ikhtisar Penjadwalan

Sebuah penjadwal mengawasi Pod yang baru saja dibuat dan belum ada Node yang dialokasikan untuknya. Untuk setiap Pod yang ditemukan oleh penjadwal, maka penjadwal tersebut bertanggung jawab untuk menemukan Node terbaik untuk menjalankan Pod. Penjadwal dapat menetapkan keputusan penempatan ini dengan mempertimbangkan prinsip-prinsip penjadwalan yang dijelaskan di bawah ini.

Jika kamu ingin memahami mengapa Pod ditempatkan pada Node tertentu, atau jika kamu berencana untuk mengimplementasikan penjadwal kustom sendiri, halaman ini akan membantu kamu belajar tentang penjadwalan.

Kube-scheduler

Kube-scheduler adalah penjadwal standar untuk Kubernetes dan dijalankan sebagai bagian dari _control plane_. Kube-scheduler dirancang agar jika kamu mau dan perlu, kamu bisa menulis komponen penjadwalan kamu sendiri dan menggunakannya.

Untuk setiap Pod yang baru dibuat atau Pod yang tak terjadwal lainnya, kube-scheduler memilih Node yang optimal untuk menjalankannya. Namun, setiap kontainer masuk Pod memiliki persyaratan sumber daya yang berbeda dan setiap Pod juga memiliki persyaratan yang berbeda juga. Oleh karena itu, Node yang ada perlu dipilih sesuai dengan persyaratan khusus penjadwalan.

Dalam sebuah Klaster, Node yang memenuhi persyaratan penjadwalan untuk suatu Pod disebut Node feasible. Jika tidak ada Node yang cocok, maka Pod tetap tidak terjadwal sampai penjadwal yang mampu menempatkannya.

Penjadwal menemukan Node-Node yang layak untuk sebuah Pod dan kemudian menjalankan sekumpulan fungsi untuk menilai Node-Node yang layak dan mengambil satu Node dengan skor tertinggi di antara Node-Node yang layak untuk menjalankan Pod. Penjadwal kemudian memberi tahu server API tentang keputusan ini dalam proses yang disebut dengan binding.

Beberapa faktor yang perlu dipertimbangkan untuk keputusan penjadwalan termasuk persyaratan sumber daya individu dan kolektif, aturan kebijakan / perangkat keras / lunak, spesifikasi persamaan dan anti-persamaan, lokalitas data, interferensi antar Workloads, dan sebagainya.

Pemilihan node pada kube-scheduler

Kube-scheduler memilih node untuk pod dalam 2 langkah operasi:

  1. Filtering
  2. Scoring

Langkah filtering menemukan sekumpulan Nodes yang layak untuk menjadwalkan Pod. Misalnya, penyarin PodFitsResources memeriksa apakah Node kandidat memiliki sumber daya yang cukup untuk memenuhi permintaan spesifik sumber daya dari Pod. Setelah langkah ini, daftar Node akan berisi Node-node yang sesuai; seringkali, akan terisi lebih dari satu. Jika daftar itu kosong, maka Pod itu tidak (belum) dapat dijadwalkan.

Pada langkah scoring, penjadwal memberi peringkat pada Node-node yang tersisa untuk memilih penempatan paling cocok untuk Pod. Penjadwal memberikan skor untuk setiap Node yang sudah tersaring, memasukkan skor ini pada aturan penilaian yang aktif.

Akhirnya, kube-scheduler memberikan Pod ke Node dengan peringkat tertinggi. Jika ada lebih dari satu node dengan skor yang sama, maka kube-scheduler memilih salah satunya secara acak.

Ada dua cara yang didukung untuk mengkonfigurasi perilaku penyaringan dan penilaian oleh penjadwal:

  1. Aturan Penjadwalan yang memungkinkan kamu untuk mengkonfigurasi Predicates untuk pemfilteran dan Priorities untuk penilaian.
  2. Profil Penjadwalan yang memungkinkan kamu mengkonfigurasi Plugin yang menerapkan tahapan penjadwalan berbeda, termasuk: QueueSort, Filter, Score, Bind, Reserve, Permit, dan lainnya. Kamu juga bisa mengonfigurasi kube-scheduler untuk menjalankan profil yang berbeda.

Selanjutnya

2 - Kerangka Kerja Penjadwalan (Scheduling Framework)

FEATURE STATE: Kubernetes 1.15 [alpha]

Kerangka kerja penjadwalan (Scheduling Framework) adalah arsitektur yang dapat dipasang (pluggable) pada penjadwal Kubernetes untuk membuat kustomisasi penjadwal lebih mudah. Hal itu dilakukan dengan menambahkan satu kumpulan "plugin" API ke penjadwal yang telah ada. Plugin dikompilasi ke dalam penjadwal. Beberapa API memungkinkan sebagian besar fitur penjadwalan diimplementasikan sebagai plugin, sambil tetap mempertahankan penjadwalan "inti" sederhana dan terpelihara. Silahkan merujuk pada [proposal desain dari kerangka penjadwalan] kep untuk informasi teknis lebih lanjut tentang desain kerangka kerja tersebut.

Alur kerja kerangka kerja

Kerangka kerja penjadwalan mendefinisikan beberapa titik ekstensi. Plugin penjadwal mendaftar untuk dipanggil di satu atau lebih titik ekstensi. Beberapa plugin ini dapat mengubah keputusan penjadwalan dan beberapa hanya bersifat informasi.

Setiap upaya untuk menjadwalkan satu Pod dibagi menjadi dua fase, Siklus Penjadwalan (Scheduling Cycle) dan Siklus Pengikatan (Binding Cycle).

Siklus Penjadwalan dan Siklus Pengikatan

Siklus penjadwalan memilih sebuah Node untuk Pod, dan siklus pengikatan menerapkan keputusan tersebut ke klaster. Secara bersama-sama, siklus penjadwalan dan siklus pengikatan diartikan sebagai sebuah "konteks penjadwalan (scheduling context)".

Siklus penjadwalan dijalankan secara serial, sementara siklus pengikatan dapat berjalan secara bersamaan.

Siklus penjadwalan atau pengikatan dapat dibatalkan jika Pod telah ditentukan untuk tidak terjadwalkan atau jika terdapat kesalahan internal. Pod akan dikembalikan ke antrian dan dicoba lagi.

Titik-titik ekstensi

Gambar berikut menunjukkan konteks penjadwalan Pod dan titik-titik ekstensi yang diperlihatkan oleh kerangka penjadwalan. Dalam gambar ini "Filter" setara dengan "Predicate" dan "Scoring" setara dengan "Priority Function".

Satu plugin dapat mendaftar di beberapa titik ekstensi untuk melakukan pekerjaan yang lebih kompleks atau stateful.

Titik-titik ekstensi dari kerangka kerja Penjadwalan

QueueSort

Plugin ini digunakan untuk mengurutkan Pod-Pod dalam antrian penjadwalan. Plugin QueueSort pada dasarnya menyediakan fungsi Less (Pod1, Pod2). Hanya satu jenis plugin QueueSort yang dapat diaktifkan dalam waktu yang bersamaan.

PreFilter

Plugin ini digunakan untuk melakukan pra-proses informasi tentang Pod, atau untuk memeriksa tertentu kondisi yang harus dipenuhi oleh klaster atau Pod. Jika plugin PreFilter menghasilkan hasil yang salah, siklus penjadwalan dibatalkan.

Filter

Plugin ini digunakan untuk menyaring Node yang tidak dapat menjalankan Pod. Untuk setiap Node, penjadwal akan memanggil plugin Filter sesuai dengan urutan mereka dikonfigurasi. Jika ada plugin Filter menandai Node menjadi infeasible, maka plugin yang lainnya tidak akan dipanggil untuk Node itu. Node-Node dapat dievaluasi secara bersamaan.

PostFilter

Plugin ini disebut setelah fase Filter, tetapi hanya ketika tidak ada node yang layak ditemukan untuk pod. Plugin dipanggil dalam urutan yang dikonfigurasi. Jika plugin postFilter menandai node sebagai 'Schedulable', plugin yang tersisa tidak akan dipanggil. Implementasi PostFilter yang khas adalah preemption, yang mencoba membuat pod dapat di menjadwalkan dengan mendahului Pod lain.

PreScore

Plugin ini digunakan untuk melakukan pekerjaan "pra-penilaian", yang menghasilkan keadaan yang dapat dibagi untuk digunakan oleh plugin-plugin Score. Jika plugin PreScore mengeluarkan hasil salah, maka siklus penjadwalan dibatalkan.

Score

Plugin ini digunakan untuk menentukan peringkat Node yang telah melewati fase penyaringan. Penjadwal akan memanggil setiap plugin Score untuk setiap Node. Akan ada kisaran bilangan bulat yang telah ditetapkan untuk mewakili skor minimum dan maksimum. Setelah fase NormalizeScore, penjadwal akan menggabungkan skor Node dari semua plugin sesuai dengan bobot plugin yang telah dikonfigurasi.

NormalizeScore

Plugin ini digunakan untuk memodifikasi skor sebelum penjadwal menghitung peringkat akhir Node-Node. Plugin yang mendaftar untuk titik ekstensi ini akan dipanggil dengan hasil Score dari plugin yang sama. Hal ini dilakukan sekali untuk setiap plugin dan setiap siklus penjadwalan.

Sebagai contoh, anggaplah sebuah plugin BlinkingLightScorer memberi peringkat pada Node-Node berdasarkan berapa banyak kedipan lampu yang mereka miliki.

func ScoreNode(_ *v1.pod, n *v1.Node) (int, error) {
    return getBlinkingLightCount(n)
}

Namun, jumlah maksimum kedipan lampu mungkin kecil jika dibandingkan dengan NodeScoreMax. Untuk memperbaikinya, BlinkingLightScorer juga harus mendaftar untuk titik ekstensi ini.

func NormalizeScores(scores map[string]int) {
    highest := 0
    for _, score := range scores {
        highest = max(highest, score)
    }
    for node, score := range scores {
        scores[node] = score*NodeScoreMax/highest
    }
}

Jika ada plugin NormalizeScore yang menghasilkan hasil yang salah, maka siklus penjadwalan dibatalkan.

Catatan: Plugin yang ingin melakukan pekerjaan "pra-pemesanan" harus menggunakan titik ekstensi NormalizeScore.

Reserve

Ini adalah titik ekstensi yang bersifat informasi. Plugin yang mempertahankan keadaan runtime (alias "stateful plugins") harus menggunakan titik ekstensi ini untuk diberitahukan oleh penjadwal ketika sumber daya pada suatu Node dicadangkan untuk Pod yang telah disiapkan. Proses ini terjadi sebelum penjadwal benar-benar mengikat Pod ke Node, dan itu ada untuk mencegah kondisi balapan (race conditions) ketika penjadwal menunggu agar pengikatan berhasil.

Ini adalah langkah terakhir dalam siklus penjadwalan. Setelah Pod berada dalam status dicadangkan, maka itu akan memicu plugin Unreserve (apabila gagal) atau plugin PostBind (apabila sukses) di akhir siklus pengikatan.

Permit

Plugin Permit dipanggil pada akhir siklus penjadwalan untuk setiap Pod untuk mencegah atau menunda pengikatan ke Node kandidat. Plugin Permit dapat melakukan salah satu dari ketiga hal ini:

  1. approve
         Setelah semua plugin Permit menyetujui sebuah Pod, Pod tersebut akan dikirimkan untuk diikat.

  2. deny
         Jika ada plugin Permit yang menolak sebuah Pod, Pod tersebut akan dikembalikan ke antrian penjadwalan. Hal ini akan memicu plugin Unreserve.

  3. wait (dengan batas waktu)
         Jika plugin Permit menghasilkan "wait", maka Pod disimpan dalam      daftar Pod "yang menunggu" internal, dan siklus pengikatan Pod ini dimulai tetapi akan langsung diblokir      sampai mendapatkan approved. Jika waktu tunggu habis, ** wait ** menjadi ** deny **      dan Pod dikembalikan ke antrian penjadwalan, yang memicu plugin Unreserve.

Catatan: Ketika setiap plugin dapat mengakses daftar Pod-Pod "yang menunggu" dan menyetujuinya (silahkan lihat FrameworkHandle), kami hanya mengharapkan plugin Permit untuk menyetujui pengikatan Pod dalam kondisi "menunggu" yang telah dipesan. Setelah Pod disetujui, akan dikirim ke fase PreBind.

PreBind

Plugin ini digunakan untuk melakukan pekerjaan apa pun yang diperlukan sebelum Pod terikat. Sebagai contoh, plugin PreBind dapat menyediakan network volume dan melakukan mounting pada Node target sebelum mengizinkan Pod berjalan di sana.

Jika ada plugin PreBind yang menghasilkan kesalahan, maka Pod ditolak dan kembali ke antrian penjadwalan.

Bind

Plugin ini digunakan untuk mengikat Pod ke Node. Plugin-plugin Bind tidak akan dipanggil sampai semua plugin PreBind selesai. Setiap plugin Bind dipanggil sesuai urutan saat dikonfigurasi. Plugin Bind dapat memilih untuk menangani atau tidak Pod yang diberikan. Jika plugin Bind memilih untuk menangani Pod, ** plugin Bind yang tersisa dilewati **.

PostBind

Ini adalah titik ekstensi bersifat informasi. Plugin-plugin PostBind dipanggil setelah sebuah Pod berhasil diikat. Ini adalah akhir dari siklus pengikatan, dan dapat digunakan untuk membersihkan sumber daya terkait.

Unreserve

Ini adalah titik ekstensi bersifat informasi. Jika sebuah Pod telah dipesan dan kemudian ditolak di tahap selanjutnya, maka plugin-plugin Unreserve akan diberitahu. Plugin Unreserve harus membersihkan status yang terkait dengan Pod yang dipesan.

Plugin yang menggunakan titik ekstensi ini sebaiknya juga harus digunakan Reserve.

Plugin API

Ada dua langkah untuk plugin API. Pertama, plugin harus mendaftar dan mendapatkan konfigurasi, kemudian mereka menggunakan antarmuka titik ekstensi. Antarmuka (interface) titik ekstensi memiliki bentuk sebagai berikut.

type Plugin interface {
    Name() string
}

type QueueSortPlugin interface {
    Plugin
    Less(*v1.pod, *v1.pod) bool
}

type PreFilterPlugin interface {
    Plugin
    PreFilter(context.Context, *framework.CycleState, *v1.pod) error
}

// ...

Konfigurasi plugin

Kamu dapat mengaktifkan atau menonaktifkan plugin dalam konfigurasi penjadwal. Jika kamu menggunakan Kubernetes v1.18 atau yang lebih baru, kebanyakan plugin-plugin penjadwalan sudah digunakan dan diaktifkan secara bawaan.

Selain plugin-plugin bawaan, kamu juga dapat mengimplementasikan plugin-plugin penjadwalan kamu sendiri dan mengonfigurasinya bersama-sama dengan plugin-plugin bawaan. Kamu bisa mengunjungi plugin-plugin penjadwalan untuk informasi lebih lanjut.

Jika kamu menggunakan Kubernetes v1.18 atau yang lebih baru, kamu dapat mengonfigurasi sekumpulan plugin sebagai profil penjadwal dan kemudian menetapkan beberapa profil agar sesuai dengan berbagai jenis beban kerja. Pelajari lebih lanjut di multi profil.

3 - Penyetelan Kinerja Penjadwal

FEATURE STATE: Kubernetes v1.14 [beta]

kube-scheduler merupakan penjadwal (scheduler) Kubernetes bawaan yang bertanggung jawab terhadap penempatan Pod-Pod pada seluruh Node di dalam sebuah klaster.

Node-Node di dalam klaster yang sesuai dengan syarat-syarat penjadwalan dari sebuah Pod disebut sebagai Node-Node layak (feasible). Penjadwal mencari Node-Node layak untuk sebuah Pod dan kemudian menjalankan fungsi-fungsi untuk menskor Node-Node tersebut, memilih sebuah Node dengan skor tertinggi di antara Node-Node layak lainnya, di mana Pod akan dijalankan. Penjadwal kemudian memberitahu API server soal keputusan ini melalui sebuah proses yang disebut Binding.

Laman ini menjelaskan optimasi penyetelan (tuning) kinerja yang relevan untuk klaster Kubernetes berskala besar.

Pada klaster berskala besar, kamu bisa menyetel perilaku penjadwal untuk menyeimbangkan hasil akhir penjadwalan antara latensi (seberapa cepat Pod-Pod baru ditempatkan) dan akurasi (seberapa akurat penjadwal membuat keputusan penjadwalan yang tepat).

Kamu bisa mengonfigurasi setelan ini melalui pengaturan percentageOfNodesToScore pada kube-scheduler. Pengaturan KubeSchedulerConfiguration ini menentukan sebuah ambang batas untuk penjadwalan Node-Node di dalam klaster kamu.

Pengaturan Ambang Batas

Opsi percentageOfNodesToScore menerima semua angka numerik antara 0 dan 100. Angka 0 adalah angka khusus yang menandakan bahwa kube-scheduler harus menggunakan nilai bawaan. Jika kamu mengatur percentageOfNodesToScore dengan angka di atas 100, kube-scheduler akan membulatkan ke bawah menjadi 100.

Untuk mengubah angkanya, sunting berkas konfigurasi kube-scheduler (biasanya /etc/kubernetes/config/kube-scheduler.yaml), lalu ulang kembali kube-scheduler.

Setelah kamu selesai menyunting, jalankan perintah

kubectl get componentstatuses

untuk memverifikasi komponen kube-scheduler berjalan dengan baik (healthy). Keluarannya kira-kira seperti ini:

NAME                 STATUS    MESSAGE             ERROR
controller-manager   Healthy   ok
scheduler            Healthy   ok
...

Ambang Batas Penskoran Node

Untuk meningkatan kinerja penjadwalan, kube-scheduler dapat berhenti mencari Node-Node yang layak saat sudah berhasil menemukannya. Pada klaster berskala besar, hal ini menghemat waktu dibandingkan dengan pendekatan awam yang mengecek setiap Node.

Kamu bisa mengatur ambang batas untuk menentukan berapa banyak jumlah Node minimal yang dibutuhkan, sebagai persentase bagian dari seluruh Node di dalam klaster kamu. kube-scheduler akan mengubahnya menjadi bilangan bulat berisi jumlah Node. Saat penjadwalan, jika kube-scheduler mengidentifikasi cukup banyak Node-Node layak untuk melewati jumlah persentase yang diatur, maka kube-scheduler akan berhenti mencari Node-Node layak dan lanjut ke [fase penskoran] (/id/docs/concepts/scheduling/kube-scheduler/#kube-scheduler-implementation).

Bagaimana penjadwal mengecek Node menjelaskan proses ini secara detail.

Ambang Batas Bawaan

Jika kamu tidak mengatur sebuah ambang batas, maka Kubernetes akan menghitung sebuah nilai menggunakan pendekatan linier, yaitu 50% untuk klaster dengan 100 Node, serta 10% untuk klaster dengan 5000 Node.

Artinya, kube-scheduler selalu menskor paling tidak 5% dari klaster kamu, terlepas dari seberapa besar klasternya, kecuali kamu secara eksplisit mengatur percentageOfNodesToScore menjadi lebih kecil dari 5.

Jika kamu ingin penjadwal untuk memasukkan seluruh Node di dalam klaster ke dalam penskoran, maka aturlah percentageOfNodesToScore menjadi 100.

Contoh

Contoh konfigurasi di bawah ini mengatur percentageOfNodesToScore menjadi 50%.

apiVersion: kubescheduler.config.k8s.io/v1alpha1
kind: KubeSchedulerConfiguration
algorithmSource:
  provider: DefaultProvider

...

percentageOfNodesToScore: 50

Menyetel percentageOfNodesToScore

percentageOfNodesToScore merupakan angka 1 sampai 100 dengan nilai bawaan yang dihitung berdasarkan ukuran klaster. Di sini juga terdapat batas bawah yang telah ditetapkan, yaitu 50 Node.

Catatan:

Pada klaster dengan kurang dari 50 Node layak, penjadwal masih terus memeriksa seluruh Node karena Node-Node layak belum mencukupi supaya penjadwal dapat menghentikan proses pencarian lebih awal.

Pada klaster kecil, jika kamu mengatur percentageOfNodesToScore dengan angka kecil, pengaturan ini hampir atau sama sekali tidak berpengaruh, karena alasan yang sama.

Jika klaster kamu punya ratusan Node, gunakan angka bawaan untuk opsi konfigurasi ini. Mengubah angkanya kemungkinan besar tidak akan mengubah kinerja penjadwal secara berarti.

Sebuah catatan penting yang perlu dipertimbangkan saat mengatur angka ini adalah ketika klaster dengan jumlah Node sedikit diperiksa untuk kelayakan, beberapa Node tidak dikirim untuk diskor bagi sebuah Pod. Hasilnya, sebuah Node yang mungkin memiliki nilai lebih tinggi untuk menjalankan Pod tersebut bisa saja tidak diteruskan ke fase penskoran. Hal ini berdampak pada penempatan Pod yang kurang ideal.

Kamu sebaiknya menghindari pengaturan percentageOfNodesToScore menjadi sangat rendah, agar kube-scheduler tidak seringkali membuat keputusan penempatan Pod yang buruk. Hindari pengaturan persentase di bawah 10%, kecuali throughput penjadwal sangat penting untuk aplikasi kamu dan skor dari Node tidak begitu penting. Dalam kata lain, kamu memilih untuk menjalankan Pod pada Node manapun selama Node tersebut layak.

Bagaimana Penjadwal Mengecek Node

Bagian ini ditujukan untuk kamu yang ingin mengerti bagaimana fitur ini bekerja secara internal.

Untuk memberikan semua Node di dalam klaster sebuah kesempatan yang adil untuk dipertimbangkan dalam menjalankan Pod, penjadwal mengecek Node satu persatu secara round robin. Kamu dapat membayangkan Node-Node ada di dalam sebuah array. Penjadwal mulai dari indeks array pertama dan mengecek kelayakan dari Node sampai jumlahnya telah mencukupi sesuai dengan percentageOfNodesToScore. Untuk Pod berikutnya, penjadwal melanjutkan dari indeks array Node yang terhenti ketika memeriksa kelayakan Node-Node untuk Pod sebelumnya.

Jika Node-Node berada di beberapa zona, maka penjadwal akan mengecek Node satu persatu pada seluruh zona untuk memastikan bahwa Node-Node dari zona berbeda masuk dalam pertimbangan kelayakan. Sebagai contoh, ada 6 Node di dalam 2 zona:

Zona 1: Node 1, Node 2, Node 3, Node 4
Zona 2: Node 5, Node 6

Penjadwal mempertimbangkan kelayakan dari Node-Node tersebut dengan urutan berikut:

Node 1, Node 5, Node 2, Node 6, Node 3, Node 4

Setelah semua Node telah dicek, penjadwal akan kembali pada Node 1.