Taint dan Toleration
Afinitas Node, seperti yang dideskripsikan di sini, adalah salah satu properti dari Pod yang menyebabkan pod tersebut memiliki preferensi untuk ditempatkan di sekelompok Node tertentu (preferensi ini dapat berupa soft constraints atau hard constraints yang harus dipenuhi). Taint merupakan kebalikan dari afinitas -- properti ini akan menyebabkan Pod memiliki preferensi untuk tidak ditempatkan pada sekelompok Node tertentu.
Taint dan toleration bekerja sama untuk memastikan Pod dijadwalkan pada Node yang sesuai. Satu atau lebih taint akan diterapkan pada suatu node; hal ini akan menyebabkan node tidak akan menerima pod yang tidak mengikuti taint yang sudah diterapkan.
Konsep
Kamu dapat menambahkan taint pada sebuah node dengan menggunakan perintah kubectl taint. Misalnya,
kubectl taint nodes node1 key=value:NoSchedule
akan menerapkan taint pada node node1
. Taint tersebut memiliki key key
, value value
,
dan effect taint NoSchedule
. Hal ini artinya pod yang ada tidak akan dapat dijadwalkan pada node1
kecuali memiliki taint yang sesuai.
Untuk menghilangkan taint yang ditambahkan dengan perintah di atas, kamu dapat menggunakan perintah di bawah ini:
kubectl taint nodes node1 key:NoSchedule-
Kamu dapat memberikan spesifikasi toleration untuk pod pada bagian PodSpec.
Kedua toleration yang diterapkan di bawa ini "sesuai" dengan taint yang
taint yang dibuat dengan perintah kubectl taint
di atas, sehingga sebuah pod
dengan toleration yang sudah didefinisikan akan mampu di-schedule ke node node
:
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
tolerations:
- key: "key"
operator: "Exists"
effect: "NoSchedule"
Sebuah toleration "sesuai" dengan sebuah taint jika key dan efek yang ditimbulkan sama:
operator
dianggapExists
(pada kasus dimana tidak adavalue
yang diberikan), atauoperator
dianggapEqual
danvalue
yang ada sama
Operator
bernilai Equal
secara default jika tidak diberikan spesifikasi khusus.
Catatan:Terdapat dua kasus khusus:
- Sebuah
key
dengan operatorExists
akan sesuai dengan semua key, value, dan effect yang ada. Dengan kata lain, tolaration ini akan menerima semua hal yang diberikan.tolerations: - operator: "Exists"
- Sebuah
effect
yang kosong akan dianggap sesuai dengan semua effect dengan keykey
.tolerations: - key: "key" operator: "Exists"
Contoh yang diberikan di atas menggunakan effect
untuk NoSchedule
.
Alternatif lain yang dapat digunakan adalah effect
untuk PreferNoSchedule
.
PreferNoSchedule
merupakan "preferensi" yang lebih fleksibel dari NoSchedule
--
sistem akan mencoba untuk tidak menempatkan pod yang tidak menoleransi taint
pada node, tapi hal ini bukan merupakan sesuatu yang harus dipenuhi. Jenis ketiga
dari effect
adalah NoExecute
, akan dijelaskan selanjutnya.
Kamu dapat menerapkan beberapa taint sekaligus pada node atau beberapa toleration sekaligus pada sebuah pod. Mekanisme Kubernetes dapat memproses beberapa taint dan toleration sekaligus sama halnya seperti sebuah filter: memulai dengan taint yang ada pada node, kemudian mengabaikan taint yang sesuai pada pod yang memiliki toleration yang sesuai; kemudian taint yang diterapkan pada pod yang sudah disaring tadi akan menghasilkan suatu effect pada pod. Secara khusus:
- jika terdapat taint yang tidak tersaring dengan effect
NoSchedule
maka Kubernetes tidak akan menempatkan pod pada node tersebut - jika tidak terdapat taint yang tidak tersaring dengan effect
NoSchedule
tapi terdapat setidaknya satu taint yang tidak tersaring dengan effectPreferNoSchedule
maka Kubernetes akan mencoba untuk tidak akan menempatkan pod pada node tersebut - jika terdapat taint yang tidak tersaring dengan effect
NoExecute
maka pod akan berada dalam kondisi evicted dari node (jika pod tersebut sudah terlanjur ditempatkan pada node tersebut), dan tidak akan di-schedule lagi pada node tersebut.
Sebagai contoh, bayangkan kamu memberikan taint pada node sebagai berikut:
kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value1:NoExecute
kubectl taint nodes node1 key2=value2:NoSchedule
Dan pod memiliki dua toleration:
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
Pada kasus ini, pod tidak akan di-schedule pada node, karena tidak ada toleration yang sesuai dengan taint ketiga. Akan tetapi, pod yang sebelumnya sudah dijalankan di node dimana taint ditambahkan akan tetap jalan, karena taint ketiga merupakan taint yang tidak ditoleransi oleh pod.
Pada umumnya, jika sebuah taint memiliki effect NoExecute
ditambahkan pada node,
maka semua pod yang tidak menoleransi taint tersebut akan berada dalam state
evicted secara langsung, dan semua pod yang menoleransi taint tersebut
tidak akan berjalan seperti biasanya (tidak dalam state evicted). Meskipun demikian,
toleration dengan effect NoExecute
dapat dispesfikasikan sebagai field opsional
tolerationSeconds
yang memberikan perintah berapa lama suatu pod akan berada
pada node apabila sebuah taint ditambahkan. Contohnya:
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
tolerationSeconds: 3600
ini berarti apabila sebuah pod sedang dalam berada dalam state running, kemudian sebuah taint yang sesuai ditambahkan pada node, maka pod tersebut akan tetap berada di dalam node untuk periode 3600 detik sebelum state-nya berubah menjadi evicted. Jika taint dihapus sebelum periode tersebut, maka pod tetap berjalan sebagaimana mestinya.
Contoh Penggunaan
Taint dan toleration adalah mekanisme fleksibel yang digunakan untuk memaksa pod agar tidak dijadwalkan pada node-node tertentu atau mengubah state pod menjadi evicted. Berikut adalah beberapa contoh penggunaannya:
-
Node-Node yang Sifatnya Dedicated: Jika kamu ingin menggunakan sekumpulan node dengan penggunaan eksklusif dari sekumpulan pengguna, kamu dapat menambahkan taint pada node-node tersebut (misalnya,
kubectl taint nodes nodename dedicated=groupName:NoSchedule
) dan kemudian menambahkan toleration yang sesuai pada pod-pod yang berada di dalamnya (hal ini dapat dilakukan dengan mudah dengan cara menulis admission controller yang bersifat khusus). Pod-pod dengan toleration nantinya akan diperbolehkannya untuk menggunakan node yang sudah di-taint (atau dengan kata lain didedikasikan penggunaannya) maupun node lain yang ada di dalam klaster. Jika kamu ingin mendedikasikan node khusus yang hanya digunakan oleh pod-pod tadi serta memastikan pod-pod tadi hanya menggunakan node yang didedikasikan, maka kamu harus menambahkan sebuah label yang serupa dengan taint yang diberikan pada sekelompok node (misalnya,dedicated=groupName
), dan admission controller sebaiknya menambahkan afininitas node untuk memastikan pod-pod tadi hanya dijadwalkan pada node dengan labeldedicated=groupName
. -
Node-Node dengan Perangkat Keras Khusus: Pada suatu klaster dimana sebagian kecuali node memiliki perangkat keras khusus (misalnya GPU), kita ingin memastikan hanya pod-pod yang membutuhkan GPU saja yang dijadwalkan di node dengan GPU. Hal ini dapat dilakukan dengan memberikan taint pada node yang memiliki perangkat keras khusus (misalnya,
kubectl taint nodes nodename special=true:NoSchedule
ataukubectl taint nodes nodename special=true:PreferNoSchedule
) serta menambahkan toleration yang sesuai pada pod yang menggunakan node dengan perangkat keras khusus. Seperti halnya pada kebutuhan dedicated node, hal ini dapat dilakukan dengan mudah dengan cara menulis admission controller yang bersifat khusus. Misalnya, kita dapat menggunakan Extended Resource untuk merepresentasikan perangkat keras khusus, kemudian taint node dengan perangkat keras khusus dengan nama extended resource dan jalankan admission controller ExtendedResourceToleration. Setelah itu, karena node yang ada sudah di-taint, maka tidak akan ada pod yang tidak memiliki toleration yang akan dijadwalkan pada node tersebut_. Meskipun begitu, ketika kamu membuat suatu _pod_ yang membutuhkan _extended resource_, maka _admission controller_ dariExtendedResourceToleration
akan mengoreksi _toleration_ sehingga _pod_ tersebut dapat dijadwalkan pada _node_ dengan perangkat keras khusus. Dengan demikian, kamu tidak perlu menambahkan _toleration_ secara manual pada pod yang ada. -
Eviction berbasis Taint (fitur beta): Konfigurasi eviction per pod yang terjadi ketika pod mengalami gangguan, hal ini akan dibahas lebih lanjut di bagian selanjutnya.
Eviction berbasis Taint
Sebelumnya, kita sudah pernah membahas soal effect taint NoExecute
,
yang memengaruhi pod yang sudah dijalankan dengan cara sebagai berikut:
- pod yang tidak menoleransi taint akan segera diubah state-nya menjadi evicted
- pod yang menoleransi taint yang tidak menspesifikasikan
tolerationSeconds
pada spesifikasi toleration yang ada akan tetap berada di dalam node tanpa adanya batas waktu tertentu - pod yang menoleransi taint yang menspesifikasikan
tolerationSeconds
spesifikasi toleration yang ada akan tetap berada di dalam node hingga batas waktu tertentu
Sebagai tambahan, Kubernetes 1.6 memperkenalkan dukungan alfa untuk merepresentasikan node yang bermasalah. Dengan kata lain, node controller akan secara otomatis memberikan taint pada sebuah node apabila node tersebut memenuhi kriteria tertentu. Berikut merupakan taint yang secara default disediakan:
node.kubernetes.io/not-ready
: Node berada dalam state not ready. Hal ini terjadi apabila value dari NodeConditionReady
adalah "False
".node.kubernetes.io/unreachable
: Node berada dalam state unreachable dari node controller Hal ini terjadi apabila value dari NodeConditionReady
adalah "Unknown
".node.kubernetes.io/out-of-disk
: Node kehabisan kapasitas disk.node.kubernetes.io/memory-pressure
: Node berada diambang kapasitas memori.node.kubernetes.io/disk-pressure
: Node berada diambang kapasitas disk.node.kubernetes.io/network-unavailable
: Jaringan pada Node bersifat unavailable.node.kubernetes.io/unschedulable
: Node tidak dapat dijadwalkan.node.cloudprovider.kubernetes.io/uninitialized
: Ketika kubelet dijalankan dengan penyedia layanan cloud "eksternal", taint ini akan diterapkan pada node untuk menandai node tersebut tidak digunakan. Setelah kontroler dari cloud-controller-manager melakukan inisiasi node tersebut, maka kubelet akan menghapus taint yang ada.
Pada versi 1.13, fitur TaintBasedEvictions
diubah menjadi beta dan diaktifkan secara default,
dengan demikian taint-taint tersebut secara otomatis ditambahkan oleh NodeController (atau kubelet)
dan logika normal untuk melakukan eviction pada pod dari suatu node tertentu berdasarkan value
dari Ready yang ada pada NodeCondition dinonaktifkan.
Catatan: Untuk menjaga perilaku rate limiting yang ada pada eviction pod apabila node mengalami masalah, sistem sebenarnya menambahkan taint dalam bentuk rate limiter. Hal ini mencegah eviction besar-besaran pada pod pada skenario dimana master menjadi terpisah dari node lainnya.
Fitur beta ini, bersamaan dengan tolerationSeconds
, mengizinkan sebuah pod
untuk menspesifikasikan berapa lama pod harus tetap sesuai dengan sebuah node
apabila node tersebut bermasalah.
Misalnya, sebuah aplikasi dengan banyak state lokal akan lebih baik untuk tetap berada di suatu node pada saat terjadi partisi jaringan, dengan harapan partisi jaringan tersebut dapat diselesaikan dan mekanisme eviction pod tidak akan dilakukan. Toleration yang ditambahkan akan berbentuk sebagai berikut:
tolerations:
- key: "node.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 6000
Perhatikan bahwa Kubernetes secara otomatis menambahkan toleration untuk
node.kubernetes.io/not-ready
dengan tolerationSeconds=300
kecuali konfigurasi lain disediakan oleh pengguna.
Kubernetes juga secara otomatis menambahkan toleration untuk
node.kubernetes.io/unreachable
dengan tolerationSeconds=300
kecuali konfigurasi lain disediakan oleh pengguna.
Toleration yang ditambahkan secara otomatis ini menjamin bahwa perilaku default dari suatu pod adalah tetap bertahan selama 5 menit pada node apabila salah satu masalah terdeteksi. Kedua toleration default tadi ditambahkan oleh DefaultTolerationSeconds admission controller.
Pod-pod pada DaemonSet dibuat dengan toleration
NoExecute
untuk taint tanpa tolerationSeconds
:
node.kubernetes.io/unreachable
node.kubernetes.io/not-ready
Hal ini menjamin pod-pod yang merupakan bagian dari DaemonSet tidak pernah berada di dalam state evicted apabila terjadi permasalahan pada node.
Taint pada Node berdasarkan Kondisi Tertentu
Pada versi 1.12, fitur TaintNodesByCondition
menjadi fitur beta, dengan demikian lifecycle
dari kontroler node akan secara otomatis menambahkan taint sesuai dengan kondisi node.
Hal yang sama juga terjadi pada scheduler, scheduler tidak bertugas memeriksa kondisi node
tetapi kondisi taint. Hal ini memastikan bahwa kondisi node tidak memengaruhi apa
yang dijadwalkan di node. Pengguna dapat memilih untuk mengabaikan beberapa permasalahan yang
ada pada node (yang direpresentasikan oleh kondisi Node) dengan menambahkan toleration Pod NoSchedule
.
Sedangkan taint dengan effect NoExecute
dikendalikan oleh TaintBasedEviction
yang merupakan
fitur beta yang diaktifkan secara default oleh Kubernetes sejak versi 1.13.
Sejak Kubernetes versi 1.8, kontroler DaemonSet akan secara otomatis
menambahkan toleration NoSchedule
pada semua daemon untuk menjaga
fungsionalitas DaemonSet.
node.kubernetes.io/memory-pressure
node.kubernetes.io/disk-pressure
node.kubernetes.io/out-of-disk
(hanya untuk pod yang bersifat critical)node.kubernetes.io/unschedulable
(versi 1.10 atau yang lebih baru)node.kubernetes.io/network-unavailable
(hanya untuk jaringan host)
Menambahkan toleration ini menjamin backward compatibility. Kamu juga dapat menambahkan toleration lain pada DaemonSet.