Taint / Tolerationとは
Taintとは、PodをNodeへスケジューリングさせないための機能である。
Node Affinityとは逆の機能になる。
TaintsをNodeに設定し、PodにはTolerationsを設定することができる。
これらにはkey, valueなどを設定し、TaintsとTolerationsの条件がマッチした際に、PodはNodeにスケジューリングされるようになる。
それぞれ1つ、または複数のTaints、Tolerationsを設定することができる。
目次
Taints
Taintsは、以下の3つを使って条件をセットする。
- key
- value
- effect
例えば、key: app
、value: batch
、effect: NoSchedule
というように、Node、Podにそれぞれ設定する。key, valueはそのままセットした値が条件比較で使われる。effectについては次項で説明する。
effectとは
effectとは、条件をどのように受け入れるのかの制約である。
effectは以下の3種類がある。
- NoSchedule
- TaintとTolerationがマッチした場合にのみに、PodがNodeにスケジューリングされる。
- PreferNoSchedule
- Nodeは条件が一致しないPodを基本的には拒否するが、該当のPodがどのNodeにもスケジューリングされず行き場所がなくなっている場合、PreferNoScheduleが設定されたNodeは、条件にマッチしなくてもそのPodを受け入れてスケジューリングする。
- NoExecute
- TaintとTolerationがマッチした場合にのみに、PodがNodeにスケジューリングされる。
- このTaintがNodeにセットされたときに、条件に合わないPodが既にスケジューリングされていた場合、そのPodはただちにNodeから追い出される。つまり、起動中のPodにも影響が出る。
説明するのが中々難しいので、実際に検証してみる。
ハンズオン
以下のminikubeというnodeにTaintを設定し、Tolerationを設定したPodをスケジューリングしてみる。
$ sudo kubectl get nodes
NAME STATUS ROLES AGE VERSION
minikube Ready master 3d v1.14.3
NoScheduleの挙動を検証
Taintを設定前の状態
nodeをdescribeしてみると、Taintsが<none>
になっている。
$ sudo kubectl describe node minikube | grep Taints
Taints: <none>
Taintを設定
key: app
、value: batch
、effect: NoSchedule
というTaintを設定する。
$ sudo kubectl taint nodes minikube app=batch:NoSchedule
node/minikube tainted
Taintを設定後の状態
nodeをdescribeすると、Taintsが設定されていることが確認できる。
$ sudo kubectl describe nodes minikube | grep Taints
Taints: app=batch:NoSchedule
Tolerationの設定
apiVersion: v1
kind: Pod
metadata:
name: sample-pod
spec:
containers:
- name: sample-container
image: nginx
tolerations:
# TaintのKeyを指定
- key: "app"
# Equal or Exists。Default: Equal。
operator: "Equal"
# TaintのValueを指定。operatorがExistsの場合、valueは省略可能。
# operatorにExistsを設定した場合、keyとeffectのみが一致したNodeを探すことになる。
value: "batch"
# Effectを設定。省略した場合、全てのEffectにマッチする。
effect: "NoSchedule"
# effectにNoExecuteを設定した場合、PodがNodeから追い出されるまでの時間を設定する。
# 0や負の数を設定した場合は即座に追い出される。
#tolerationSeconds: 0
条件が一致した場合
Podがスケジューリングされていることを確認する。
$ sudo kubectl get pod
NAME READY STATUS RESTARTS AGE
sample-pod 1/1 Running 0 4s
$ sudo kubectl describe pod sample-pod
# **snip**
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 25s default-scheduler Successfully assigned default/sample-pod to minikube
Normal Pulling 25s kubelet, minikube Pulling image "nginx"
Normal Pulled 22s kubelet, minikube Successfully pulled image "nginx"
Normal Created 22s kubelet, minikube Created container sample-container
Normal Started 22s kubelet, minikube Started container sample-container
条件が一致しない場合
Nodeにapp=batch:NoSchedule
というTaintを設定、
Podにapp=api:NoSchedule
というTolerationを設定した場合、Podはスケジューリング先のNodeが存在しないため、以下のようになる。
$ sudo kubectl get pod
NAME READY STATUS RESTARTS AGE
sample-pod 0/1 Pending 0 10s
$ sudo kubectl describe pod sample-pod
# **snip**
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 5s (x2 over 5s) default-scheduler 0/1 nodes are available: 1 node(s) had taints that the pod didn't tolerate.
PreferNoScheduleの挙動を検証
NodeにTaintの設定
app=batch:PreferNoSchedule
というTaintをminikube Nodeに設定する。
$ sudo kubectl taint nodes minikube app=batch:PreferNoSchedule
node/minikube tainted
確認
$ sudo kubectl describe node minikube | grep Taint
Taints: app=batch:PreferNoSchedule
PodにTolerationの設定
以下のTolerationをPodに設定する。
apiVersion: v1
kind: Pod
metadata:
name: sample-pod
spec:
containers:
- name: sample-container
image: nginx
tolerations:
# TaintのKeyを指定
- key: "sample"
# Equal or Exists。Default: Equal。
operator: "Equal"
# TaintのValueを指定。operatorがExistsの場合、valueは省略可能。
value: "ThisIsASample"
# Effectを設定。省略した場合、全てのEffectにマッチする。
effect: "NoSchedule"
apply
$ sudo kubectl apply -f pod.yml
pod/sample-pod configured
```
### スケジューリング状態確認
Taintは`app=batch:PreferNoSchedule`、PodのTolerationsは`sample=ThisIsASample:NoSchedule`で一致していないが、このPodは他に行き場所がないため、minikubeのNodeにスケジューリングされた。
```shell-session
$ sudo kubectl get pod
NAME READY STATUS RESTARTS AGE
sample-pod 1/1 Running 0 14s
```
```shell-session
$ sudo kubectl describe pod sample-pod
# **snip**
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 25s default-scheduler Successfully assigned default/sample-pod to minikube
Normal Pulling 24s kubelet, minikube Pulling image "nginx"
Normal Pulled 21s kubelet, minikube Successfully pulled image "nginx"
Normal Created 21s kubelet, minikube Created container sample-container
Normal Started 21s kubelet, minikube Started container sample-container
```
## NoExecuteの挙動を検証
先述の[PreferNoScheduleの挙動を検証](#prefernoscheduleの挙動を検証)の環境をそのまま利用する。
### 作業前のNodeを確認
先程セットしたTaintがNodeにセットされていることを確認。
```shell-session
$ sudo kubectl describe node minikube | grep Taints
Taints: app=batch:PreferNoSchedule
```
### 作業前のPodを確認
先程作成したPodが起動していることを確認。
```shell-session
$ sudo kubectl get pod
NAME READY STATUS RESTARTS AGE
sample-pod 1/1 Running 0 52s
```
### Taintを削除
先程セットしたTaintを削除する。
```shell-session
$ sudo kubectl taint nodes minikube app-
node/minikube untainted
```
### Taintを設定
minikubeのNodeに`app=batch:NoExecute`というTaintを設定する。
```shell-session
$ sudo kubectl taint nodes minikube app=batch:NoExecute
node/minikube tainted
```
### 作業後のNodeを確認
```shell-session
$ sudo kubectl describe node minikube | grep Taints
Taints: app=batch:NoExecute
```
### 作業後のPodを確認
先述の[PreferNoScheduleの挙動を検証](#prefernoscheduleの挙動を検証)で作成したPodは、条件に合わないため、新たな`NoExecute`のTaintをセットしたら、ただちに破棄された。
```shell-session
$ sudo kubectl get pod
NAME READY STATUS RESTARTS AGE
sample-pod 0/1 Terminating 0 83s
```
ちなみに、Taintを`NoSchedule`もしくは`PreferNoSchedule`にセットし直した場合は、既存のPodは破棄されなかった。
```shell-session
$ sudo kubectl taint nodes minikube app=batch:NoSchedule
$ sudo kubectl taint nodes minikube app=batch:PreferNoSchedule
```
## 関連記事
- [【KubernetesのAffinity】その1 - Node Affinityの使い方](https://qiita.com/Esfahan/items/aeddf89428441ec3437c)
- [【KubernetesのAffinity】その2 - Pod Affinity / Pod Anti-Affinityの使い方](https://qiita.com/Esfahan/items/a673317a29ca407e5ae7)
## 参考
- [Taints and Tolerations](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/)
- [Kubernetes道場 18日目 - Affinity / Anti-Affinity / Taint / Tolerationについて](https://cstoku.dev/posts/2018/k8sdojo-18/#taint-toleration)
- [KubernetesのTaintsとTolerationsについて](https://qiita.com/sheepland/items/8fedae15e157c102757f)