k8s☞17-1调度之node污染和pod容忍

阅读量: zyh 2021-06-17 16:21:58
Categories: > Tags:

引用

概念文档:污点和容忍度 | Kubernetes

命令文档:Kubectl Reference Docs (kubernetes.io)

污点/容忍概念

Node上的污点规则,即Node告知调度器只有可以容忍污点规则的Pod才可以调度过来。

Node的污点规则由两部分组成:污点:污点效果。

Pod上的容忍规则,即Pod告知调度器可以容忍Node上设定的污点规则。

🍖容忍规则和污点规则都可以添加多个。

污点/容忍命令

Node的污点规则:

# 添加污点
## 标签对:污染关键词
kubectl taint nodes <node.name> KEY_1=VAL_1:TAINT_EFFECT_1 KEY_N=VAL_N:TAINT_EFFECT_N

# 移除污点
kubectl taint nodes <node.name> KEY_1-

# 查看节点污染信息,若无污染则为 none
kubectl describe nodes <node.name> | grep Taints
Taints:             node-role.kubernetes.io/master:NoSchedule

Pod容忍规则:

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"

operator 可以是Equal等于或者Exists存在。

调度逻辑

首先,Pod的容忍规则需要完全等同于污点规则,即污点和污点效果都一致才算是匹配成功。但存在特殊情况:

其次,当Node的污点规则有多个的时候,调度器会将Pod的容忍规则与之一一匹配。就如同小学题里那种连线题一样。

最后,若都可以匹配,则Pod可以调度进去。但只要存在一个不匹配的污点规则,那么调度器就需要依据这个污点规则的污点效果来判断Pod的进/退:

污点效果

一般情况,若Node存在下列污点效果,调度器的逻辑是:

NoSchedule 表示调度器不可调度【还未创建的】Pod到此节点。

PreferNoSchedule表示尽量不要调度【还未创建的】Pod到此节点。

NoExecute 表示绝不允许调度Pod到此节点,哪怕Pod【已经创建】都会被驱逐。

针对【NoExecute】,若可以【匹配NoExecute】的Pod里包含了额外的宽恕期规则tolerationSeconds,则Pod【仅可以】在tolerationSeconds宽恕期之内运行。

🤦‍♂️经测试,即使是污点规则添加之后的Pod,也只可以在tolerationSeconds内运行。因此这个宽恕期不如称之为【可运行时间】。

https://kubernetes.io/zh/docs/concepts/scheduling-eviction/taint-and-toleration/#taint-based-evictions

例如:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  tolerations:
  - key: "example-key"
    operator: "Exists"
    effect: "NoExecute"
    tolerationSeconds: 3600

上述配置表示,当 pod 所在节点被添加了一个example-key:NoExecute 污点的时候,pod 将不会被驱逐,而是可以继续存活3600秒,如果还未到3600秒,污点就被移除,则 pod 驱逐也会停止。

自动污点规则

当某种条件为真时,节点控制器会自动给节点添加一个污点。当前内置的污点包括:

在节点被驱逐的时候,节点控制器或者 kubelet 会添加带有 NoExecute 污点效果的相关内置污点。异常恢复的时候,会自动移除污点。

🤷‍♂️关于用kubectl drain执行驱逐的时候,node显示的污点只有一个node.kubernetes.io/unschedulable:NoSchedule。但实际效果是node.kubernetes.io/unschedulable:NoExecute。即驱逐命令会驱逐掉已存在的Pod。可能kubectl drain会添加内置的特殊污点效果。

➜   kubectl drain k8s03 --ignore-daemonsets --delete-emptydir-data
➜   kubectl describe node k8s03 | grep Taints
Taints:             node.kubernetes.io/unschedulable:NoSchedule

如果你想让某个pod在节点出现问题(例如节点网络故障)后,依然被调度在当前节点保持1小时,那么你可以添加下列容忍规则:

tolerations:
- key: "node.kubernetes.io/network-unavailable"
  operator: "Exists"
  effect: "NoExecute"
  tolerationSeconds: 3600

自动容忍规则

Kubernetes 会自动给 Pod 添加内置污点 node.kubernetes.io/not-ready:NoExecute 的容忍度并配置 tolerationSeconds=300,除非用户提供的 Pod 配置中已经已存在了 key 为 node.kubernetes.io/not-ready 的容忍度。

Kubernetes 会自动给 Pod 添加内置污点 node.kubernetes.io/unreachable:NoExecute 的容忍度并配置 tolerationSeconds=300,除非用户提供的 Pod 配置中已经已存在了 key 为 node.kubernetes.io/unreachable 的容忍度。

这意味着在其中一种问题被检测到时 Pod 默认能够继续停留在当前节点运行 5 分钟。

但是,对于DaemonSet的Pod,则不会配置tolerationSeconds。这意味着,Node出现上述问题后,这类Pod将永久运行不被驱逐。

DaemonSet的自动附加容忍度:

node.kubernetes.io/disk-pressure:NoSchedule op=Exists
node.kubernetes.io/memory-pressure:NoSchedule op=Exists
node.kubernetes.io/network-unavailable:NoSchedule op=Exists
node.kubernetes.io/pid-pressure:NoSchedule op=Exists
node.kubernetes.io/unschedulable:NoSchedule op=Exists

node.kubernetes.io/not-ready:NoExecute op=Exists
node.kubernetes.io/unreachable:NoExecute op=Exists

🍖DaemonSet中除了上述自动容忍度,还经常见到万能容忍度:NoSchedule op=Exists 或者 op=Exists