Taintsの使い道についてあまりピンとこなくて、使い道を調べてたらこのことを知ったので記事にした。
Taintsのユースケース
- 専有NodeにTaintsを付与する
- 特殊なハードウェアを備えたNodeにTaintsを付与して、そのハードウェアを必要としないPodが配置されないようにする
- Nodeに問題が起きたときにPodがそのNodeに配置されないようにする
さらに読みすすめると「taintを基にした排除」の項にこんなことが書かれていた。
Nodeコントローラーは特定の条件を満たす場合に自動的にtaintを追加します。 組み込まれているtaintは下記の通りです。
...
node.kubernetes.io/unschedulable
: Nodeがスケジューリングできない場合。
スケジューリングできない場合ということは、もしかしてdrainやcordonを使うときにtaintsが付与されるのかな? と思ったので実際に確認してみた。
drain/cordonでもTaintsが使われている
drainを実行するとPodを退避する前にcordonが実行されて、Taintにnode.kubernetes.io/unschedulable:NoSchedule
が付与される。
ざっくりこんな流れ。
- 対象Nodeでcordonが実行される
- 対象NodeのTaintsに
node.kubernetes.io/unschedulable:NoSchedule
が付与されて、新しいPodが配置されないようにする - Podの退避or停止が実行される
- 退避されたPodは別Nodeで起動する
kindで検証してみる
まずは環境用意
kindでローカルにクラスタを構築して検証する。
こんなcluster.yaml
を用意する。
ちなみに https://kind.sigs.k8s.io/docs/user/configuration/#name-your-cluster から引っ張ってきた。
$ cat cluster.yaml kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane - role: worker - role: worker - role: worker
$ kind create cluster --name sample --config=cluster.yaml Creating cluster "sample" ... ✓ Ensuring node image (kindest/node:v1.24.0) 🖼 ✓ Preparing nodes 📦 📦 📦 📦 ✓ Writing configuration 📜 ✓ Starting control-plane 🕹️ ✓ Installing CNI 🔌 ✓ Installing StorageClass 💾 ✓ Joining worker nodes 🚜 Set kubectl context to "kind-sample" You can now use your cluster with: kubectl cluster-info --context kind-sample Thanks for using kind! 😊
出来上がったノード。
$ kubectl get nodes NAME STATUS ROLES AGE VERSION sample-control-plane Ready control-plane 69s v1.24.0 sample-worker Ready <none> 32s v1.24.0 sample-worker2 Ready <none> 32s v1.24.0 sample-worker3 Ready <none> 32s v1.24.0
各sample-workerのLabelsとTaintsはこんな感じ。 3台ともすべて同じ。
$ kubectl describe node sample-worker Name: sample-worker Roles: <none> Labels: beta.kubernetes.io/arch=amd64 beta.kubernetes.io/os=linux kubernetes.io/arch=amd64 kubernetes.io/hostname=sample-worker kubernetes.io/os=linux Annotations: kubeadm.alpha.kubernetes.io/cri-socket: unix:///run/containerd/containerd.sock node.alpha.kubernetes.io/ttl: 0 volumes.kubernetes.io/controller-managed-attach-detach: true CreationTimestamp: Tue, 12 Jul 2022 23:28:35 +0900 Taints: <none> 👈node作成直後なので何も付与されていない Unschedulable: false ...
全sample-workerに適当なラベルenv=testing
を付与。
$ kubectl label node sample-worker env=testing node/sample-worker labeled $ kubectl label node sample-worker2 env=testing node/sample-worker2 labeled $ kubectl label node sample-worker3 env=testing node/sample-worker3 labeled
nginxのPodをenv=testing
なNodeで起動する。
$ cat nginx-pod.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: env: testing name: nginx spec: replicas: 3 selector: matchLabels: env: testing template: metadata: labels: env: testing spec: containers: - image: nginx name: nginx affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: env operator: In values: - testing $ kubectl apply -f nginx-pod.yaml deployment.apps/nginx created $ kubectl get deployment -o wide NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR nginx 3/3 3 3 28s nginx nginx env=testing $ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-575bc5fb56-bc5cj 1/1 Running 0 48s 10.244.3.2 sample-worker2 <none> <none> nginx-575bc5fb56-q4g2v 1/1 Running 0 48s 10.244.1.2 sample-worker <none> <none> nginx-575bc5fb56-srsx4 1/1 Running 0 48s 10.244.2.2 sample-worker3 <none> <none>
これで準備ができた。
sample-workerを対象にdrainを実行してみる
ログ通り、cordonが実行された後に各podが退避されていることがわかる。
$ kubectl drain sample-worker --ignore-daemonsets node/sample-worker cordoned WARNING: ignoring DaemonSet-managed Pods: kube-system/kindnet-wzcdv, kube-system/kube-proxy-dwkzb evicting pod default/nginx-575bc5fb56-q4g2v pod/nginx-575bc5fb56-q4g2v evicted node/sample-worker drained
sample-worker
のステータスに SchedulingDisabled
が追加されており、sample-worker
上で動いていたPod 消えて別Nodesample-worker3
で新しいPodが起動する。
$ kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME sample-control-plane Ready control-plane 6m40s v1.24.0 172.23.0.2 <none> Ubuntu 21.10 4.18.0-348.el8.0.2.x86_64 containerd://1.6.4 sample-worker Ready,SchedulingDisabled <none> 6m3s v1.24.0 172.23.0.5 <none> Ubuntu 21.10 4.18.0-348.el8.0.2.x86_64 containerd://1.6.4 sample-worker2 Ready <none> 6m3s v1.24.0 172.23.0.4 <none> Ubuntu 21.10 4.18.0-348.el8.0.2.x86_64 containerd://1.6.4 sample-worker3 Ready <none> 6m3s v1.24.0 172.23.0.3 <none> Ubuntu 21.10 4.18.0-348.el8.0.2.x86_64 containerd://1.6.4 $ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-575bc5fb56-bc5cj 1/1 Running 0 2m18s 10.244.3.2 sample-worker2 <none> <none> nginx-575bc5fb56-gx5c7 1/1 Running 0 32s 10.244.2.3 sample-worker3 <none> <none> nginx-575bc5fb56-srsx4 1/1 Running 0 2m18s 10.244.2.2 sample-worker3 <none> <none>
describeを見るとnode.kubernetes.io/unschedulable:NoSchedule
というTaintsが付与されていることがわかる。
$ kubectl describe node sample-worker Name: sample-worker Roles: <none> Labels: beta.kubernetes.io/arch=amd64 beta.kubernetes.io/os=linux env=testing kubernetes.io/arch=amd64 kubernetes.io/hostname=sample-worker kubernetes.io/os=linux Annotations: kubeadm.alpha.kubernetes.io/cri-socket: unix:///run/containerd/containerd.sock node.alpha.kubernetes.io/ttl: 0 volumes.kubernetes.io/controller-managed-attach-detach: true CreationTimestamp: Tue, 12 Jul 2022 23:28:35 +0900 Taints: node.kubernetes.io/unschedulable:NoSchedule 👈付与された Unschedulable: true ...
Taintsを削除する場合
Taints node.kubernetes.io/unschedulable:NoSchedule
を削除するときはuncordonすればOK。
$ kubectl uncordon sample-worker node/sample-worker uncordoned $ kubectl get node -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME sample-control-plane Ready control-plane 11m v1.24.0 172.23.0.2 <none> Ubuntu 21.10 4.18.0-348.el8.0.2.x86_64 containerd://1.6.4 sample-worker Ready <none> 10m v1.24.0 172.23.0.5 <none> Ubuntu 21.10 4.18.0-348.el8.0.2.x86_64 containerd://1.6.4 sample-worker2 Ready <none> 10m v1.24.0 172.23.0.4 <none> Ubuntu 21.10 4.18.0-348.el8.0.2.x86_64 containerd://1.6.4 sample-worker3 Ready <none> 10m v1.24.0 172.23.0.3 <none> Ubuntu 21.10 4.18.0-348.el8.0.2.x86_64 containerd://1.6.4 $ kubectl describe node sample-worker Name: sample-worker Roles: <none> Labels: beta.kubernetes.io/arch=amd64 beta.kubernetes.io/os=linux env=testing kubernetes.io/arch=amd64 kubernetes.io/hostname=sample-worker kubernetes.io/os=linux Annotations: kubeadm.alpha.kubernetes.io/cri-socket: unix:///run/containerd/containerd.sock node.alpha.kubernetes.io/ttl: 0 volumes.kubernetes.io/controller-managed-attach-detach: true CreationTimestamp: Tue, 12 Jul 2022 23:28:35 +0900 Taints: <none> 👈消えてる Unschedulable: false ...