# Taint dan Toleration

LLMS index: [llms.txt](/llms.txt)

---

<!-- 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.


<div class="alert alert-info" role="note"><h4 class="alert-heading">Catatan:</h4><p>Terdapat dua kasus khusus:</p>
<ul>
<li>Sebuah <code>key</code> dengan operator <code>Exists</code> akan sesuai dengan semua <em>key</em>, <em>value</em>, dan <em>effect</em> yang ada.
Dengan kata lain, <em>tolaration</em> ini akan menerima semua hal yang diberikan.</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">tolerations</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl">- <span class="nt">operator</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Exists&#34;</span><span class="w">
</span></span></span></code></pre></div><ul>
<li>Sebuah <code>effect</code> yang kosong akan dianggap sesuai dengan semua <em>effect</em> dengan <em>key</em> <code>key</code>.</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">tolerations</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl">- <span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;key&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">operator</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Exists&#34;</span><span class="w">
</span></span></span></code></pre></div></div>


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.


<div class="alert alert-info" role="note"><h4 class="alert-heading">Catatan:</h4>Untuk menjaga perilaku <a href="/id/docs/concepts/architecture/nodes/"><em>rate limiting</em></a> yang
ada pada <em>eviction</em> <em>pod</em> apabila <em>node</em> mengalami masalah, sistem sebenarnya menambahkan
<em>taint</em> dalam bentuk <em>rate limiter</em>. Hal ini mencegah <em>eviction</em> besar-besaran pada <em>pod</em>
pada skenario dimana master menjadi terpisah dari <em>node</em> lainnya.</div>


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.
