TaintsとTolerationsについて
Kubernetesには最初、特定のnodeに特定のpodをscheduleする方法としてnode selectorを使う方法があった。(node selectorの他にも特定のnodeに特定のpodをscheduleするための仕組みとしてNode Affinityがある)
しかし後からもっと柔軟にscheduleするためのメカニズムが導入された。
それがTaints
とTolerations
。
(taintは"汚れ"という意味。tolerationは"容認"という意味。つまり"汚れ"を"容認"できるならscheduleできる仕組み)
Taints
とTolerations
はNode Selector
やNode Affinity
と似ているが性質は正反対で、
Node Selector
やNode Affinity
が特定のnodeに特定のpodをscheduleするための仕組みに対し、
Taints
とTolerations
は特定のnodeにpodをscheduleしないための仕組みだ。
Taints
とTolerations
は互いに協調しあい、podが不適当なnodeにscheduleされないようにする。
Node Affinityなどの場合には、それらが未指定の場合はどこのNodeにでもscheduleされてしまうが、Taints
とTolerations
の場合は指定しない限りその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
のような形式で実行する。
Taints
はkey
とvalue
とeffect
の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時に影響があるNoSchedule やPreferNoSchedule と違って、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
参考
- Kubernetes完全ガイド(最高に分かりやすく書かれているのでぜひ買いましょう)
- Kubernetes in Action
- Taints and Tolerations