<?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://www.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://www.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://www.xbcatm.com/zh/posts/kubernetes-cordon-drain-node/</link><pubDate>Thu, 03 Feb 2028 00:00:00 +0000</pubDate><guid>https://www.xbcatm.com/zh/posts/kubernetes-cordon-drain-node/</guid><description>区分调度排除、驱逐过滤、中断预算与工作负载真实终止。</description><content:encoded>&lt;p&gt;Cordon 改变调度资格，drain 协调驱逐并等待 Pod 终止。两条命令都不保证维护期间工作一定保留；应用关闭逻辑、替代容量、存储和中断预算共同决定结果。应把排空视为需要观察的状态，并记录明确例外，而不是从命令名称推导节点已经可以安全关机。&lt;/p&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://www.xbcatm.com/zh/posts/k8s-node-affinity-pins-workloads/</link><pubDate>Thu, 09 Dec 2027 00:00:00 +0000</pubDate><guid>https://www.xbcatm.com/zh/posts/k8s-node-affinity-pins-workloads/</guid><description>亲和约束让 Pod 落到带指定标签的节点上,把工作负载放进具备相应磁盘、GPU 或隔离属性的机器。</description><content:encoded>&lt;p&gt;亲和性是放置匹配：可以&amp;quot;偏好&amp;quot;某个标签也可以&amp;quot;强制&amp;quot;它，再用反亲和把副本散开，换取更强的韧性。硬件从来不会长期均匀——这边一池 GPU，那边高速本地 NVMe，还有合规数据的隔离区——而工作负载悄悄依赖落到对的地方。没有显式规则，调度器只按空闲容量铺，需要 GPU 的 Pod 落到没有 GPU 的节点，在运行时而不是调度时才失败。&lt;/p&gt;
&lt;p&gt;亲和把这次失败前移到它该在的位置。 placements 写成节点上的数据（标签）配 Pod 上的规则，可 review 的配置代替了&amp;quot;哪些节点是特殊的&amp;quot;部落知识。读 manifest 的人一眼看出工作负载必须跑在哪、为什么。&lt;/p&gt;
&lt;h2 id="按标签匹配节点"&gt;按标签匹配节点&lt;/h2&gt;
&lt;p&gt;亲和性规则读取节点标签，让你说明某个 Pod 应该、甚至必须落在带某个标签的节点上。把稳定的标签一次性打在节点上，剩下的就让调度器去匹配。&lt;code&gt;accelerator=nvidia-a100&lt;/code&gt;、&lt;code&gt;storage=nvme&lt;/code&gt;、&lt;code&gt;zone=regulated&lt;/code&gt; 这类标签描述机器的持久属性；因为它们住在 node 对象上，换机器也不影响引用它的 Pod 规则——新硬件打同样的标签，老规则继续生效。&lt;/p&gt;
&lt;p&gt;标签名要像 API 字段一样认真起，因为改一个被广泛引用的标签名，就是跨所有匹配它的 manifest 的迁移。约定小而有文档的词表，胜过每队自创 key：&lt;code&gt;workload-class&lt;/code&gt;、&lt;code&gt;hardware&lt;/code&gt;、&lt;code&gt;compliance&lt;/code&gt; 覆盖大多数家底，再配半页约定文档，免得 GPU 标签拼出五种写法。像校验镜像 tag 一样在 CI 里校验标签——要求一个没有任何节点携带的标签的 Pod，是该死在流水线里的拼写错误，而不是凌晨三点的发布。&lt;/p&gt;
&lt;h2 id="偏好还是强制"&gt;偏好还是强制&lt;/h2&gt;
&lt;p&gt;偏好型规则尽力而行，条件允许就把负载摊开；强制型规则则硬性拒绝那些满足不了标签的 Pod。只有放置真地有讲究才用强制，否则偏好能留给调度器更多弹性。成本模型很直白：强制拿可用性换正确——没有匹配节点有位子，Pod 就 Pending，也不去错的地方；偏好拿正确换可用——落到次优但活着的地方。&lt;/p&gt;
&lt;p&gt;大多数家底想要的是：少数硬约束用强制（有 GPU、合规区、架构），软诉求全用偏好（跨机架摊、优先新型号）。偏好项的权重给软诉求排优先级：便宜容量优先，贵池子当溢出。强制规则每季度 review，因为去年稀缺的硬件今年可能遍地都是；一条没人记得的强制规则，就是&amp;quot;集群明明有空位却不调度&amp;quot;的病因。&lt;/p&gt;
&lt;h2 id="反亲和把副本分开"&gt;反亲和把副本分开&lt;/h2&gt;
&lt;p&gt;反亲和看的是其它 Pod，把一个工作负载的副本摊到不同节点，单个节点故障的杀伤面就变小。配合副本数与 topology 键使用，分离才有意义，而不是表面文章。&lt;code&gt;topologyKey: kubernetes.io/hostname&lt;/code&gt; 跨机器散，&lt;code&gt;topologyKey: topology.zone&lt;/code&gt; 跨故障域散。前者扛死 kubelet，后者扛死机房——按你真正怕的 outage 选键；跨 zone 散要 zone 数不小于副本数才有意义。&lt;/p&gt;
&lt;p&gt;强制反亲和值得跟强制亲和一样的谨慎：三副本配强制主机散开，坏一台没事，但工作负载永远超不过节点数，两节点集群根本装不下。对多数服务，高权重的偏好反亲和拿到几乎全部韧性，又没有调度脆弱。强制形态留给那几个 co-location 真的比 Pending 更糟的：quorum 成员、单 leader 对。&lt;/p&gt;
&lt;p&gt;新规则上线后不要只看能否调度，还要看落点是否符合预期：用一周时间每天按节点标签分组统计一次实际分布，确认 GPU 负载真的留在 GPU 池、合规负载没有外溢。若发现偏好规则长期被容量压力打败，就把缺口量化成扩容需求写进排期；若某条强制规则的匹配节点长期为零，就回头检查标签名是否拼错或已被改名，避免一条僵尸规则悄悄卡住未来的发布。&lt;/p&gt;
&lt;h2 id="坏掉的样子"&gt;坏掉的样子&lt;/h2&gt;
&lt;p&gt;标志性故障是永久 Pending：events 写着 &lt;code&gt;didn't match pod affinity rules&lt;/code&gt;，节点却半空。病因几乎总在标签侧——节点标签没打、改名了、值跟规则对不上（&lt;code&gt;nvme&lt;/code&gt; 对 &lt;code&gt;nvme-ssd&lt;/code&gt;）。&lt;code&gt;kubectl get nodes -L hardware,workload-class&lt;/code&gt; 一张表看清实际标签面，跟 Pod 的要求一对，mismatch 多半当场招供。&lt;/p&gt;
&lt;p&gt;更阴的是满足但错位的放置：偏好规则在容量压力下悄悄输掉，几周下来 GPU 负载漂到共享节点，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;第一条看标签面，第二条看一个 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;/ul&gt;</content:encoded></item><item><title>污点会排斥那些不打算容忍它的 Pod</title><link>https://www.xbcatm.com/zh/posts/k8s-taints-and-tolerations-reserve-nodes/</link><pubDate>Thu, 25 Feb 2027 00:00:00 +0000</pubDate><guid>https://www.xbcatm.com/zh/posts/k8s-taints-and-tolerations-reserve-nodes/</guid><description>污点按效果劝退或排斥没有相应容忍度的 Pod。专用节点池还需要放置约束与访问控制。</description><content:encoded>&lt;p&gt;污点排斥没有容忍对应效果的 Pod，容忍度只移除这项障碍，不会强制把负载送到专用硬件。专用节点设计通常还需要标签与必要的节点亲和，再分别检查容量和准入策略。不能把通行资格理解成目的地保证，也不能把容忍度当成工作负载的完整权限边界。&lt;/p&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;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="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&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://www.xbcatm.com/zh/posts/k8s-node-affinity-pins-workloads/"&gt;节点亲和把工作负载放到合适的节点&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.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;/ul&gt;</content:encoded></item></channel></rss>