website/content/id/docs/concepts/scheduling-eviction/taint-and-toleration.md

315 lines
15 KiB
Markdown

---
title: Taint dan Toleration
content_type: concept
weight: 40
---
<!-- overview -->
Afinitas Node, seperti yang dideskripsikan [di sini](/id/docs/concepts/configuration/assign-pod-node/#node-affinity-beta-feature),
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.
<!-- body -->
## Konsep
Kamu dapat menambahkan _taint_ pada sebuah _node_ dengan menggunakan perintah [kubectl taint](/docs/reference/generated/kubectl/kubectl-commands#taint).
Misalnya,
```shell
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:
```shell
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`:
```yaml
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
```
```yaml
tolerations:
- key: "key"
operator: "Exists"
effect: "NoSchedule"
```
Sebuah _toleration_ "sesuai" dengan sebuah _taint_ jika _key_ dan efek yang
ditimbulkan sama:
* `operator` dianggap `Exists` (pada kasus dimana tidak ada `value` yang diberikan), atau
* `operator` dianggap `Equal` dan `value` yang ada sama
`Operator` bernilai `Equal` secara _default_ jika tidak diberikan spesifikasi khusus.
{{< note >}}
Terdapat dua kasus khusus:
* Sebuah `key` dengan operator `Exists` akan sesuai dengan semua _key_, _value_, dan _effect_ yang ada.
Dengan kata lain, _tolaration_ ini akan menerima semua hal yang diberikan.
```yaml
tolerations:
- operator: "Exists"
```
* Sebuah `effect` yang kosong akan dianggap sesuai dengan semua _effect_ dengan _key_ `key`.
```yaml
tolerations:
- key: "key"
operator: "Exists"
```
{{< /note >}}
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
_effect_ `PreferNoSchedule` 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:
```shell
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_:
```yaml
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:
```yaml
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_](/docs/reference/access-authn-authz/admission-controllers/) 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 _label_ `dedicated=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` atau
`kubectl 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_](/docs/reference/access-authn-authz/admission-controllers/) yang
bersifat khusus. Misalnya, kita dapat menggunakan [_Extended Resource_](/id/docs/concepts/configuration/manage-compute-resources-container/#extended-resources)
untuk merepresentasikan perangkat keras khusus, kemudian _taint_ _node_ dengan perangkat keras khusus
dengan nama _extended resource_ dan jalankan _admission controller_
[ExtendedResourceToleration](/docs/reference/access-authn-authz/admission-controllers/#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_ dari `ExtendedResourceToleration` 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 _NodeCondition_ `Ready` adalah "`False`".
* `node.kubernetes.io/unreachable`: _Node_ berada dalam _state_ _unreachable_ dari _node controller_
Hal ini terjadi apabila _value_ dari _NodeCondition_ `Ready` 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.
{{< note >}}
Untuk menjaga perilaku [_rate limiting_](/id/docs/concepts/architecture/nodes/) 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.
{{< /note >}}
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:
```yaml
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_](https://git.k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds).
_Pod-pod_ pada [DaemonSet](/id/docs/concepts/workloads/controllers/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.