7.7. 污点和容限

理解并使用污点和容限。

7.7.1. 了解污点和容限

通过使用污点(taint),节点可以拒绝调度 pod,除非 pod 具有匹配的容限(toleration)

您可以通过节点规格(NodeSpec)将污点应用到节点,并通过 Pod 规格(PodSpec)将容限应用到 pod。当您应用污点时,调度程序无法将 pod 放置到该节点上,除非 pod 可以容限该污点。

节点规格中的污点示例

apiVersion: v1
kind: Node
metadata:
  name: my-node
#...
spec:
  taints:
  - effect: NoExecute
    key: key1
    value: value1
#...

Pod 规格中的容限示例

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
#...
spec:
  tolerations:
  - key: "key1"
    operator: "Equal"
    value: "value1"
    effect: "NoExecute"
    tolerationSeconds: 3600
#...

污点与容限由 key、value 和 effect 组成。

表 7.1. 污点和容限组件

参数描述

key

key 是任意字符串,最多 253 个字符。key 必须以字母或数字开头,可以包含字母、数字、连字符、句点和下划线。

value

value 是任意字符串,最多 63 个字符。value 必须以字母或数字开头,可以包含字母、数字、连字符、句点和下划线。

effect

effect 的值包括:

NoSchedule [1]

  • 与污点不匹配的新 pod 不会调度到该节点上。
  • 该节点上现有的 pod 会保留。

PreferNoSchedule

  • 与污点不匹配的新 pod 可以调度到该节点上,但调度程序会尽量不这样调度。
  • 该节点上现有的 pod 会保留。

NoExecute

  • 与污点不匹配的新 pod 无法调度到该节点上。
  • 节点上没有匹配容限的现有 pod 将被移除。

operator

Equal

key/value/effect 参数必须匹配。这是默认值。

Exists

key/effect 参数必须匹配。您必须保留一个空的 value 参数,这将匹配任何值。

  1. 如果向 control plane 节点添加了一个 NoSchedule 污点,节点必须具有 node-role.kubernetes.io/master=:NoSchedule 污点,这默认会添加。

    例如:

    apiVersion: v1
    kind: Node
    metadata:
      annotations:
        machine.openshift.io/machine: openshift-machine-api/ci-ln-62s7gtb-f76d1-v8jxv-master-0
        machineconfiguration.openshift.io/currentConfig: rendered-master-cdc1ab7da414629332cc4c3926e6e59c
      name: my-node
    #...
    spec:
      taints:
      - effect: NoSchedule
        key: node-role.kubernetes.io/master
    #...

容限与污点匹配:

  • 如果 operator 参数设为 Equal

    • key 参数相同;
    • value 参数相同;
    • effect 参数相同。
  • 如果 operator 参数设为 Exists

    • key 参数相同;
    • effect 参数相同。

OpenShift Container Platform 中内置了以下污点:

  • node.kubernetes.io/not-ready:节点未就绪。这与节点状况 Ready=False 对应。
  • node.kubernetes.io/unreachable:节点无法从节点控制器访问。这与节点状况 Ready=Unknown 对应。
  • node.kubernetes.io/memory-pressure:节点存在内存压力问题。这与节点状况 MemoryPressure=True 对应。
  • node.kubernetes.io/disk-pressure:节点存在磁盘压力问题。这与节点状况 DiskPressure=True 对应。
  • node.kubernetes.io/network-unavailable:节点网络不可用。
  • node.kubernetes.io/unschedulable:节点不可调度。
  • node.cloudprovider.kubernetes.io/uninitialized:当节点控制器通过外部云提供商启动时,在节点上设置这个污点来将其标记为不可用。在云控制器管理器中的某个控制器初始化这个节点后,kubelet 会移除此污点。
  • node.kubernetes.io/pid-pressure :节点具有 pid 压力。这与节点状况 PIDPressure=True 对应。

    重要

    OpenShift Container Platform 不设置默认的 pid.available evictionHard

