系统学习 故障排查学习路径:从方法论到系统、网络、数据库与 K8s

nodes-unavailable

调度失败(0/N nodes are available)的定位与修复

现象

Pod 一直 Pending,kubectl describe pod 的 Events 出现类似 0/5 nodes are available: 1 node(s) had untolerated taint, 3 Insufficient cpu, 1 node(s) didn't match Pod's node affinity/selector 的信息。这表示调度器逐个节点执行过滤插件后,没有任何节点通过全部条件。

事件里的数字不是“节点总数减可用数”,而是一个节点可能同时不满足多个条件,所以各项计数之和可以大于 N。后面的 preemption: 0/5 nodes are available 是抢占尝试的独立结果,表示即使驱逐低优先级 Pod 也找不到可行节点。若事件出现 pod has unbound immediate PersistentVolumeClaims,说明存储绑定也参与了过滤,不能只按资源不足处理。

快速定位

先读完整事件,不要只看第一行:

kubectl describe pod <pod> -n <ns> | sed -n '/Events/,$p'
kubectl get events -n <ns> --sort-by=.lastTimestamp | tail -30
kubectl get pod <pod> -n <ns> -o yaml

查看节点状态、污点和可分配资源:

kubectl get nodes -o wide
kubectl describe node <node> | sed -n '/Taints/,/Events/p'
kubectl describe node <node> | sed -n '/Allocated resources/,/Events/p'
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints

检查存储和调度器:

kubectl get pvc -n <ns>
kubectl get pv
kubectl -n kube-system logs <scheduler-pod> --tail=100

再对照 Pod 的调度约束:

kubectl get pod <pod> -n <ns> \
  -o jsonpath='{.spec.nodeSelector}{"\n"}{.spec.affinity}{"\n"}{.spec.tolerations}{"\n"}{.spec.topologySpreadConstraints}{"\n"}'
kubectl get pod <pod> -n <ns> \
  -o jsonpath='{range .status.conditions[*]}{.type}{"="}{.status}{" "}{.reason}{"\n"}{end}'

PodScheduled=False 的 reason 和 message 会直接给出调度失败摘要,适合快速确认是否只有存储或亲和性一个原因。

Insufficient cpu 看的是 requests 与节点 allocatable 的差值,不是节点当前的实际使用率;Allocated resources 展示的也是已分配 requests。排查时不要被监控里的低 CPU 使用率误导。事件中的 reason 通常来自调度过滤插件,但同一插件可能产生多个 reason(如 Insufficient cpu 与 Insufficient memory),逐项核对比凭经验猜测更快。

常见根因

  1. CPU、内存或临时存储 requests 太高,节点 allocatable 扣掉系统保留和已有 Pod 后放不下。
  2. 节点带有 NoSchedule 污点,例如控制面专用、GPU 专用或维护中的节点,Pod 没有对应 toleration。
  3. nodeSelector、nodeAffinity 或 requiredDuringScheduling 规则与节点标签不匹配。
  4. Pod 反亲和、Pod 亲和或 topology spread 约束无法满足,例如要求每个可用区都有副本但节点标签不完整。
  5. PVC 未绑定、PV 的 nodeAffinity 与候选节点冲突,或卷挂载数量达到上限。
  6. hostPort 已被占用,或节点 Pod 数量达到 maxPods 上限。
  7. 节点被 cordon、处于 NotReady,或调度器本身未正常运行。
  8. 集群总空闲资源足够,但碎片化严重,没有任何单节点能容纳整个 Pod。
  9. 低优先级 Pod 无法抢占:没有可驱逐的受害者,或驱逐后仍不满足资源与约束。
  10. LimitRange 为容器注入了默认 requests,实际值比清单里写的大。
  11. 自定义调度器、调度器 profile 或扩展插件配置错误,过滤结果异常。
  12. Pod 请求 GPU 等扩展资源,但节点没有对应资源、device plugin 未上报或资源名写错。

修复

相关命令

参考链接

读完自测

合上页面,先回答,再展开对照。

  1. 0/5 nodes are available 后面的各项计数应该怎么读?
  2. 节点监控显示 CPU 很空闲,为什么调度器仍报 Insufficient cpu?
  3. 有状态 Pod 因 PV 节点亲和性无法调度,应该怎么处理?
答案
  1. 每一项是未通过某个过滤条件的节点数,一个节点可能同时计入多项,所以计数之和可以大于节点总数;后面的抢占结果要单独看。
  2. 调度器比较的是 Pod 的 requests 与节点 allocatable 的剩余量,allocatable 已扣除系统保留、kubelet 预留和已有 Pod 的 requests;实际使用率低不代表可分配额度足够,资源碎片化也会导致放不下。
  3. 检查 PVC 绑定的 PV 的 nodeAffinity 和可用区,把 Pod 调度到匹配节点,或使用能产生正确拓扑的 StorageClass;本地卷无法跨节点迁移,必要时重建 PV 并迁移数据。
微信小程序码:扫码打开命令速查小程序

小程序版

微信扫码,随时查命令