ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

K8s 调度不均衡排查实录:required 和 preferred 选错引发的连锁反应

K8s 调度不均衡排查实录:required 和 preferred 选错引发的连锁反应 上篇我们聊了 Pod CrashLoopBackOff 时日志拿不到的排查思路用 crictl 绕过 kubectl 直接读容器运行时日志。这篇看一个完全不同的方向——Pod 不是起不来是起来了但分布不均衡。场景Deployment 20 副本上线后Pod 全堆在 2 台 Node其余 Node 资源充裕但无 Pod 被调度路径Events 发现 FailedScheduling → 统计匹配标签的 Node 数 → 审阅亲和性配置 → 修正为 preferred → Pod 分布均匀以下排查基于 K8s v1.28使用 apps/v1 API【坐标】— Pod 调度困局20 副本 Deployment 上线新 Pod 全部堆在 node-1 和 node-2——node-3、node-4、node-5 一台 Pod 都没有。资源不够吧第一反应。kubectl top node一看——node-3 CPU 18%、内存 32%node-4、node-5 也类似资源充裕得很。不是资源不够——是 affinity 配置把调度范围锁死了。kubectl describe pod看 Events答案直接贴脸了调度器kube-schedulerK8s 集群的控制面组件负责将 Pod 分配到合适的 Node在 predicate 阶段过滤掉了 3 台 Node。剩下 2 台刚好塞下 20 个副本——但这不是我们想要的效果。金句K8s 不是没有告诉你问题在哪——Events 已经说了只是你没看【分层】— 从 Pod 到集群逐层排查调度问题发生在容器启动前CRI 层容器运行时不涉及跳过。排查从 Pod 层直接进入 Node 层 → 集群层。金句排查 K8s 问题不是在查 Pod——是在查 Pod 所在的整条链路① Pod 层 — Events 缩小范围Events 给出了两条线索node selector 不匹配—— nodeAffinity节点亲和性Pod 声明我只想跑在打了特定标签的 Node 上只匹配了 2 台 Nodepod anti-affinity rules—— podAntiAffinityPod 反亲和性Pod 声明我不想和其他同标签 Pod 挤在同一台 Node 上让同组 Pod 互斥Pod 的 YAML 是这样声明的两个都是requiredDuringSchedulingIgnoredDuringExecution硬约束Pod 调度时必须满足的条件调度器在 predicate 阶段直接过滤不满足的 Node不满足直接报 Unschedulable不会降级尝试——调度器必须满足才能调度不满足就直接判 Unschedulable。② Node 层 — 统计匹配标签的 NodenodeAffinity 要求 Node 有workload-typeai标签。查一下集群里有多少 Node 满足只有 2 台。node-3、node-4、node-5 没有这个标签。那 podAntiAffinity 的作用是什么topologyKey: kubernetes.io/hostname表示同一台 Node 上的 Pod 互斥——每台 Node 最多一个同组 Pod。但 Node 池只有 2 台所以上限就是 2 个 Pod不对requiredDuringScheduling的 podAntiAffinity 只是不允许同组 Pod 在同一台 Node只是说不同 Node 可以各放一个并不限制每台 Node 的数量。但加上 nodeAffinity 后 Node 池只剩 2 台Predicate 阶段nodeAffinity过滤掉 3 台无workload-typeaipodAntiAffinity不作额外过滤没有同 Node 冲突剩下 2 台 → Score 阶段按资源打分 → 均匀分布 → 各 10 个验证 node-3 是否被污点拒绝——kubectl describe node node-3显示 Taints:none。没有污点没有资源压力单纯是workload-typeai标签不匹配调度器在 predicate 阶段就没把它列入候选。【路径】— 下次先跑这套命令排查调度不均衡的核心三板斧# ① 看调度失败原因kubectl describe podpod|grep-A15Events# ② 统计匹配 nodeAffinity 的 Node 数kubectl get nodes-lkeyvalue--show-labels# ③ 看 Pod 跨 Node 分布密度黄金命令kubectl get pods-owide|awk{print $8}|sort|uniq-c|sort-rn异常判断标准Events 出现didnt match pod anti-affinity rulesdidnt match node selector→ 亲和性配置过严两个约束将可用 Node 池的交集缩小了kubectl get nodes -l label匹配数量 3 → nodeAffinity 的 label 覆盖太窄考虑扩标签或改preferredDuringScheduling分布密度uniq -c显示某个 Node 集中度 60% → 调度不均衡检查亲和性 调度器打分策略【定位】— ❌ 两个常见误判Pod 调度不均衡这个现象最容易被带偏的方向有两个。误判 1“加副本就能自然打散”Naive 思路Pod 分布不均 → 加副本让它自己散开。但 podAntiAffinity 只是互斥同 NodeNode 池只有 2 台的话加再多副本也只堆在这 2 台上。有经验的人会说加 Node 就能分散。新 Node 没有workload-typeai标签不匹配 nodeAffinity加了也白加。正确做法查 nodeAffinity 和 podAntiAffinity 的组合范围。两个亲和性叠加可用 Node 是两者调度的交集不是并集。取交集后只剩 2 台——加副本只在 2 台里堆加 Node 不打对应标签仍然进不来。误判 2“requiredDuringScheduling是更安全的选择”很多人直觉认为required 比 preferred 靠谱它能保证规则被执行。但requiredDuringScheduling是硬约束——调度器在 predicate 阶段必须找到满足条件的 Node找不到就直接报Unschedulable不会尝试打分阶段的软性优化。preferredDuringScheduling是软约束——调度器在 scoring 阶段优先推荐满足条件的 Node但如果不满足仍然可以调度到其他 Node。选择规则Node 池 5 台 → 一律用preferredDuringSchedulingNode 池 ≥ 5 台且对分布有硬要求 → 才考虑requiredDuringScheduling但必须评估缩减后的 Node 池是否足够【标点】— 修复 Check-listYAML 修正两个关键改动requiredDuringScheduling→preferredDuringScheduling调度器不再因不匹配而拒绝调度改为优先调度到匹配的 NodepodAntiAffinity 权重 50 nodeAffinity 权重 100尽量走 AI 标签的 Node但如果都满了可以落到其他 Node金句一个 YAML 字段没配不是 K8s 会帮你兜底——是它会按默认值运行而默认值往往不适合你的场景Check-listkubectl describe pod pod | grep -A 15 Events→ 看调度失败原因kubectl get nodes -l keyvalue→ 统计匹配 nodeAffinity 的 Node 数量kubectl get pods -o wide | awk {print $8} | sort | uniq -c | sort -rn→ 看 Pod 跨 Node 分布kubectl get pod pod -o yaml | grep -A 30 affinity→ 审阅完整亲和性配置Node 5 台一律用preferredDuringScheduling≥ 5 台才考虑requiredDuringScheduling金句故障排查的终点不是修好了——是把排查路径写成 check-list附完整命令清单# 排查阶段 # 查看调度 Eventskubectl describe podpod|grep-A15Events# 查看 Pod 分布kubectl get pods-owide# 统计匹配标签的 Nodekubectl get nodes-lworkload-typeai --show-labels# 查看 Node 详情污点、标签、资源kubectl describenodenode# 修复阶段 # 应用修正后的 YAMLkubectl apply-fdeployment-fixed.yaml# 观察分布变化kubectl get pods-owide-w# 持续监控 # 分布密度快速检视kubectl get pods-owide|awk{print $8}|sort|uniq-c|sort-rn下篇我们聊 DaemonSet 更新策略导致节点逐个宕机的排查——当maxUnavailable设错rolling update 会一台接一台地干掉你的 Pod。
返回列表