7.7.2. 添加污点和容限

您可以为 pod 和污点添加容限,以便节点能够控制哪些 pod 应该或不应该调度到节点上。对于现有的 pod 和节点,您应首先将容限添加到 pod,然后将污点添加到节点,以避免在添加容限前从节点上移除 pod。

流程

  1. 通过编辑 Pod spec 使其包含 tolerations 小节来向 pod 添加容限:

    使用 Equal 运算符的 pod 配置文件示例

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    #...
    spec:
      tolerations:
      - key: "key1" 1
        value: "value1"
        operator: "Equal"
        effect: "NoExecute"
        tolerationSeconds: 3600 2
    #...

    1
    容限参数,如 Taint 和 toleration 组件表中所述。
    2
    tolerationSeconds 参数指定 pod 在被驱除前可以保持与节点绑定的时长。

    例如:

    使用 Exists 运算符的 pod 配置文件示例

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    #...
    spec:
       tolerations:
        - key: "key1"
          operator: "Exists" 1
          effect: "NoExecute"
          tolerationSeconds: 3600
    #...

    1
    Exists 运算符不会接受一个 value

    本例在 node1 上放置一个键为 key1 且值为 value1 的污点,污点效果是 NoExecute

  2. 通过以下命令,使用 Taint 和 toleration 组件表中描述的参数为节点添加污点:

    $ oc adm taint nodes <node_name> <key>=<value>:<effect>

    例如:

    $ oc adm taint nodes node1 key1=value1:NoExecute

    此命令在 node1 上放置一个键为 key1,值为 value1 的污点,其效果是 NoExecute

    注意

    如果向 control plane 节点添加了一个 NoSchedule 污点,节点必须具有 node-role.kubernetes.io/master=:NoSchedule 污点,这默认会添加。

    例如:

    apiVersion: v1
    kind: Node
    metadata:
      annotations:
        machine.openshift.io/machine: openshift-machine-api/ci-ln-62s7gtb-f76d1-v8jxv-master-0
        machineconfiguration.openshift.io/currentConfig: rendered-master-cdc1ab7da414629332cc4c3926e6e59c
      name: my-node
    #...
    spec:
      taints:
      - effect: NoSchedule
        key: node-role.kubernetes.io/master
    #...

    pod 上的容限与节点上的污点匹配。具有任一容限的 pod 可以调度到 node1 上。

7.7.3. 使用计算机器集添加污点和容限

您可以使用计算机器集为节点添加污点。与 MachineSet 对象关联的所有节点都会使用污点更新。容限响应由计算机器设置添加的污点,其方式与直接添加到节点的污点相同。

流程

  1. 通过编辑 Pod spec 使其包含 tolerations 小节来向 pod 添加容限:

    使用 Equal 运算符的 pod 配置文件示例

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    #...
    spec:
      tolerations:
      - key: "key1" 1
        value: "value1"
        operator: "Equal"
        effect: "NoExecute"
        tolerationSeconds: 3600 2
    #...

    1
    容限参数,如 Taint 和 toleration 组件表中所述。
    2
    tolerationSeconds 参数指定 pod 在被驱除前与节点绑定的时长。

    例如:

    使用 Exists 运算符的 pod 配置文件示例

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    #...
    spec:
      tolerations:
      - key: "key1"
        operator: "Exists"
        effect: "NoExecute"
        tolerationSeconds: 3600
    #...

  2. 将污点添加到 MachineSet 对象:

    1. 为您想要污点的节点编辑 MachineSet YAML,也可以创建新 MachineSet 对象:

      $ oc edit machineset <machineset>
    2. 将污点添加到 spec.template.spec 部分:

      计算机器设置规格中的污点示例

      apiVersion: machine.openshift.io/v1beta1
      kind: MachineSet
      metadata:
        name: my-machineset
      #...
      spec:
      #...
        template:
      #...
          spec:
            taints:
            - effect: NoExecute
              key: key1
              value: value1
      #...

      本例在节点上放置一个键为 key1,值为 value1 的污点,污点效果是 NoExecute

    3. 将计算机器设置为 0:

      $ oc scale --replicas=0 machineset <machineset> -n openshift-machine-api
      提示

      您还可以应用以下 YAML 来扩展计算机器集:

      apiVersion: machine.openshift.io/v1beta1
      kind: MachineSet
      metadata:
        name: <machineset>
        namespace: openshift-machine-api
      spec:
        replicas: 0

      等待机器被删除。

    4. 根据需要扩展计算机器:

      $ oc scale --replicas=2 machineset <machineset> -n openshift-machine-api

      或者:

      $ oc edit machineset <machineset> -n openshift-machine-api

      等待机器启动。污点添加到与 MachineSet 对象关联的节点上。

