Taint/Toleration pod调度策略
一 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 没有其他地方可以被调度,也不会被驱逐出去(个人实验结果,请自行验证)