Taints/TolerationsとDeamonSetはどっちが優先されるんだろうな？って疑問を解消する

こんにちは
株式会社クラスアクト インフラストラクチャ事業部の大塚です。

今日も今日とてKubernetesの学習をしていたのですが、Taints/Tolerationsという概念とDeamonSetという概念を学びました。
その時に1つの疑問が生じました。「あれ？どっちが優先されるんだろう？DeamonSetは全てのnodeに同じ環境をデプロイするんだよな？けどnodeにTaintsが設定されていたら、邪魔されるよね？どうなるんだ？どっちが優先されるんだ？」
今回はそんな（くだらない）疑問を解消する為のlogを取りましたので、備忘録として記載しておきます。

# 用語

Taints/Tolerations
---
>toleration はPodに適用され、一致するtaintが付与されたNodeへPodがスケジューリングされることを認めるものです。ただしそのNodeへ必ずスケジューリングされるとは限りません。
taintとtolerationは組になって機能し、Podが不適切なNodeへスケジューリングされないことを保証します。taintはNodeに一つまたは複数個付与することができます。これはそのNodeがtaintを許容しないPodを受け入れるべきではないことを示します。

https://kubernetes.io/ja/docs/concepts/scheduling-eviction/taint-and-toleration/

DeamonSet
---
>DaemonSetは、すべての（または一部の）ノードがPodのコピーを実行することを保証します。ノードがクラスタに追加されると、Podが追加されます。ノードがクラスタから削除されると、これらのPodはガベージコレクションされます。DaemonSetを削除すると、それが作成したPodがクリーンアップされます。

https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/

# 検証イメージ

環境は以下を用意しました。4台のnodeでk8sクラスタを組んでおります。
k8s-master nodeに対してtaints env=master:NoScheduleを設定していきます。
この状態でtolerationsが設定されていないDeamonSet（pod）がk8s-masterにデプロイされるのか、或いはtolerationsが設定されていない為はじかれるのか、ということになります。
もしpodがデプロイされたらDeamonSetのプライオリティが高く、そうでなければTaints/Tolerationsのプライオリティが高いということになります。

![kubernetes-ページ17.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/2d1622e7-6e8a-54be-f1e6-7156dc54af01.png)

以下が検証前の環境logになります。
nodeが4台あり、特に何もデプロイされていないことが分かると思います。
```
root@k8s-master:~# kubectl get node 
NAME           STATUS   ROLES    AGE    VERSION 
k8s-worker01   Ready    <none>   34h    v1.26.4 
k8s-master     Ready    <none>   2d2h   v1.26.4 
k8s-worker02   Ready    <none>   34h    v1.26.4 
k8s-worker03   Ready    <none>   54s    v1.26.4 

root@k8s-master:~# kubectl get all 
NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE 
service/kubernetes   ClusterIP   10.152.183.1   <none>        443/TCP   2d2h
```

また以下のコマンド結果より、k8s-master nodeにtaintsが何も設定されていないことが分かります。
```
root@k8s-master:~# kubectl describe node k8s-master | grep Taints 
Taints:             <none>
```

# nodeにtaintsを設定する
taintsを設定する為にはkubectl taint nodeコマンドを実行します。
今回は以下のコマンドを実行しました。describeの出力結果で設定が正常に出来ていることが分かります。
```
root@k8s-master:~# kubectl taint node k8s-master env=master:NoSchedule 
node/k8s-master tainted 
root@k8s-master:~# kubectl describe node k8s-master | grep Taints 
Taints:             env=master:NoSchedule
```

# DeamonSetをデプロイ

今回ds用に準備したyamlファイルは以下となります。
ds名は"test-ds"、pod名は"nginx"とし、pod内のコンテナは1つで名前を"nginx-container"としています。
```
root@k8s-master:~/yaml# cat test-ds.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: test-ds
spec:
  selector:
    matchLabels:
      name: nginx
  template:
    metadata:
      labels:
        name: nginx
    spec:
      containers:
      - name: nginx-container
        image: nginx:latest
```

このyamlファイルをベースにデプロイしていきます。
```
root@k8s-master:~/yaml# kubectl create -f test-ds.yaml
daemonset.apps/test-ds created
```

どのノードにデプロイされているか確認します。
出力結果よりk8s-master nodeにはデプロイされていませんね。
taints/tolerationsが優先されているっぽいです。
```
root@k8s-master:~/yaml# kubectl get all -o wide
NAME                READY   STATUS    RESTARTS   AGE   IP            NODE           NOMINATED NODE   READINESS GATES
pod/test-ds-f858g   1/1     Running   0          63s   10.1.79.69    k8s-worker01   <none>           <none>
pod/test-ds-shk5r   1/1     Running   0          63s   10.1.39.193   k8s-worker03   <none>           <none>
pod/test-ds-2nt4m   1/1     Running   0          63s   10.1.69.199   k8s-worker02   <none>           <none>

NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE    SELECTOR
service/kubernetes   ClusterIP   10.152.183.1   <none>        443/TCP   2d2h   <none>

NAME                     DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE   CONTAINERS        IMAGES         SELECTOR
daemonset.apps/test-ds   3         3         3       3            3           <none>          63s   nginx-container   nginx:latest   name=nginx
```

この時のイメージです。
![kubernetes-ページ19.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/f3a52232-e7fd-9326-ebfe-f54c7d7ec59d.png)

# DeamonSetにtolerationsを設定してみる

追加検証です。以下の様にyamlを修正しデプロイされるpodにtolerationを付与していきます。
```
root@k8s-master:~/yaml# cat test-ds.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: test-ds
spec:
  selector:
    matchLabels:
      name: nginx
  template:
    metadata:
      labels:
        name: nginx
    spec:
      tolerations:
      - key: "env"
        operator: "Equal"
        value: "master"
        effect: NoSchedule
      containers:
      - name: nginx-container
        image: nginx:latest
```

先程作成したdsを削除してから、修正したyamlで再度dsをデプロイします
```
root@k8s-master:~/yaml# kubectl delete ds test-ds
daemonset.apps "test-ds" deleted
root@k8s-master:~/yaml# kubectl create -f test-ds.yaml
daemonset.apps/test-ds created
```

デプロイ結果は以下です。
tolerationを設定したことでk8s-master nodeにもpodがデプロイされましたね。
```
root@k8s-master:~/yaml# kubectl get all -o wide
NAME                READY   STATUS    RESTARTS   AGE   IP             NODE           NOMINATED NODE   READINESS GATES
pod/test-ds-4z2k9   1/1     Running   0          42s   10.1.79.70     k8s-worker01   <none>           <none>
pod/test-ds-l9wps   1/1     Running   0          42s   10.1.39.194    k8s-worker03   <none>           <none>
pod/test-ds-5677r   1/1     Running   0          42s   10.1.69.200    k8s-worker02   <none>           <none>
pod/test-ds-wvwkj   1/1     Running   0          42s   10.1.235.210   k8s-master     <none>           <none>

NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE    SELECTOR
service/kubernetes   ClusterIP   10.152.183.1   <none>        443/TCP   2d3h   <none>

NAME                     DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE   CONTAINERS        IMAGES         SELECTOR
daemonset.apps/test-ds   4         4         4       4            4           <none>          42s   nginx-container   nginx:latest   name=nginx
```

この時のイメージです
![kubernetes-ページ20.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/706d3dc6-6f95-94e6-88d3-85a34ea69836.png)