Opensourcetechブログ

OpensourcetechによるNGINX/Kubernetes/Zabbix/Neo4j/Linuxなどオープンソース技術に関するブログです。

TaintとTolerationsによるPodの配置管理(kubernetes)


LinuCエヴァンジェリスト・Open Source Summit Japan 2022ボランティアリーダー鯨井貴博@opensourcetechです。


はじめに
今回はkubernetesのPod(コンテナ)を特定のノードに配置しないようにTaintとTolerationを使ってみます。


TaintとTolerationsとは
Taintは特定のノードにマーキング(Taintは汚れという意味)をして、
それを許容(Tolerarion)するPodのみ配置(スケジューリング)出来るようにするものです。


Taintをノードに付ける
早速、特定ノードにTaintを付けてみます。

まず、現在のノード状態を確認。

kubeuser@master01:~$ kubectl get nodes
NAME       STATUS   ROLES           AGE    VERSION
master01   Ready    control-plane   151d   v1.27.0
worker01   Ready    <none>          151d   v1.27.0
worker02   Ready    <none>          151d   v1.27.0

kubeuser@master01:~$ kubectl describe nodes master01 | grep Taint
Taints:             node-role.kubernetes.io/control-plane:NoSchedule

kubeuser@master01:~$ kubectl describe nodes worker01 | grep Taint
Taints:             <none>

kubeuser@master01:~$ kubectl describe nodes worker02 | grep Taint
Taints:             <none>


MasterノードのみTaintが付与(デフォルト)されており、
Workerノードの2台はTaintがありません。

この場合、worker01/worker02いずれのノードもPodが配置できる状態です。

では、worker01にTaint(env=production:NoSchedule)を付与します。
Taintは、Key=Value:Effectという形式で付与します。
- Key:任意名
- Value:任意値
- Effect:NoSchedule(Podを配置しない)・NoExecute(Podの実行を許可しない、既存Podは停止される)・PreferNoSchedule(可能な限り配置しない)

kubeuser@master01:~$ kubectl taint node worker01 env=production:NoSchedule
node/worker01 tainted

kubeuser@master01:~$ kubectl describe nodes worker01 | grep Taint
Taints:             env=production:NoSchedule



Taintを考慮せず、Podを起動してみる
まずは、Taintの事を気にせずに通常通りPodを起動します。
想定では、Taintが付与されていないノード(worker02)で起動するはずです。

kubeuser@master01:~/taint$ kubectl run taint01 --image=nginx:latest --dry-run=client -o yaml > taint01.yaml

kubeuser@master01:~/taint$ vi taint01.yaml 

kubeuser@master01:~/taint$ cat taint01.yaml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    status: notaint
    run: taint01
  name: taint01
spec:
  containers:
  - image: nginx:latest
    name: taint01
  dnsPolicy: ClusterFirst
  restartPolicy: Always

kubeuser@master01:~/taint$ kubectl apply -f taint01.yaml 
pod/taint01 created

kubeuser@master01:~/taint$ kubectl get pods -w
NAME                         READY   STATUS              RESTARTS      AGE
hpa-nginx-668b69fd79-k7d2q   1/1     Running             1 (91d ago)   129d
nginx-6cbc9bb4f5-jm8mr       1/1     Running             0             142d
nginx-6cbc9bb4f5-pfhfz       1/1     Running             0             142d
nginx2-f96cfc57b-vnsfm       1/1     Running             0             142d
taint01                      0/1     ContainerCreating   0             22s
test-webserver               1/1     Running             2 (91d ago)   126d
webserver-master01           1/1     Running             0             93d
taint01                      0/1     ContainerCreating   0             52s
taint01                      1/1     Running             0             97s

kubeuser@master01:~/taint$ kubectl get pods taint01 -o wide
NAME      READY   STATUS    RESTARTS   AGE    IP           NODE       NOMINATED NODE   READINESS GATES
taint01   1/1     Running   0          113s   10.0.30.77   worker02   <none>           <none>


