一 Taint/Toleration介紹:
1 一個例子:
我這里測試了一個rc,內容如下:
[root@k8s-master-01 practice]# cat my-nginx-rc.yaml apiVersion: v1 kind: ReplicationController metadata: name: my-nginx spec: replicas: 3 selector: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 restartPolicy: Always
[root@k8s-master-01 practice]# cat my-nginx-service.yaml apiVersion: v1 kind: Service metadata: name: my-nginx spec: selector: app: nginx ports: - name: http port: 80 targetPort: 80 protocol: TCP
[root@k8s-master-01 practice]# kubectl create -f my-nginx-rc.yaml replicationcontroller/my-nginx created [root@k8s-master-01 practice]# kubectl get pod NAME READY STATUS RESTARTS AGE my-nginx-7dkgz 1/1 Running 0 60s my-nginx-mq8rs 1/1 Running 0 60s my-nginx-rj67n 1/1 Running 0 60s [root@k8s-master-01 practice]# kubectl create -f my-nginx-service.yaml service/my-nginx created [root@k8s-master-01 practice]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-nginx NodePort 10.103.32.111 <none> 80:30965/TCP 9s [root@k8s-master-01 practice]# kubectl describe pod my-nginx-7dkgz|grep -i node: Node: k8s-node-02/10.10.0.135 [root@k8s-master-01 practice]# kubectl describe pod my-nginx-mq8rs|grep -i node: Node: k8s-node-01/10.10.0.190 [root@k8s-master-01 practice]# kubectl describe pod my-nginx-rj67n|grep -i node: Node: k8s-node-02/10.10.0.135
說明:整個集群有三個master node和兩個slave node,當運行三個nginx pod的時候,發現所有的容器都都跑在了slave node上,而三個master上卻沒有容器,這就是本課的內容了。
2 Taint/Toleration說明:
[root@k8s-master-01 practice]# kubectl describe node k8s-master-01|grep -i taints Taints: node-role.kubernetes.io/master:NoSchedule
在master節點上都能看到這個信息,這就是默認情況下master節點不能運行pod的原因。這正是Taint/Toleration機制。
taint:污點的意思。如果一個節點被打上了污點,那么pod是不允許運行在這個節點上面的,當然如果你可以容忍(Toleration),那可以運行。
為k8s-master-01打一個污點:
[root@k8s-master-01 practice]# kubectl taint nodes k8s-master-01 env=joint:NoSchedule node/k8s-master-01 tainted [root@k8s-master-01 practice]# kubectl describe node k8s-master-01|grep -i taints Taints: env=joint:NoSchedule
node-role.kubernetes.io/master:NoSchedule
上面這條污點規則意味着:當有新的pod需要調度時(不影響已經在k8s-master-01上運行的pod),k8s-master-01不參與。
如果有需求,當我調度新的pod時,想讓它運行在這個節點上,就要設置容忍了:
還拿上面的例子:
kubectl taint nodes k8s-master-01 node-role.kubernetes.io/master-
node/k8s-master-01 untainted
注意后面有一個“-”,這條命令是指:移除所有以node-role.kubernetes.io/master為鍵的Taint.
[root@k8s-master-01 practice]# kubectl describe node k8s-master-01|grep -i taint Taints: env=joint:NoSchedule (只剩下這一條taint。) [root@k8s-master-01 practice]# kubectl create -f my-nginx-rc.yaml [root@k8s-master-01 practice]# kubectl get pod|grep my-nginx my-nginx-4xq2c 1/1 Running 0 55s my-nginx-979nf 1/1 Running 0 55s my-nginx-l2zv4 1/1 Running 0 55s my-nginx-qfkgk 1/1 Running 0 55s my-nginx-wj8qj 1/1 Running 0 55s my-nginx-zthhf 1/1 Running 0 55s [root@k8s-master-01 practice]# kubectl describe pod my-nginx-4xq2c|grep -i node: Node: k8s-node-02/10.10.0.135 [root@k8s-master-01 practice]# kubectl describe pod my-nginx-979nf|grep -i node: Node: k8s-node-01/10.10.0.190 [root@k8s-master-01 practice]# kubectl describe pod my-nginx-l2zv4|grep -i node: Node: k8s-master-01/10.10.0.170 [root@k8s-master-01 practice]# kubectl describe pod my-nginx-qfkgk|grep -i node: Node: k8s-node-02/10.10.0.135 [root@k8s-master-01 practice]# kubectl describe pod my-nginx-wj8qj|grep -i node: Node: k8s-node-01/10.10.0.190 [root@k8s-master-01 practice]# kubectl describe pod my-nginx-zthhf|grep -i node: Node: k8s-master-01/10.10.0.170
我們看見新的pod在toleration這個污點后就可以運行在了這台master node上了。
3 調度策略:
3.1 可以在同一個 node 上使用多個 taints ,也可以在同一個 pod 上使用多個 tolerations。
3.2 taints and tolerations 時類似一個過濾器:
對比一個 node 上所有的 taints
忽略掉和 pod 中 toleration 匹配的 taints
遺留下來未被忽略掉的所有taints將對pod產生effect,具體見下:
3.2.1 至少有 1 個未被忽略的 taint 且 effect 是 NoSchedule 時,則 k8s 不會將該 pod 調度到這個 node 上
3.2.2 至少有 1 個未被忽略的 taint 且 effect 是 PreferNoSchedule 時,則 k8s 將嘗試不把該 pod 調度到這個 node 上
3.2.3 至少有 1 個未被忽略的 taint 且 effect 是 NoExecute 時,則 k8s 會立即將該 pod 從該 node 上驅逐(如果已經在該 node 上運行),
或着不會將該 pod 調度到這個 node 上(如果還沒在這個 node 上運行)
3.4 我們上面使用的策略是:NoSchedule,其他的策略:
PreferNoSchedule:這意味着不是一個強制必須的調度策略(盡量不去滿足不合要求的 pod 調度到 node 上來)
NoExecute:立刻移除已經運行的pod且新pod不會被調度到該節點上。
3.5 常見的寫法:
3.5.1 下面兩種寫法等價:
tolerations: - key: "demo.test.com/app" operator: "Equal" value: "whoami" effect: "NoSchedule"
tolerations: - key: "demo.test.com/app" operator: "Exists" effect: "NoSchedule"
operator 默認值是 Equal 如果不指定的話
3.5.2:
key 為空且 operator 是 Exists 時,將匹配所有的 keys, values 和 effects ,這表明可以 tolerate 所有的 taint
3.6具體場景使用:
有下列三個taint:
kubectl taint nodes tvm-04 key1=value1:NoSchedule
kubectl taint nodes tvm-04 key1=value1:NoExecute
kubectl taint nodes tvm-04 key2=value2:NoSchedule
tolerations: - key: "key1" operator: "Equal" value: "value1" effect: "NoSchedule" - key: "key1" operator: "Equal" value: "value1" effect: "NoExecute"
上述場景中,
該 pod 不會調度到 node 上,因為第 3 個 taint 不滿足
如果該 pod 已經在該 node 上運行,則不會被驅逐
通常而言,不能 tolerate 一個 effect 是 NoExecute 的 pod 將被立即驅逐,但是,通過指定可選的字段 tolerationSeconds 則可以規定該 pod 延遲到一個時間段后再被驅逐,例如:
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
tolerationSeconds: 3600
也就是說,在 3600 秒后將被驅逐。但是,如果在這個時間點前移除了相關的 taint 則也不會被驅逐
注3:關於被驅逐,如果該 pod 沒有其他地方可以被調度,也不會被驅逐出去(個人實驗結果,請自行驗證)