7.7.4. 使用污点和容限将用户绑定到节点

如果要指定一组节点供特定用户独占使用,为 pod 添加容限。然后,在这些节点中添加对应的污点。具有容限的 pod 被允许使用污点节点,或集群中的任何其他节点。

如果您希望确保 pod 只调度到那些污点节点,还要将标签添加到同一组节点,并为 pod 添加节点关联性,以便 pod 只能调度到具有该标签的节点。

流程

配置节点以使用户只能使用该节点:

  1. 为这些节点添加对应的污点:

    例如:

    $ oc adm taint nodes node1 dedicated=groupName:NoSchedule
    提示

    您还可以应用以下 YAML 来添加污点:

    kind: Node
    apiVersion: v1
    metadata:
      name: my-node
    #...
    spec:
      taints:
        - key: dedicated
          value: groupName
          effect: NoSchedule
    #...
  2. 通过编写自定义准入控制器,为 pod 添加容限。

7.7.5. 使用污点和容限控制具有特殊硬件的节点

如果集群中有少量节点具有特殊的硬件,您可以使用污点和容限让不需要特殊硬件的 pod 与这些节点保持距离,从而将这些节点保留给那些确实需要特殊硬件的 pod。您还可以要求需要特殊硬件的 pod 使用特定的节点。

您可以将容限添加到需要特殊硬件并污点具有特殊硬件的节点的 pod 中。

流程

确保为特定 pod 保留具有特殊硬件的节点:

  1. 为需要特殊硬件的 pod 添加容限。

    例如:

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    #...
    spec:
      tolerations:
        - key: "disktype"
          value: "ssd"
          operator: "Equal"
          effect: "NoSchedule"
          tolerationSeconds: 3600
    #...
  2. 使用以下命令之一,给拥有特殊硬件的节点添加污点:

    $ oc adm taint nodes <node-name> disktype=ssd:NoSchedule

    或者:

    $ oc adm taint nodes <node-name> disktype=ssd:PreferNoSchedule
    提示

    您还可以应用以下 YAML 来添加污点:

    kind: Node
    apiVersion: v1
    metadata:
      name: my_node
    #...
    spec:
      taints:
        - key: disktype
          value: ssd
          effect: PreferNoSchedule
    #...

7.7.6. 删除污点和容限

您可以根据需要,从节点移除污点并从 pod 移除容限。您应首先将容限添加到 pod,然后将污点添加到节点,以避免在添加容限前从节点上移除 pod。

流程

移除污点和容限:

  1. 从节点移除污点:

    $ oc adm taint nodes <node-name> <key>-

    例如:

    $ oc adm taint nodes ip-10-0-132-248.ec2.internal key1-

    输出示例

    node/ip-10-0-132-248.ec2.internal untainted

  2. 要从 pod 移除某一容限,请编辑 Pod 规格来移除该容限:

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    #...
    spec:
      tolerations:
      - key: "key2"
        operator: "Exists"
        effect: "NoExecute"
        tolerationSeconds: 3600
    #...