<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>节点 · XB 现场笔记</title><link>https://hk.xbcatm.com/zh/tags/%E8%8A%82%E7%82%B9/</link><description>基于 HTTP、DNS、TLS、Caddy、SSH、发布与恢复的可复现运维现场笔记。</description><generator>Hugo</generator><language>zh-CN</language><atom:link href="https://hk.xbcatm.com/zh/tags/%E8%8A%82%E7%82%B9/index.xml" rel="self" type="application/rss+xml"/><item><title>Cordon 与 drain 协调节点维护</title><link>https://hk.xbcatm.com/zh/posts/kubernetes-cordon-drain-node/</link><pubDate>Thu, 03 Feb 2028 00:00:00 +0000</pubDate><guid>https://hk.xbcatm.com/zh/posts/kubernetes-cordon-drain-node/</guid><description>区分调度排除、驱逐过滤、中断预算与工作负载真实终止。</description><content:encoded>&lt;p&gt;Cordon 改变调度资格，drain 协调驱逐并等待 Pod 终止。两条命令都不保证维护期间工作一定保留；应用关闭逻辑、替代容量、存储和中断预算共同决定结果。应把排空视为需要观察的状态，并记录明确例外，而不是从命令名称推导节点已经可以安全关机。&lt;/p&gt;
&lt;figure class="technical-diagram"&gt;&lt;img loading="lazy" src="https://hk.xbcatm.com/visuals/posts-kubernetes-cordon-drain-node.detail.zh.svg" alt="Cordon 存在调度例外。Drain 包含 cordon，并涉及删除过滤、服务端支持的驱逐与终止等待。部分完成结果、中断预算、剩余负载、替代容量和存储都需要检查。" width="560" height="2990"&gt;&lt;figcaption&gt;Cordon 是放置限制，不证明节点已清空。Drain 不是原子事务，也不证明写入或替代副本成功。本轮没有执行原文保留的诊断命令。&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id="cordon-改变未来放置"&gt;Cordon 改变未来放置&lt;/h2&gt;
&lt;p&gt;Cordon 设置节点的不可调度字段，已有 Pod 继续运行，普通的新调度会避开它。Drain 自己也会执行 cordon，因此单独先做一次可以留下观察窗口，但不是必需步骤。Uncordon 重新允许调度，不保证立即出现新副本，也不会修好不健康的 kubelet；恢复前仍应核对节点状态与应用准备情况。&lt;/p&gt;
&lt;p&gt;这项调度限制存在例外。DaemonSet Pod 容忍不可调度条件，直接填写 nodeName 的 Pod 则绕过普通调度选择。具有相应容忍度的其他 Pod 也可能符合放置条件。因此，需要检查真实剩余负载，不能把 cordon 说成阻止所有 Pod 到来的防火墙，更不能只凭不可调度字段就判断节点已经清空。&lt;/p&gt;
&lt;h2 id="drain-具有过滤检查和独立操作"&gt;Drain 具有过滤检查和独立操作&lt;/h2&gt;
&lt;p&gt;Kubectl 先列出 Pod 并检查删除条件。独立 Pod 或管理控制器已经不存在的 Pod 可能需要 force；emptyDir 需要确认丢弃内容；DaemonSet 需要 ignore 选项。镜像 Pod 会被跳过，因为删除 API 表示不能停止 kubelet 根据静态清单管理的底层工作负载，静态程序需要单独规划维护。&lt;/p&gt;
&lt;p&gt;预检查不等于原子事务。真正开始驱逐后，一部分可以成功，另一部分仍在等待或失败；失败时节点也可能已经被 cordon。再次尝试前应重新读取节点与 Pod 状态，不能认为命令非零退出就表示所有东西都保持原样。维护记录要区分哪些请求被接受、哪些进程已经退出，以及哪些副本仍未恢复。&lt;/p&gt;
&lt;p&gt;Ignore-daemonsets 会留下 DaemonSet Pod。Delete-emptydir-data 允许丢失临时卷内容，不负责迁移。Force 允许处理无管理控制器的 Pod，却不会绕过 PodDisruptionBudget。选择参数前要核对归属、数据用途与重建方式；即使一个进程无状态，删除唯一实例也可能影响服务，因此无状态不是足够的安全证明。&lt;/p&gt;
&lt;h2 id="预算约束主动驱逐"&gt;预算约束主动驱逐&lt;/h2&gt;
&lt;p&gt;服务端支持时，drain 使用 Eviction API，并检查适用的中断预算。Disable-eviction 则改为直接删除，绕过这种保护。这个区别非常重要：添加 force 不能解决预算拒绝，而绕过驱逐可能删除维持法定多数或业务可用性所需的副本。不能把几个名字带有强制含义的参数视为同一个开关。&lt;/p&gt;
&lt;p&gt;健康 Pod 可能因为预算没有可中断数量而被阻塞。默认 IfHealthyBudget 还限制已经运行但不健康的 Pod：当所保护应用已经低于健康要求时，驱逐可能等待；这并不表示每个不健康 Pod 都必须先变 Ready。AlwaysAllow 改变这类不健康 Pod 的判定，应结合应用恢复行为选择，而不是为了让终端尽快返回随意启用。&lt;/p&gt;
&lt;p&gt;Drain 会等待终止，并重试部分被拒绝的驱逐。超时默认无限，但认证失败、服务端错误等仍可能结束命令。优雅终止只给应用一个停止窗口，不能证明写入完成或替代副本可用。设置合理的操作期限，有助于把受阻维护暴露出来，而不是让值班人员无限等待没有说明的进度。&lt;/p&gt;
&lt;h2 id="坏掉的样子"&gt;坏掉的样子&lt;/h2&gt;
&lt;p&gt;可中断数量为零是重要线索，不是立即削弱预算的许可。应检查选择到的 Pod、当前和期望健康数、替代容量与存储拓扑。先恢复不健康副本或增加安全容量，可能比降低保护更合理。多节点并行排空会竞争同一预算，还可能加重恢复压力；增加并发不能凭空获得更多可用副本。&lt;/p&gt;
&lt;p&gt;维护不能继续时，应找出具体剩余 Pod 和原因，不要为了看到成功退出而直接换成 disable-eviction。关闭节点之前，仍需验证应用健康，以及静态 Pod、DaemonSet 等剩余类别。普通 drain 成功本来就会留下部分工作负载，操作手册必须解释这些例外如何处理，而不是把它们当作遗漏。&lt;/p&gt;
&lt;h2 id="快速验证"&gt;快速验证&lt;/h2&gt;
&lt;p&gt;以下保留命令本轮没有执行。应明确选择临时集群与目标命名空间。客户端干跑仍读取集群，但不真正提交驱逐，也不验证服务端是否准许驱逐。示例中的 ignore 与 emptyDir 参数会压下对应预检查拒绝，所以不能把这份输出当成未忽略任何问题的完整安全报告。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;kubectl get node node-1 -o jsonpath=&amp;#39;{.spec.unschedulable}{&amp;#34;\n&amp;#34;}&amp;#39;
kubectl drain node-1 --dry-run=client --ignore-daemonsets --delete-emptydir-data
kubectl get pods --field-selector spec.nodeName=node-1 -o custom-columns=NAME:.metadata.name,OWNER:.metadata.ownerReferences[0].kind
kubectl get pdb -A -o custom-columns=NAME:.metadata.name,MIN:.spec.minAvailable,MAX:.spec.maxUnavailable,ALLOWED:.status.disruptionsAllowed
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;节点字段显示 cordon 状态。Pod 列表只涵盖当前命名空间，而且只显示第一个 owner reference；空列或非空列都不能证明完整控制器关系。实际操作前应比较所有命名空间和控制引用。预算列表虽然跨命名空间，却未显示命名空间与选择器，需要逐个匹配实际负载。真实排空仍须在获准环境单独验证，这些检查不能认证其成功。&lt;/p&gt;
&lt;h2 id="来源"&gt;来源&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/"&gt;安全地排空节点&lt;/a&gt;，drain 流程及其与 PodDisruptionBudget 的交互，已核验 2026-10-15。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://kubernetes.io/docs/reference/kubectl/generated/kubectl_drain/"&gt;kubectl drain 参考&lt;/a&gt;，精确的拒绝条件与参数说明，已核验 2026-10-15。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://kubernetes.io/docs/concepts/workloads/pods/disruptions/"&gt;Pod 中断&lt;/a&gt;，主动与被动中断的区别以及驱逐重试，已核验 2026-10-15。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://kubernetes.io/docs/tasks/run-application/configure-pdb/"&gt;Primary reference&lt;/a&gt;，不健康 Pod 驱逐策略，已核验 2026-10-15。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>节点亲和把工作负载放到合适的节点</title><link>https://hk.xbcatm.com/zh/posts/k8s-node-affinity-pins-workloads/</link><pubDate>Thu, 09 Dec 2027 00:00:00 +0000</pubDate><guid>https://hk.xbcatm.com/zh/posts/k8s-node-affinity-pins-workloads/</guid><description>亲和约束让 Pod 落到带指定标签的节点上,把工作负载放进具备相应磁盘、GPU 或隔离属性的机器。</description><content:encoded>&lt;p&gt;节点亲和把工作负载的要求与节点标签匹配起来。它可以要求 NVMe 存储，也可以偏好较新的机型，但不会代替调度器的其他检查。即使没有亲和规则，调度器也会先按资源请求、污点、存储卷约束等条件筛选，再给可行节点评分，并非只比较此刻的空闲容量。&lt;/p&gt;
&lt;p&gt;GPU 放置说明了这一区别：通过设备插件声明 GPU 扩展资源请求，才能把设备数量纳入资源适配；加速器标签可以进一步选择型号。标签本身不会分配 GPU，容忍污点也既不请求设备，又不要求一定进入专用池。必须分别表达资源需求、放置要求和允许进入哪些节点。&lt;/p&gt;
&lt;figure class="technical-diagram"&gt;&lt;img loading="lazy" src="https://hk.xbcatm.com/visuals/posts-k8s-node-affinity-pins-workloads.detail.zh.svg" alt="示意节点 A 和 C 带有 storage=nvme，B 为 storage=hdd。必要 storage=nvme 规则把 B 排除；偏好规则给 A 和 C 的评分增加贡献，本身不排除 B。这些只是标签规则结果，不是实际调度结果。资源适配、其他约束和评分仍然相关；必要标签匹配是必需条件，却不足以保证放置。本图记录较早的单独绘图审阅，不代表真实调度已经验证。" width="720" height="2358"&gt;&lt;figcaption&gt;必要亲和按标签过滤。偏好亲和参与可行节点评分，两者单独都不保证成功放置。&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id="按标签匹配节点"&gt;按标签匹配节点&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;accelerator=nvidia-a100&lt;/code&gt;、&lt;code&gt;storage=nvme&lt;/code&gt; 等标签描述的属性，需要节点供给流程建立并持续维护。替换节点不会自动继承旧节点的任意标签。应先确认新硬件确有这些属性，再附上旧标签；否则规则在形式上匹配，实际选到的机器却不适合业务。&lt;/p&gt;
&lt;p&gt;把标签词表当作 API 管理。重命名一个键会影响所有引用它的清单，过时的值则可能错误描述硬件。校验配置时要对照预期节点清单，包括计划扩容但还未上线的容量。某个标签暂时不存在，可能是供给过程未完成或整个节点池暂时缺席，不一定只是拼写错误。不要让静态校验把这些不同原因混成同一个结论。&lt;/p&gt;
&lt;p&gt;隔离还依赖标签完整性。Kubernetes 1.34 文档建议结合 Node authorizer、NodeRestriction 准入插件和受保护的 &lt;code&gt;node-restriction.kubernetes.io/&lt;/code&gt; 标签键。普通的节点自报合规标签并不是独立安全边界。需要明确谁能修改标签，以及谁能修改工作负载的放置要求；字符串匹配不能代替这些权限检查。&lt;/p&gt;
&lt;h2 id="偏好还是强制"&gt;偏好还是强制&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;requiredDuringSchedulingIgnoredDuringExecution&lt;/code&gt; 排除不满足规则的节点；&lt;code&gt;preferredDuringSchedulingIgnoredDuringExecution&lt;/code&gt; 为可行节点增加带权偏好，其他评分仍可能胜出。两种形式都不保证剩余容量、应用健康或故障韧性。必要条件可能让 Pod 保持 Pending；偏好允许落到不匹配的节点，但所有硬约束仍须通过。&lt;/p&gt;
&lt;p&gt;名称还说明生效时机。采用 IgnoredDuringExecution 时，节点标签后来改变不会驱逐已绑定的 Pod；改变偏好也不会自动重新分布现有副本。应把新的调度决策与当前实际落点分开检查，不能看到新规则就假定全部旧副本已经迁移。&lt;/p&gt;
&lt;p&gt;同时设置 nodeSelector 与必要节点亲和时，两者必须都满足。多个 nodeSelectorTerms 之间是“或”，同一项内的 matchExpressions 是“与”。排查容量之前先核对分组：把替代条件误写成同时成立的条件，可能直接排除整个目标节点池。&lt;/p&gt;
&lt;h2 id="反亲和把副本分开"&gt;反亲和把副本分开&lt;/h2&gt;
&lt;p&gt;Pod 反亲和匹配的是指定命名空间范围与拓扑域中的其他 Pod。&lt;code&gt;kubernetes.io/hostname&lt;/code&gt; 表示节点；标准可用区键是 &lt;code&gt;topology.kubernetes.io/zone&lt;/code&gt;。相关节点需要一致的拓扑标签。准入策略还可能限制必要反亲和使用哪些拓扑键，因此不能假定所有集群都接受必要的可用区规则。&lt;/p&gt;
&lt;p&gt;假设三个副本相互选中，要求主机级分离，却只有两个满足其他条件的节点，那么可能有两个副本运行、第三个 Pending，并非整个工作负载完全无法运行。偏好反亲和允许共置，不能承诺几乎相同的韧性。选择规则时，要结合应用能承受的故障、可用拓扑域与替代容量，不能只看总节点数。&lt;/p&gt;
&lt;h2 id="坏掉的样子"&gt;坏掉的样子&lt;/h2&gt;
&lt;p&gt;Pod 处于 Pending 时，读取完整调度事件和准入后的配置。标签不匹配只是一种可能；资源请求放不下、未容忍污点、卷拓扑以及调度配置中的附加约束，都可能排除节点。观测到 CPU 使用率低，不代表请求账本还有余量。应修复实际报告的约束，而不是先把必要亲和降成偏好。&lt;/p&gt;
&lt;p&gt;已绑定 Pod 的落点不合预期时，要对照它调度时的规则与节点标签。检查原规则是否只是偏好、标签之后是否改变，以及 Pod 是否通过 nodeName 绕过普通调度。当前分布不符意图，不足以说明调度器因容量变化而迁移了既有 GPU 工作负载。&lt;/p&gt;
&lt;h2 id="快速验证"&gt;快速验证&lt;/h2&gt;
&lt;p&gt;以下保留的命令没有重新执行，只是简略的排查起点：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;kubectl get nodes -L accelerator,workload-class --no-headers
kubectl describe pod api-0 | grep -A 8 &amp;#34;Node-Selectors&amp;#34;
kubectl get pods -o wide -l app=api | awk &amp;#39;{print $1, $7}&amp;#39; | sort | uniq -c | sort -rn | head
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;grep 视图可能遗漏亲和细节。最后的管道同时包含唯一 Pod 名和表头，因此不能汇总每节点副本数；固定列号也容易失效。应检查完整的 affinity、nodeSelector、实际 nodeName 及被选择的同伴 Pod，再明确统计拓扑域。以上命令不能证明放置正确或具备韧性。图中记录的是较早的单独绘图审阅；真实调度仍未验证。&lt;/p&gt;
&lt;h2 id="来源"&gt;来源&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/"&gt;Kubernetes 节点亲和文档&lt;/a&gt;，节点亲和语义，已核验 2026-06-10。&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/"&gt;Kubernetes taints 与 tolerations&lt;/a&gt;，说明把 Pod 从专用节点挡开，已核验 2026-09-05。&lt;/li&gt;
&lt;li&gt;&lt;a href="https://v1-34.docs.kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/"&gt;Kubernetes 1.34 placement rules&lt;/a&gt;，标签可信性、条件分组与调度时亲和语义，已核验 2026-10-18。&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/kube-scheduler/"&gt;Kubernetes scheduler&lt;/a&gt;，筛选与可行节点评分，已核验 2026-10-18。&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/manage-gpus/scheduling-gpus/"&gt;Schedule GPUs&lt;/a&gt;，设备资源请求与 GPU 型号标签的区别，已核验 2026-10-18。&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>污点会排斥那些不打算容忍它的 Pod</title><link>https://hk.xbcatm.com/zh/posts/k8s-taints-and-tolerations-reserve-nodes/</link><pubDate>Thu, 25 Feb 2027 00:00:00 +0000</pubDate><guid>https://hk.xbcatm.com/zh/posts/k8s-taints-and-tolerations-reserve-nodes/</guid><description>污点按效果劝退或排斥没有相应容忍度的 Pod。专用节点池还需要放置约束与访问控制。</description><content:encoded>&lt;p&gt;污点排斥没有容忍对应效果的 Pod，容忍度只移除这项障碍，不会强制把负载送到专用硬件。专用节点设计通常还需要标签与必要的节点亲和，再分别检查容量和准入策略。不能把通行资格理解成目的地保证，也不能把容忍度当成工作负载的完整权限边界。&lt;/p&gt;
&lt;figure class="technical-diagram"&gt;&lt;img loading="lazy" src="https://hk.xbcatm.com/visuals/posts-k8s-taints-and-tolerations-reserve-nodes.detail.zh.svg" alt="未容忍的污点效果不同：NoSchedule 阻止新的普通调度，PreferNoSchedule 软性避让，NoExecute 还会触发已有 Pod 驱逐。匹配 NoExecute 的容忍度可用 tolerationSeconds 设置期限。匹配由键、运算符、值和效果决定。Equal 比较值，Exists 忽略指定键的值，空效果覆盖所有效果，合法的空键 Exists 扩展到所有键。硬性污点必须全部被容忍才通过该过滤。容量、必要亲和、设备请求、授权和准入是不同机制。文章 Python 样本只检验匹配逻辑；这里没有验证集群行为。" width="720" height="2968"&gt;&lt;figcaption&gt;容忍度移除匹配污点这一项障碍。效果决定后果，放置与权限仍是其他机制。&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id="给专用者的标记"&gt;给专用者的标记&lt;/h2&gt;
&lt;p&gt;NoSchedule 污点在未被容忍时，阻止普通的新调度，但不移动已有 Pod。这可以把 GPU 等专用节点留给特定负载。不能进一步概括为所有污点都不影响运行中程序：NoExecute 具有驱逐行为，PreferNoSchedule 则只是调度偏好。首先看清 effect，才能判断这次变更会影响新放置还是已有实例。&lt;/p&gt;
&lt;p&gt;污点不是安全隔离。有权提交合适容忍度的主体可能获得池子资格，直接指定 nodeName 还会绕过普通调度检查。准入限制、授权和设备资源请求是另外的控制；一个 GPU 容忍度既没有请求 GPU，也不保证有空闲 GPU。审阅专用池时，需要同时核对谁能修改模板、谁能添加容忍度以及真正需要哪些硬件资源。&lt;/p&gt;
&lt;h2 id="效果决定行为"&gt;效果决定行为&lt;/h2&gt;
&lt;p&gt;NoSchedule 对未容忍的 Pod 构成硬性调度排除；PreferNoSchedule 提供软性避让偏好，单靠它不会让节点完全失去资格。NoExecute 还可能移除已经绑定、却没有匹配容忍度的 Pod。匹配 NoExecute 的容忍度可以带 tolerationSeconds，限定污点出现之后还能停留多久；不写时长与设置短时长具有不同后果。&lt;/p&gt;
&lt;p&gt;执行基于污点驱逐的是相应驱逐控制器，不是调度器把正在运行的进程搬走。这不等同于 kubectl drain，中断预算处理与操作顺序并不相同。维护应选择适合的流程，先评估受影响负载，不要把 NoExecute 当成有同样保护栏的快速排空按钮。容忍过期引发的延迟动作同样需要纳入维护时间线。&lt;/p&gt;
&lt;h2 id="配对即约定"&gt;配对即约定&lt;/h2&gt;
&lt;p&gt;本例演示 Equal 和 Exists 两种运算符，匹配由键、运算符、值及效果共同决定。Equal 比较值，Exists 忽略指定键的值；空 effect 覆盖所有效果。合法的空 key 需要 Exists，并把匹配扩展到所有键。应校验 API 格式，不能让不合法输入在本地模型里悄悄变成通配符；未来或其他版本的运算符也不在本例范围内。&lt;/p&gt;
&lt;p&gt;匹配完成之后，所有剩余硬性污点都必须被容忍，这项调度过滤才通过。但资源、亲和、卷和其他调度插件仍可以拒绝节点。对专用节点标签设置必要亲和，才补上容忍度刻意不提供的目的地限制。许可进入与要求只能进入，是两条不同契约，缺少后一条时专用负载完全可能落到通用节点。&lt;/p&gt;
&lt;p&gt;模型限定为 Kubernetes 1.34 的 Equal/Exists 子集，把省略的字符串值按空字符串比较。它不是完整的 API 校验、默认填充或准入实现。后续版本由特性开关控制的其他操作符，需要另行按版本检查，不能直接当作本模型已经支持。&lt;/p&gt;
&lt;h2 id="坏掉的样子"&gt;坏掉的样子&lt;/h2&gt;
&lt;p&gt;最贵的故障是过宽的容忍度污染了专用池。一条写着 &lt;code&gt;operator: Exists&lt;/code&gt; 却不带值的容忍度，或一份被复制进公共图表的容忍度，会匹配该键下的所有取值，于是普通发布突然有资格落到图形处理器或竞价节点上。预留池被廉价负载占满，而它真正要服务的专用负载反而长期等待调度。这恰好与守护进程集的故障互为镜像：那边是缺了容忍度导致专用节点没有覆盖，这边是多了容忍度导致专用节点失去保护。应审计宽泛容忍度，但它不是 RBAC 授权；公共模板里必须写清键、值与效果。&lt;/p&gt;
&lt;p&gt;第二种故障是把本该用 &lt;code&gt;NoSchedule&lt;/code&gt; 的地方写成了 &lt;code&gt;NoExecute&lt;/code&gt;。前者只拦截新负载，后者会把没有匹配容忍度的运行中负载直接驱离，还可能在 &lt;code&gt;tolerationSeconds&lt;/code&gt; 倒计时结束后动手。一个维护污点若选错效果，就可能意外驱逐生产负载，而从示例里顺手复制的六十秒容忍倒计时，会把一次预留变成一场无人排期的延迟驱逐。与标准 IgnoredDuringExecution 节点亲和不同，污点侧的效果字段自带破坏力，因此维护污点先在单台节点演练，看过负载分布再向整池推广。&lt;/p&gt;
&lt;p&gt;第三种故障是污点与容忍度之间的拼写漂移。节点上的 &lt;code&gt;dedicated=gpu:NoSchedule&lt;/code&gt; 永远遇不上清单里的 &lt;code&gt;dedicated=GPU:NoSchedule&lt;/code&gt;，写着 &lt;code&gt;PreferNoSchedule&lt;/code&gt; 的容忍度也覆盖不了 &lt;code&gt;NoSchedule&lt;/code&gt; 的污点。专用负载于是长期等待调度，事件里写着存在污点但负载未能容忍，而池子表面一切健康。请用查看负载详情的输出对照查看节点污点的输出，逐字比对两侧，再把规范的三元组收敛到同一份文档里，避免口头约定慢慢走样。&lt;/p&gt;
&lt;h2 id="快速验证"&gt;快速验证&lt;/h2&gt;
&lt;p&gt;把下面的代码存为污点容忍模拟脚本并运行。它只用标准库，不触碰任何集群，复刻上文四条匹配规则：按键匹配，按运算符与取值匹配，按效果匹配，软偏好永不拦截。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;tolerates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;taint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tol&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;一条容忍度按键、取值、运算符与效果匹配一条污点。&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;operator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tol&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Equal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Equal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Exists&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;model supports only Equal and Exists&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;tol&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Exists&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;empty key requires Exists&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Exists&amp;#34;&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;tol&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Exists requires an empty value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tol&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;tol&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;taint&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tol&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Equal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Equal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tol&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;taint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;effect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tol&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;effect&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;effect&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;effect&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;taint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;effect&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;schedulable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;taints&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tolerations&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;只有硬性污点全部被容忍时负载才允许调度。&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;taint&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;taints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;taint&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;effect&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;PreferNoSchedule&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nb"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tolerates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;taint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tol&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tolerations&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;：实际 &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;，期望 &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;OK: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; -&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gpu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;dedicated&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;gpu&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;effect&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;NoSchedule&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;exact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;dedicated&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;gpu&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;effect&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;NoSchedule&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;schedulable&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;gpu&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;exact&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;精确匹配允许调度&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;schedulable&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;gpu&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[]),&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;缺失容忍应当拒绝&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;wide&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;dedicated&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Exists&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;effect&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;NoSchedule&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;other&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;dedicated&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;spot&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;effect&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;NoSchedule&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;schedulable&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;wide&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;存在运算符匹配任意取值&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;schedulable&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;gpu&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;dedicated&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;spot&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;effect&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;NoSchedule&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}]),&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;错误取值应当拒绝&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;evict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;maintenance&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;drain&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;effect&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;NoExecute&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;any_effect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;maintenance&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;drain&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;schedulable&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;evict&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;any_effect&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;空效果覆盖任意效果&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;schedulable&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;evict&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[]),&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;未容忍的 NoExecute 不通过调度过滤&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;soft&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;cost&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;cheap&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;effect&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;PreferNoSchedule&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;schedulable&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;soft&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[]),&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;软偏好永不拦截&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;PASS: 7 scenarios; allow and repel verified&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;七个场景锁定关键行为：精确匹配证明放行成立，缺失容忍证明拒绝成立，存在运算符匹配任意取值但错误取值仍被挡回，空效果覆盖驱逐型污点，未容忍的 NoExecute 不通过该过滤，但模型没有执行真实驱逐，而软偏好永不拦截。预期输出以通过信息结尾，说明七组场景成立。&lt;/p&gt;
&lt;p&gt;本轮在 Linux、Python 3.12.14 上重新运行两种语言的实验，并额外验证不合法容忍度、空键与效果错配反例。它只验证匹配逻辑，不验证容量亲和与真实污点。上线前请对照负载事件与节点实际污点列表复核，再改生产配置。&lt;/p&gt;
&lt;h2 id="延伸阅读"&gt;延伸阅读&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hk.xbcatm.com/zh/posts/k8s-node-affinity-pins-workloads/"&gt;节点亲和把工作负载放到合适的节点&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hk.xbcatm.com/zh/posts/k8s-daemonset-runs-everywhere/"&gt;守护进程集在每台符合条件的节点上放一个副本&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="来源"&gt;来源&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/"&gt;Kubernetes 污点与容忍&lt;/a&gt;，说明效果与调度，已核验 2026-10-15。&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/"&gt;Kubernetes 节点亲和&lt;/a&gt;，说明按节点标签匹配负载，已核验 2026-10-15。&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kubernetes/api/v0.34.0/core/v1/types.go"&gt;Kubernetes v1.34.0 core API types&lt;/a&gt;，可省略的字符串值与 Equal/Exists 容忍操作符，已核验 2026-10-18。&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item></channel></rss>