Taintsの使い道についてあまりピンとこなくて、使い道を調べてたらこのことを知ったので記事にした。
k8sのドキュメントにユースケースが書かれている。
kubernetes.io
- 専有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
...