节点亲和把工作负载的要求与节点标签匹配起来。它可以要求 NVMe 存储,也可以偏好较新的机型,但不会代替调度器的其他检查。即使没有亲和规则,调度器也会先按资源请求、污点、存储卷约束等条件筛选,再给可行节点评分,并非只比较此刻的空闲容量。

GPU 放置说明了这一区别:通过设备插件声明 GPU 扩展资源请求,才能把设备数量纳入资源适配;加速器标签可以进一步选择型号。标签本身不会分配 GPU,容忍污点也既不请求设备,又不要求一定进入专用池。必须分别表达资源需求、放置要求和允许进入哪些节点。

示意节点 A 和 C 带有 storage=nvme,B 为 storage=hdd。必要 storage=nvme 规则把 B 排除;偏好规则给 A 和 C 的评分增加贡献,本身不排除 B。这些只是标签规则结果,不是实际调度结果。资源适配、其他约束和评分仍然相关;必要标签匹配是必需条件,却不足以保证放置。本图记录较早的单独绘图审阅,不代表真实调度已经验证。
必要亲和按标签过滤。偏好亲和参与可行节点评分,两者单独都不保证成功放置。

按标签匹配节点

accelerator=nvidia-a100、storage=nvme 等标签描述的属性,需要节点供给流程建立并持续维护。替换节点不会自动继承旧节点的任意标签。应先确认新硬件确有这些属性,再附上旧标签;否则规则在形式上匹配,实际选到的机器却不适合业务。

把标签词表当作 API 管理。重命名一个键会影响所有引用它的清单,过时的值则可能错误描述硬件。校验配置时要对照预期节点清单,包括计划扩容但还未上线的容量。某个标签暂时不存在,可能是供给过程未完成或整个节点池暂时缺席,不一定只是拼写错误。不要让静态校验把这些不同原因混成同一个结论。

隔离还依赖标签完整性。Kubernetes 1.34 文档建议结合 Node authorizer、NodeRestriction 准入插件和受保护的 node-restriction.kubernetes.io/ 标签键。普通的节点自报合规标签并不是独立安全边界。需要明确谁能修改标签,以及谁能修改工作负载的放置要求;字符串匹配不能代替这些权限检查。

偏好还是强制

requiredDuringSchedulingIgnoredDuringExecution 排除不满足规则的节点;preferredDuringSchedulingIgnoredDuringExecution 为可行节点增加带权偏好,其他评分仍可能胜出。两种形式都不保证剩余容量、应用健康或故障韧性。必要条件可能让 Pod 保持 Pending;偏好允许落到不匹配的节点,但所有硬约束仍须通过。

名称还说明生效时机。采用 IgnoredDuringExecution 时,节点标签后来改变不会驱逐已绑定的 Pod;改变偏好也不会自动重新分布现有副本。应把新的调度决策与当前实际落点分开检查,不能看到新规则就假定全部旧副本已经迁移。

同时设置 nodeSelector 与必要节点亲和时,两者必须都满足。多个 nodeSelectorTerms 之间是“或”,同一项内的 matchExpressions 是“与”。排查容量之前先核对分组:把替代条件误写成同时成立的条件,可能直接排除整个目标节点池。

反亲和把副本分开

Pod 反亲和匹配的是指定命名空间范围与拓扑域中的其他 Pod。kubernetes.io/hostname 表示节点;标准可用区键是 topology.kubernetes.io/zone。相关节点需要一致的拓扑标签。准入策略还可能限制必要反亲和使用哪些拓扑键,因此不能假定所有集群都接受必要的可用区规则。

假设三个副本相互选中,要求主机级分离,却只有两个满足其他条件的节点,那么可能有两个副本运行、第三个 Pending,并非整个工作负载完全无法运行。偏好反亲和允许共置,不能承诺几乎相同的韧性。选择规则时,要结合应用能承受的故障、可用拓扑域与替代容量,不能只看总节点数。

坏掉的样子

Pod 处于 Pending 时,读取完整调度事件和准入后的配置。标签不匹配只是一种可能;资源请求放不下、未容忍污点、卷拓扑以及调度配置中的附加约束,都可能排除节点。观测到 CPU 使用率低,不代表请求账本还有余量。应修复实际报告的约束,而不是先把必要亲和降成偏好。

已绑定 Pod 的落点不合预期时,要对照它调度时的规则与节点标签。检查原规则是否只是偏好、标签之后是否改变,以及 Pod 是否通过 nodeName 绕过普通调度。当前分布不符意图,不足以说明调度器因容量变化而迁移了既有 GPU 工作负载。

快速验证

以下保留的命令没有重新执行,只是简略的排查起点:

kubectl get nodes -L accelerator,workload-class --no-headers
kubectl describe pod api-0 | grep -A 8 "Node-Selectors"
kubectl get pods -o wide -l app=api | awk '{print $1, $7}' | sort | uniq -c | sort -rn | head

grep 视图可能遗漏亲和细节。最后的管道同时包含唯一 Pod 名和表头,因此不能汇总每节点副本数;固定列号也容易失效。应检查完整的 affinity、nodeSelector、实际 nodeName 及被选择的同伴 Pod,再明确统计拓扑域。以上命令不能证明放置正确或具备韧性。图中记录的是较早的单独绘图审阅;真实调度仍未验证。

来源