Kubernetes——污点和容忍度

污点和容忍度

  污点 taints(英[teɪnt] 美[teɪnt]) 是定义在节点之上的键值型属性数据,用于让节点拒绝将 Pod 调度运行于其上, 除非该 Pod 对象具有接纳节点污点的容忍度。而容忍度 tolerations 是定义在 Pod 对象上的键值型属性数据,用于配置其可容忍的节点污点,而且调度器仅能将 Pod对 象调度至其能够容忍该节点污点的节点之上,如图所示:

  节点选择器 nodeSelector 和节点亲和性 nodeAffinity 两种调度方式都是通过在 Pod 对象上添加标签选择器来完成对特定类型节点标签的匹配,它们实现的是由 Pod 选择节点的机制。而污点和容忍度则是通过向节点添加污点信息来控制 Pod 对象的调度结果,从而赋予了节点控制何种 Pod 对象能够调度于其上的主控权。简单来说,节点亲和性使得 Pod 对象被吸引到一类特定的节点,而污点则相反,它提供了让节点排斥特定Pod对象的能力。

  Kubernetes 使用 PodToleratesNodeTaints 预选策略和 TaintTolerationPriority 优选函数来完成此种类型的高级调度机制。

一、定义污点和容忍度

  污点定义在节点的 nodeSpec 中,而容忍度则定义在 Pod 的 podSpec 中,它们都是键值型数据,但又都额外支持一个效果 effect 标记,语法格式为 key=value:effect,其中key和value的用法及格式与资源注解信息相似, 而 effect 则用于定义对 Pod 对象的排斥等级,它主要包含以下三种类型:

    • NoSchedule: 不能容忍此污点的新 Pod 对象不可调度至当前节点,属于强制型约束关系,节点上现存的 Pod 对象不受影响。
    • PreferNoSchedule: NoSchedule 的柔性约束版本,即不能容忍此污点的新 Pod 对象尽量不要调度至当前节点,不过无其他节点可供调度时也允许接受相应的 Pod 对象。节点上现存的 Pod 对象不受影响。
    • NoExecute: 不能容忍此污点的新 Pod 对象不可调度至当前节点,属于强制型约束关系,而且节点上现存的 Pod 对象因节点污点变动或 Pod 容忍度变动而不再满足匹配规则时,Pod 对象将被驱逐。

  在Pod对象上定义容忍度时,它支持两种操作符:

    1. 一种是等值比较 Equal,表示容忍度与污点必须在 key、value 和 effect 三者之上完全匹配;
    2. 另一种是存在性判断 Exists,表示二者的 key 和 effect 必须完全匹配,而容忍度中的 value 字段要使用空值。

  一个节点可以配置使用多个污点,一个 Pod 对象也可以有多个容忍度,不过二者在进行匹配检查时应遵循如下逻辑。

    1. 首先处理每个有着与之匹配的容忍度的污点。
    2. 不能匹配到的污点上,如果存在一个污点使用了 NoSchedule 效用标识,则拒绝调度 Pod 对象至此节点。
    3. 不能匹配到的污点上,若没有任何一个使用了 NoSchedule 效用标识,但至少有一个使用了 PreferNoScheduler,则应尽量避免将Pod对象调度至此节点。
    4. 如果至少有一个不匹配的污点使用了 NoExecute 效用标识,则节点将立即驱逐Pod对象,或者不予调度至给定节点;另外,即便容忍度可以匹配到使用了 NoExecute 效用标识的污点,若在定义容忍度时还同时使用tolerationSeconds 属性定义了容忍时限,则超出时限后其也将被节点驱逐。
    5. 使用 kubeadm 部署的 Kubernetes 集群,其 Master 节点将自动添加污点信息以阻止不能容忍此污点的 Pod 对象调度至此节点,因此,用户手动创建的未特意添加容忍此污点容忍度的 Pod 对象将不会被调度至此节点。

 二、管理节点的污点

  任何符合其键值规范要求的字符串均可用于定义污点信息:仅可使用字母、数字、连接符、点号和下划线,且仅能以字母或数字开头,其中键名的长度上限为 253 个字符,值最长为 63 个字符。

  实践中,污点通常用于描述具体的部署规划,它们的键名形如 node-type、node-role、node-project 或 node-geo 等,因此还可以在必要时带上域名以描述其额外的信息,如 nodet-type.xxx.com 等。

  使用 "kubectl taint" 命令即可向节点添加污点,命令的语法格式如下:

kubectl taint nodes <node-name> <key>=<value>:<effect>

  例如,使用 "node-type=production:NoSchedule" 定义节点 node01.xxx.com:

# kubectl taint nodes node01.linux.io node-type=production:NoSchedule
node "node01.linux.io" tainted

  此时,node01 上已有的 Pod 对象不受影响,但新建的 Pod 若不能容忍此污点将不能再被调度至此节点。类似下面的命令可以查看节点上的污点信息:

# kubectl get nodes node01.linux.io -o go-template={{.spec.taints}}
[map[value:production effect:NoSchedule key:node-type]]

  需要注意的是,即便是同一个键值数据,若其效用标识不同,则其分属于不同的污点信息,例如,将上面命令中的效用标识定义为 PreferNoSchedule 再添加一次:

# kubectl taint nodes node01.linux.io node-type=production:PreferNoSchedule
node "node01.linux.io" tainted

  删除某污点,仍然通过 kubectl taint 命令进行,但要使用如下的命令格式,省略效用标识则表示删除使用指定键名的所有污点,否则就只删除指定键名上对应效用标识的污点:

kubectl taint nodes <node-name> <key>:[<effect>]-

  例如,删除 node01 上 node-type 键的效用表示为 "NoSchedule" 的污点信息:

# kubectl taint nodes node01.linux.io node-type:NoSchedule- 
node "node01.linux.io" untainted

  若要删除使用指定键名的所有污点,则在删除命令中省略效用标识即能实现,例如:

# kubectl taint nodes node01.linux.io node-type- 
node "node01.linux.io" untainted

  删除节点上的全部污点信息,通过 kubectl path 命令将节点属性 spec.taints 的值直接置空即可,例如:

# kubectl patch nodes node01.linux.io -p '{"spec":{"taints":[]}}' 
node "node01.linux.io" patched

三、Pod 对象的容忍度

  Pod对象的容忍度可通过其 spec.tolerations 字段进行添加,根据使用的操作符不同,主要有两种可用的形式:

    1. 一种是与污点信息完全匹配的等值关系
    2. 另一种是判断污点信息存在性的匹配方式。

  使用 Equal 操作符的示例如下所示,其中 tolerationSeconds 用于定义延迟驱逐当前 Pod 对象的时长:

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"
  tolerationSeconds: 3600

  使用存在性判断机制的容忍度示例如下所示:

tolerations:
- key: "key1"
  operator: "Exists"
  effect: "NoExecute"
  tolerationSeconds: 3600

  实践中,若集群中的一组机器专用于为运行非生产型的容器应用而备置,而且它们可能随时按需上下线,那么就应该为其添加污点信息,以确保仅那些能容忍此污点的非生产型Pod对象可以调度其上。另外,某些有着特殊硬件的节点需要专用于运行一类有着此类硬件资源需求的Pod对象时,例如,那些有着SSD或GPU的设备,也应该为其添加污点信息以排除其他的Pod对象。

四、问题节点标识

  Kubernetes 自 1.6 版本起支持使用污点自动标识问题节点,它通过节点控制器在特定条件下自动为节点添加污点信息实现。它们都使用 NoExecute 效用标识,因此不能容忍此类污点的现有 Pod 对象也会遭到驱逐。目前,内建使用的此类污点包含如下几个。

    1. node.kubernetes.io/not-ready: 节点进入NotReady状态时被自动添加的污点。
    2. node.alpha.kubernetes.io/unreachable: 节点进入NotReachable状态时被自动添加的污点。
    3. node.kubernetes.io/out-of-disk: 节点进入OutOfDisk状态时被自动添加的污点。
    4. node.kubernetes.io/memory-pressure: 节点内存资源面临压力。
    5. node.kubernetes.io/disk-pressure: 节点磁盘资源面临压力。
    6. node.kubernetes.io/network-unavailable: 节点网络不可用。
    7. node.cloudprovider.kubernetes.io/uninitialized: kubelet由外部的云环境程序启动时,它将自动为节点添加此污点,待到云控制器管理器中的控制器初始化此节点时再将其删除。

  Kubernetes 的核心组件通常都要容忍此类的污点,以确保其相应的 DaemonSet 控制器能够无视此类污点,于节点上部署相应的关键性Pod对象,例如 kube-proxy 或 kube- flannel 等。 

posted @ 2022-07-06 17:35  左扬  阅读(247)  评论(0编辑  收藏  举报
levels of contents