bigywater.tech
Kubernetes · 46

污点与容忍:NoSchedule、NoExecute 的效果

污点和容忍到底怎么匹配?NoSchedule、PreferNoSchedule、NoExecute 三种效果差在哪?已经在运行的 Pod 会被赶走吗?这篇用一个 5 节点集群,把三种效果、四种容忍写法和“没写也存在的容忍”都逐个跑出来。

0.1 / 8.4 / 不驱逐
NoExecute 污点打上后,无容忍、tolerationSeconds=8、不写秒数的 Pod 被驱逐的时间
2 / 3 / 3
worker 被打上 NoSchedule 之后新建的 8 个副本在 worker2 / worker3 / worker4 上的分布(worker 上 0 个)
300 秒
准入自动给每个 Pod 补上的 not-ready / unreachable 容忍的 tolerationSeconds

NoSchedule 与容忍写法

实测 · 本机执行输出
  先创建 8 个副本(此时没有污点):节点 worker=2 worker2=2 worker3=2 worker4=2
  给 worker 打上 k40=a:NoSchedule 之后创建的 8 个副本:节点 worker2=2 worker3=3 worker4=3(worker 上一个都没有)
  之前那 8 个副本:节点 worker=2 worker2=2 worker3=2 worker4=2(worker 上原来的 Pod 没有被动)
  只能放在被打污点的 worker 上、容忍写成 {key: k40, operator: Equal, value: a, effect: NoSchedule}:Running 4 个
  只能放在被打污点的 worker 上、容忍写成 {key: k40, operator: Equal, value: b, effect: NoSchedule}:全部 Pending;原因:0/5 nodes are available: 2 node(s) had untolerated taint(s), 3 node(s) didn't match Pod's node affinity/selector. preemp
  只能放在被打污点的 worker 上、容忍写成 {key: k40, operator: Exists}:Running 4 个
  只能放在被打污点的 worker 上、容忍写成 {operator: Exists}:Running 4 个

先放 8 个副本(每个 worker 2 个),再给 worker 打 k40=a:NoSchedule。之后新建的 8 个副本 worker 上一个都没有,原来那 2 个也没被动——NoSchedule 只挡新调度。固定去 worker 的 Pod:容忍 Equal 且 value: a 能上;value: b 全部 Pending(2 node(s) had untolerated taint(s), 3 node(s) didn't match Pod's node affinity/selector);operator: Exists 只看 key 也能上;空 key 的 operator: Exists 容忍所有污点。

PreferNoSchedule

实测 · 本机执行输出
  没有污点:12 个副本 节点 worker=3 worker2=3 worker3=3 worker4=3
  worker 打上 PreferNoSchedule 之后:12 个副本 节点 worker2=4 worker3=4 worker4=4
  但如果 Pod 只能去这个节点(nodeSelector):节点 worker=3(软的污点不阻止)

没有污点时 12 个副本 3/3/3/3;worker 打上 PreferNoSchedule 后 12 个副本全落在另外三个节点(4/4/4),worker 上 0 个;但 Pod 如果只能去 worker(nodeSelector),3 个照样调度成功。软污点只影响打分,不阻止调度。

NoExecute

实测 · 本机执行输出
  worker 上有 3 个裸 Pod:no-tol(没有容忍)、tol-8s(容忍 NoExecute,tolerationSeconds=8)、tol-forever(容忍,没写秒数)
    no-tol       在打上 NoExecute 污点后 0.1 秒被驱逐
    tol-8s       在打上 NoExecute 污点后 8.4 秒被驱逐
    tol-forever  25 秒后还在运行

NoExecute 会驱逐已经在运行的 Pod。worker 上 3 个裸 Pod,打上 k40=a:NoExecute 之后:没有容忍的 no-tol 0.1 秒就被驱逐;容忍且 tolerationSeconds: 8 的 8.4 秒被驱逐;容忍但没写 tolerationSeconds 的 25 秒后仍在运行。节点失联时的驱逐(下面第四节的默认容忍)用的是同一套机制。

没写也存在的容忍

实测 · 本机执行输出
  一个什么容忍都没写的 Pod,spec.tolerations 里被准入补上了:node.kubernetes.io/not-ready:NoExecute(tolerationSeconds=300); node.kubernetes.io/unreachable:NoExecute(tolerationSeconds=300)
  nodeSelector 指向控制面,没有对 control-plane 污点的容忍:phase=Pending;nodeName=(未调度);0/5 nodes are available: 1 node(s) had untolerated taint(s), 4 node(s) didn't match Pod's node affinity/select
  nodeSelector 指向控制面,写了对 control-plane 污点的容忍:phase=Running;nodeName=kx-sched-control-plane

创建时没写任何容忍的 Pod,spec.tolerations 里被准入补上了 node.kubernetes.io/not-ready:NoExecute 和 node.kubernetes.io/unreachable:NoExecute,各 tolerationSeconds: 300。控制面节点自带 node-role.kubernetes.io/control-plane:NoSchedule:nodeSelector 指向控制面却没有容忍的 Pod 是 Pending,加上容忍之后 Running 在 kx-sched-control-plane。

分步演示

污点与容忍
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / kind(Docker 里的单节点或多节点真实集群,节点是 Docker Desktop 虚拟机里的容器)/ kubectl;用空的 kubeconfig 之外的独立 kubeconfig,不碰用户自己的集群;计时用 date +%s%N / kubectl 事件时间戳,数字每次运行会有小幅抖动。独立的 5 节点 kind 集群 kx-sched(1 控制面 + 4 个 worker,Kubernetes v1.37.0,与前两篇共用),污点在实验中打上、实验后移除;副本的分布取自每个 Pod 的 spec.nodeName;第 3 节的 3 个 Pod 是用 nodeName 固定在 worker 上的裸 Pod,0.25 秒间隔轮询其是否出现 deletionTimestamp 或消失(第一次运行因为 YAML 缩进写错导致 Pod 没创建、得到了“全被立即驱逐”的假结果,已修正并加了运行断言);第 4 节的控制面用 nodeSelector node-role.kubernetes.io/control-plane 指向;每种情形各一次
    • 没有验证:节点失联(NotReady)时自动打上的 node.kubernetes.io/not-ready 与 unreachable 污点和 300 秒的完整时间线(后面有专门的文章);节点条件污点(memory-pressure 等)的容忍;DaemonSet 自动带的容忍;tolerationSeconds 对已经 Terminating 的 Pod 的影响;污点与亲和的组合;kubectl drain 打的 unschedulable 污点
    京ICP备2026067502号-1京公网安备11010502063487号