Help us understand the problem. What is going on with this article?

KubernetesのTaintsとTolerationsについて

More than 1 year has passed since last update.

TaintsとTolerationsについて

Kubernetesには最初、特定のnodeに特定のpodをscheduleする方法としてnode selectorを使う方法があった。(node selectorの他にも特定のnodeに特定のpodをscheduleするための仕組みとしてNode Affinityがある)
しかし後からもっと柔軟にscheduleするためのメカニズムが導入された。
それがTaintsTolerations
(taintは"汚れ"という意味。tolerationは"容認"という意味。つまり"汚れ"を"容認"できるならscheduleできる仕組み)

TaintsTolerationsNode SelectorNode Affinityと似ているが性質は正反対で、
Node SelectorNode Affinityが特定のnodeに特定のpodをscheduleするための仕組みに対し、
TaintsTolerationsは特定のnodeにpodをscheduleしないための仕組みだ。
TaintsTolerationsは互いに協調しあい、podが不適当なnodeにscheduleされないようにする。
Node Affinityなどの場合には、それらが未指定の場合はどこのNodeにでもscheduleされてしまうが、TaintsTolerationsの場合は指定しない限りそのNodeにscheduleされることはない。
1つもしくは複数のTaintsをnodeに設定することができ、podには1つもしくは複数のtolerationsを設定することができる。
例えば、production用のNodeには他のPodをscheduleさせたくないとか、GPUやFPGAなどの特殊なデバイスを持つNodeには特定のPod以外はscheduleさせたくないとかいった場合に有効。

例えばCLIからnodeにTaintsを設定する場合、
kubectl taint nodes node1 key=value:effect
のような形式で実行する。
Taintskeyvalueeffectの3つで構成されている。
(effectの説明は後でするとして)もし以下のように実行した場合、
kubectl taint nodes node1 app=batch:NoSchedule
Tolerationsにapp=batchをもったpodではないとこのnodeにpodをscheduleできなくなる。

例えば、

$ kubectl describe node master.k8s
Name:         master.k8s
Role:
Labels:       beta.kubernetes.io/arch=amd64
              beta.kubernetes.io/os=linux
              kubernetes.io/hostname=master.k8s
              node-role.kubernetes.io/master=
Annotations:  node.alpha.kubernetes.io/ttl=0
              volumes.kubernetes.io/controller-managed-attach-detach=true
Taints:       app=batch:NoSchedule

この場合、app=batch:NoScheduleがTaints。
Taintsは<key>=<value>:<effect>で構成されていて、
app がkey、valueはbatch、effectがNoSchedule

effectの種類とその効果

effectには以下の3種類がある。(これらのeffectはTaintsでもTolerationsでも使用できる)

Effectの種類 概要
NoSchedule taintが許容できなければnodeへscheduleさせない
(すでにscheduleされているPodはそのまま)
PreferNoSchedule taintが許容できるnodeを探し、なければ許容できないnodeであってもscheduleする
NoExecute scheduling時に影響があるNoSchedulePreferNoScheduleと違って、
NoExecuteはnode上で実行中のpodへも影響がある。
もしNoExecuteエフェクトをもったtaintをnodeへ追加した場合で
かつpodがそのtaintを許容できない場合、
そのpodは停止される(つまりnode上から追い出される )。
$ kubectl describe pod hoge-pod
...
Tolerations:    app=batch:NoSchedule
...

app=batch:NoScheduleというTolerationをもっているので上記のnodeへscheduleできる。

ちなみにnode.alpha.kubernetes.io/notReady=:Exists:NoExecuteというTolerationsの場合、:Existsは、値がnullではないことを指す。

podにTolerationsを設定する例

以下のように設定した場合、keyがappでvalueがbatchでeffectがNoScheduleのTaintsを持ったnodeにこのpodはscheduleできるようになる。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: batch
spec:
  replicas: 3
  template:
    metadata:
      name: batch-pod
    spec:
      containers:
      - image: busybox
      tolerations:
      - key: "app"
        operator: "Equal"
        value: "batch"
        effect: "NoSchedule"

また以下のようにvalueを指定しないこともできる。この場合、このkeyとこのeffectが同じTaintsを持ったnodeにscheduleができる。

