21
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

KubernetesのTaint / Tolerationの使い方

Posted at

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: appvalue: batcheffect: 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: appvalue: batcheffect: 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の設定

pod.yml
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に設定する。

pod.yml
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)
21
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?