Kubernetes资源调度之污点与Pod容忍度

Kubernetes资源调度之污点与Pod容忍度

概述

污点是定义在节点之上的键值型属性数据,用于让节点有能力主动拒绝调度器将Pod调度运行到节点上,除非该Pod对象具有接纳节点污点的容忍度。容忍度(tolerations)则是定义在Pod对象上的键值型属性数据,用于配置该Pod可容忍的节点污点,否则该 Taints 节点不会被调度 Pod。

image-20220628160942866

我们知道,节点选择器(nodeSelector)和节点亲和性(nodeAffinity)两种调度方式都是通过在Pod对象上添加标签选择器来完成对特定类型节点标签的匹配,从而完成节点选择和绑定,节点亲和调度使得Pod对象被吸引到一类特定的节点,而污点的作用则相反,它为节点提供了排斥特定Pod对象的能力。

比如用户希望把 Master 节点保留给 Kubernetes 系统组件使用,或者把一组具有特殊资源预留给某些 Pod,则污点就很有用了,Pod 不会再被调度到 taint 标记过的节点。我们使用 kubeadm 搭建的集群默认就给 master 节点添加了一个污点标记,所以我们看到我们平时的 Pod 都没有被调度到 master 上去:

[root@k8s-01 ~]#  kubectl describe node k8s-01
Name:               k8s-01
Roles:              master
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=master1
                    kubernetes.io/os=linux
                    node-role.kubernetes.io/master=
......
Taints:             node-role.kubernetes.io/master:NoSchedule
Unschedulable:      false
......

其中有一条关于 Taints 的信息:node-role.kubernetes.io/master:NoSchedule,就表示master 节点打了一个污点的标记,其中影响的参数是 NoSchedule,表示 Pod 不会被调度到标记为 taints 的节点,效用标识主要有以下3种类型。

  • NoSchedule:不能容忍此污点的Pod对象不可调度至当前节点,属于强制型约束关系,但添加污点对节点上现存的Pod对象不产生影响。

  • PreferNoSchedule:NoSchedule 的软策略版本,表示尽量不调度到污点节点上去;添加该类效用的污点同样对节点上现存的Pod对象不产生影响。

  • NoExecute:该选项意味着一旦 Taint 生效,如该节点内正在运行的 Pod 没有对应容忍(Tolerate)设置,则会直接被逐出

定义删除污点

任何符合键值规范要求的字符串均可用于定义污点信息:可使用字母、数字、连接符、点号和下划线,且仅能以字母或数字开头,其中键名的长度上限为253个字符,值最长为63个字符。实践中,污点通常用于描述具体的部署规划,它们的键名形如node-type、node-role、node-project或node-geo等,而且一般还会在必要时带上域名以描述一些额外信息,例如node-type.ilinux.io等。kubectl taint命令可用于管理Node对象的污点信息,污点 taint 标记节点的命令如下:

[root@k8s-01 ~]# kubectl taint nodes k8s-02 test=node2:NoSchedule
node/k8s-02 tainted
[root@k8s-01 ~]#

删除污点,指定key和value,则具体删除这一个污点:

[root@k8s-01 ~]# kubectl taint nodes k8s-02 test=node2:NoSchedule-
node/k8s-02 untainted
[root@k8s-01 ~]#

如果只指定具体的key,则删除该key下的所有污点:

[root@k8s-01 ~]# kubectl taint nodes k8s-02 test=node2:NoSchedule
node/k8s-02 tainted
[root@k8s-01 ~]# kubectl taint nodes k8s-02 test=node3:NoExecute
node/k8s-02 tainted

image-20220628172936438

[root@k8s-01 ~]# kubectl taint nodes k8s-02 test-
node/k8s-02 untainted
[root@k8s-01 ~]#

image-20220628173113671

定义容忍度