tolerations:
- key: "app"
  operator: "Exists"
  effect: "NoSchedule"

なおoperatorを省略した場合、Equalがデフォルトとして設定される

このTaints/Tolerationsの分かりやすい使用例としては、production nodeに non-productionなpodをscheduleしたくない場合がある。

実際に試してみる

まずnodeが2台ある

$ kubectl get node
NAME                                     STATUS    ROLES     AGE       VERSION
gke-wdpress-default-pool-1a81bfcb-v7rq   Ready     <none>    16m       v1.8.8-gke.0
gke-wdpress-default-pool-1a81bfcb-w0tj   Ready     <none>    16m       v1.8.8-gke.0

それぞれのnodeにTaintsを設定する。片方をnode-type=productionに、もう片方をnode-type=developmentに。

$ kubectl taint nodes gke-wdpress-default-pool-1a81bfcb-v7rq node-type=production:NoSchedule
$ kubectl taint nodes gke-wdpress-default-pool-1a81bfcb-w0tj node-type=development:NoSchedule

tolerationを設定したpod yamlを作成

$ cat toleration-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: toleration-pod
spec:
  containers:
  - name: main
    image: alpine
    command: ["sleep", "9999999"]
  tolerations:
  - key: "node-type"
    operator: "Equal"
    value: "production"
    effect: "NoSchedule"

podを作成する。

$ kubectl create -f toleration-pod.yaml
pod "toleration-pod" created

node-type=productionを設定したnodeのほうにscheduleされていることが分かる

$ kubectl get pod -o wide
NAME             READY     STATUS    RESTARTS   AGE       IP          NODE
toleration-pod   1/1       Running   0          5s        10.24.3.8   gke-wdpress-default-pool-1a81bfcb-v7rq

しかしこれだとたまたまnode-type=productionを設定したnodeのほうにscheduleされた可能性があるので、
node-type=productionを設定したnodeをpodがscheduleされない状態にする。

$ kubectl cordon gke-wdpress-default-pool-1a81bfcb-v7rq
node "gke-wdpress-default-pool-1a81bfcb-v7rq" cordoned

SchedulingDisabledになっていることを確認

$ kubectl get node
NAME                                     STATUS                     ROLES     AGE       VERSION
gke-wdpress-default-pool-1a81bfcb-v7rq   Ready,SchedulingDisabled   <none>    14m       v1.8.8-gke.0
gke-wdpress-default-pool-1a81bfcb-w0tj   Ready                      <none>    14m       v1.8.8-gke.0

いったんpodを削除し

$ kubectl delete -f curl_pod_toleration.yaml
pod "toleration-pod" deleted

そしてpodを作成する

$ kubectl create -f curl_pod_toleration.yaml
pod "toleration-pod" created

片方のnode(node-type=development)のTaintsはこのpodは受け入れられないのでscheduleできない。
もう片方のnode(node-type=production)はSchedulingDisabled状態なのでscheduleできない。
そのためpodはscheduleされずPending状態になる。

$ kubectl get pod -o wide
NAME             READY     STATUS    RESTARTS   AGE       IP        NODE
toleration-pod   0/1       Pending   0          3s        <none>    <none>

podがscheduleされない状態にしたnodeをscheduleされる状態に戻す

$ kubectl uncordon gke-wdpress-default-pool-1a81bfcb-v7rq
node "gke-wdpress-default-pool-1a81bfcb-v7rq" uncordoned

$ kubectl get node
NAME                                     STATUS    ROLES     AGE       VERSION
gke-wdpress-default-pool-1a81bfcb-v7rq   Ready     <none>    16m       v1.8.8-gke.0
gke-wdpress-default-pool-1a81bfcb-w0tj   Ready     <none>    16m       v1.8.8-gke.0

少し待つとpodがPending状態からRunning状態に変わる。つまりscheduleされた。

$ kubectl get pod -o wide
NAME             READY     STATUS    RESTARTS   AGE       IP          NODE
toleration-pod   1/1       Running   0          36s       10.24.3.9   gke-wdpress-default-pool-1a81bfcb-v7rq

参考

studyplus
学習管理アプリ「Studyplus」を開発・運営する会社です
https://info.studyplus.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away