maxSkew 已设为 4,节点 Pod 总数为何仍相差很大
拓扑分布只统计同namespace的匹配Pod。全局节点数量差不能直接证明maxSkew失效;还需核对硬亲和性、存储条件和节点容量。
多个 namespace 都部署了相同标签的应用,topologySpreadConstraints 设为 maxSkew: 4,统计全体节点却发现 Pod 总数差了几十个。部分副本甚至因为目标节点达到 Pod 数量上限而 Pending。判断 spread 是否生效前,应先确认统计范围是不是待调度 Pod 所在的 namespace。
拓扑分布约束只把同一 namespace 中、符合选择条件的 Pod 纳入匹配数量。相同标签不会让不同 namespace 的副本合并成一个全局计数。这项边界与节点的实际总负载是两回事。
按一个待调度 Pod 重新统计
以下名称和标签是示例:
kubectl -n tenant-a get pod app-2 -o yaml
kubectl -n tenant-a describe pod app-2
kubectl -n tenant-a get pods -l app=worker -o wide
kubectl get nodes -L kubernetes.io/hostname
先读这个 Pod 的实际 topologyKey、labelSelector、maxSkew 与 whenUnsatisfiable,再按相同 namespace 和选择器统计各拓扑域。若设置了 matchLabelKeys,还要核对由它加入的实际匹配条件。不要拿 get pods -A 的节点总数,直接与这个 Pod 的 maxSkew 比较。
DoNotSchedule 下,skew 依据目标拓扑域的匹配数量与合格域中的最小匹配数量计算;minDomains 和域资格条件也会影响它。ScheduleAnyway 则用于调度评分,不提供相同的硬限制。拓扑域可以是节点或 zone,具体取决于 topologyKey,不能一律当作单台服务器。
例如每个 namespace 只有四个匹配副本,且硬性 Pod affinity 要求四个放在同一节点。在合格拓扑域与最小数量允许的情况下,单个 namespace 的 4:0 可以满足 maxSkew: 4。许多 namespace 的四副本组合落到同一节点,节点总数仍可能很不均衡。
Pending 要继续读其他调度条件
spread 满足,不代表节点已经具备运行条件。硬性 Pod affinity、节点亲和性、污点、资源请求、卷拓扑及节点可容纳的 Pod 数量,仍会共同限制候选节点。
如果事件同时出现 Too many pods 和 didn't match pod affinity rules,需要检查已有同组副本的位置,以及允许共置的节点还有没有容量。空闲节点上没有对应存储或不满足硬亲和性时,调度器不能只为降低全局数量差就把剩余副本搬过去。
110 不是所有集群的固定 Pod 上限,应读实际节点的可分配 Pod 数和平台容量配置。提高上限会影响 CNI 地址、节点资源和系统容量,不能仅因为其他节点空闲就提高它。显式 nodeName 导致延迟卷绑定等待的情况另见调度器与 WaitForFirstConsumer。
按真正的放置目标修改设计
如果目标是单个应用在同一 namespace 内分散,先核对副本标签是否匹配自身 selector、各节点是否具备拓扑标签,以及共置条件有没有抵消分散要求。在允许的测试或维护流程中调整相应模板,保留存储和业务的放置前提。
如果目标是不同 namespace 的总体负载接近,需要另外评估资源请求、调度评分、节点池容量及租户放置设计。拓扑 spread 没有可用来跨空间汇总计数的 namespaceSelector 字段;不要添加不存在的字段,也不要为追求数量均衡合并原本需要隔离的租户空间。
新规则主要影响后续调度,不会自动搬迁全部已经运行的 Pod。验收应分别看目标范围内的匹配数量、新 Pod 的调度事件和业务状态,并核对全局容量是否达到原来的运营目标。某次升级后分布变好,也不能单凭结果认定该版本把 namespace 计数改成了全局计数。