Pod对象的容忍度通过其spec.tolerations字段添加,根据使用的操作符不同,主要有两种可用形式:一种是与污点信息完全匹配的等值关系;另一种是判断污点信息存在性的匹配方式,它们分别使用Equal和Exists操作符表示。下面容忍度的定义示例使用了Equal操作符,其中tolerationSeconds用于定义延迟驱逐当前Pod对象的时长。

查看官方说明:

[root@k8s-01 ~]# kubectl explain deploy.spec.template.spec.tolerations
KIND:     Deployment
VERSION:  apps/v1

RESOURCE: tolerations <[]Object>

DESCRIPTION:
     If specified, the pod's tolerations.

     The pod this Toleration is attached to tolerates any taint that matches the
     triple <key,value,effect> using the matching operator <operator>.

FIELDS:
   effect       <string>
     Effect indicates the taint effect to match. Empty means match all taint
     effects. When specified, allowed values are NoSchedule, PreferNoSchedule
     and NoExecute.

   key  <string>
     Key is the taint key that the toleration applies to. Empty means match all
     taint keys. If the key is empty, operator must be Exists; this combination
     means to match all values and all keys.

   operator     <string>
     Operator represents a key's relationship to the value. Valid operators are
     Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for
     value, so that a pod can tolerate all taints of a particular category.

   tolerationSeconds    <integer>
     TolerationSeconds represents the period of time the toleration (which must
     be of effect NoExecute, otherwise this field is ignored) tolerates the
     taint. By default, it is not set, which means tolerate the taint forever
     (do not evict). Zero and negative values will be treated as 0 (evict
     immediately) by the system.

   value        <string>
     Value is the taint value the toleration matches to. If the operator is
     Exists, the value should be empty, otherwise just a regular string.

[root@k8s-01 ~]#

operator 的默认值是 Equal

一个容忍度和一个污点相“匹配”是指它们有一样的键名和效果,并且:

  • 如果 operatorExists (此时容忍度不能指定 value),如果一个容忍度的 key 为空且 operator 为 Exists, 表示这个容忍度与任意的 key 、value 和 effect 都匹配,即这个容忍度能容忍任意 taint。
  • 如果 operatorEqual ,则它们的 value 应该相等
  • 空的 effect 匹配所有的 effect
apiVersion: apps/v1
kind: Deployment
metadata:
  name: taint
  labels:
    app: taint
spec:
  replicas: 20
  selector:
    matchLabels:
      app: taint
  template:
    metadata:
      labels:
        app: taint
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - name: http
          containerPort: 80
      tolerations:
      - key: "test"
        operator: "Exists"
        effect: "NoSchedule"

由于node2节点被标记为了污点,所以我们这里要想 Pod 能够调度到改节点去,就需要增加容忍的声明:

      tolerations:
      - key: "test"
        operator: "Exists"
        effect: "NoSchedule"

然后创建上面的资源,查看结果:

image-20220628175401381

如果将key改成test2,则没有pod运行在02节点

image-20220628175428113

k8s内置污点

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

  • node.kubernetes.io/not-ready:节点未准备好。这相当于节点状态 Ready 的值为 "False"。
  • node.kubernetes.io/unreachable:节点控制器访问不到节点. 这相当于节点状态 Ready 的值为 "Unknown"。
  • node.kubernetes.io/memory-pressure:节点存在内存压力。
  • node.kubernetes.io/disk-pressure:节点存在磁盘压力。
  • node.kubernetes.io/pid-pressure: 节点的 PID 压力。
  • node.kubernetes.io/network-unavailable:节点网络不可用。
  • node.kubernetes.io/unschedulable: 节点不可调度。
  • node.cloudprovider.kubernetes.io/uninitialized:如果 kubelet 启动时指定了一个 "外部" 云平台驱动, 它将给当前节点添加一个污点将其标志为不可用。在 cloud-controller-manager 的一个控制器初始化这个节点后,kubelet 将删除这个污点。

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

posted @ 2022-11-29 10:24  天宇轩-王  阅读(392)  评论(0编辑  收藏  举报