想定通りですね!


Taintを考慮して、Podを起動してみる
では続いて、Taintを考慮してPodを起動します。
Toleration(許容)を設定したyamlファイルからPodを起動するので、想定ではworker01で起動するはずです。

この例では、operator: Equalを使っており、
Key・Value・Effectが一致する場合にそのノードでPodが起動されます。

kubeuser@master01:~/taint$ cp -p taint01.yaml taint02.yaml 

kubeuser@master01:~/taint$ vi taint02.yaml 

kubeuser@master01:~/taint$ cat taint02.yaml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    status: taint
    run: taint02
  name: taint02
spec:
  containers:
  - image: nginx:latest
    name: taint02
  tolerations:
  - key: env
    operator: Equal
    value: "production"
    effect: "NoSchedule"
  dnsPolicy: ClusterFirst
  restartPolicy: Always

kubeuser@master01:~/taint$ kubectl apply -f taint02.yaml 
pod/taint02 created
kubeuser@master01:~/taint$ kubectl get pods -w
NAME                         READY   STATUS              RESTARTS      AGE
hpa-nginx-668b69fd79-k7d2q   1/1     Running             1 (91d ago)   129d
nginx-6cbc9bb4f5-jm8mr       1/1     Running             0             142d
nginx-6cbc9bb4f5-pfhfz       1/1     Running             0             142d
nginx2-f96cfc57b-vnsfm       1/1     Running             0             142d
taint01                      1/1     Running             0             7m15s
taint02                      0/1     ContainerCreating   0             9s
test-webserver               1/1     Running             2 (91d ago)   126d
webserver-master01           1/1     Running             0             93d

taint02                      0/1     ContainerCreating   0             42s
taint02                      1/1     Running             0             92s

kubeuser@master01:~/taintkubectl get pods taint02 -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP          NODE       NOMINATED NODE   READINESS GATES
taint02   1/1     Running   0          2m    10.0.5.51   worker01   <none>           <none>


想定通り、worker01上でPodが起動しました。


Taintを考慮して、Podを起動してみる2
そして、もう一つ。
operator: Existsを使ってみます。
この例では、operator: Existsを使っており、
Keyが一致する場合にそのノードでPodが起動されます。

kubeuser@master01:~/taint$ cp -p taint02.yaml taint03.yaml

kubeuser@master01:~/taint$ vi taint03.yaml 

kubeuser@master01:~/taint$ cat taint03.yaml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    status: taint
    run: taint03
  name: taint03
spec:
  containers:
  - image: nginx:latest
    name: taint03
  tolerations:
  - key: env
    operator: Exists
  dnsPolicy: ClusterFirst
  restartPolicy: Always

kubeuser@master01:~/taint$ kubectl apply -f taint03.yaml 
pod/taint03 created

kubeuser@master01:~/taint$ kubectl get pods taint03 -o wide -w
NAME      READY   STATUS    RESTARTS   AGE   IP          NODE       NOMINATED NODE   READINESS GATES
taint03   1/1     Running   0          10s   10.0.5.52   worker01   <none>           <none>


こちらも想定通り、"worker01"上でPodが起動されました。


Taintの削除
Taintを付与したときのコマンドの最後に "-"を付ければOKです。

kubeuser@master01:~/taint$ kubectl get nodes worker01 | grep Taint

kubeuser@master01:~/taint$ kubectl describe nodes worker01 | grep Taint
Taints:             env=production:NoSchedule

kubeuser@master01:~/taint$ kubectl taint node worker01 env=production:NoSchedule-
node/worker01 untainted

kubeuser@master01:~/taint$ kubectl describe nodes worker01 | grep Taint
Taints:             <none>



TaintとTolerationの詳細
詳細については、以下の本家サイトで確認できます。
Taints and Tolerations
Taints and Tolerations日本語ページ

ノードの状態などによって自動的に付与されるものがあるというのも、興味深いですね。

Opensourcetech by Takahiro Kujirai