当我们执行 kubectl apply 创建 Pod 后,通过 kubectl get pod 发现 Pod 长时间处于 Pending 状态,无法被调度到节点运行。本文结合实际排障经验,系统梳理 Pending 的常见原因、定位思路与解决方法。
问题现象与背景原因
典型现象:
1 | kubectl get pod |
Pending 表示 Pod 已被 API Server 接收、写入 etcd,但调度器(kube-scheduler)还没有为它找到合适的节点。常见根因可分为五类:
- 集群资源不足:节点 CPU / 内存 / 可调度 Pod 数(
--max-pods)已被占满,新 Pod 的requests无法满足。 - 节点污点(Taint)未被容忍:节点打了
NoSchedule/NoExecute污点,而 Pod 没有配置对应的tolerations。 - 节点亲和性 / 反亲和性不满足:
nodeSelector、nodeAffinity或podAntiAffinity规则在现有节点上无法匹配。 - PVC 未绑定:Pod 引用了
persistentVolumeClaim,但对应的 PVC 处于Pending(无可用 PV 或无匹配 StorageClass)。 - 节点全部 NotReady:所有节点处于
NotReady,调度器无节点可选。
排查过程(思路与定位方法)
第一步:看调度失败的具体原因。 describe 的 Events 末尾通常会直接给出 FailedScheduling 的原因,这是最快的定位入口:
1 | kubectl describe pod web-7d8f9c6b4-x2k9p |
关注 Events 区类似如下信息:
1 | Events: |
第二步:根据 FailedScheduling 的提示,分情况深入。 不同提示对应不同方向:
Insufficient cpu / memory / pods→ 资源不足,进入「资源」分支。node(s) had taint ... that the pod didn't tolerate→ 污点问题,进入「污点」分支。didn't match Pod's node affinity/selector→ 亲和性 / 标签不匹配,进入「亲和」分支。persistentvolumeclaim "data" not found或PVC not bound→ 存储问题,进入「PVC」分支。0/N nodes are available: N node(s) were not ready→ 先解决节点 NotReady。
第三步:各分支的确认命令。
资源不足时,查看节点实际可分配资源与已用情况:
1 | kubectl top node |
污点问题时,查看节点上的污点:
1 | kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints |
亲和性 / 标签问题时,核对节点标签与 Pod selector 是否一致:
1 | kubectl get nodes --show-labels |
PVC 问题时,确认 PVC 与 StorageClass 状态:
1 | kubectl get pvc |
提示:调度失败几乎都能从
describe pod的 Events 直接读出原因,不要一上来就盲目加节点,先读 Events。
最终的解决方法
资源不足:降低 Pod 的
resources.requests;横向扩容节点;或清理长期占用资源但未使用的 Pod。若因 Pod 数量上限 触发,可调大 kubelet 的--max-pods或改用 IPVS 并调整 CNI 的 IP 分配。污点未容忍:在 Pod 模板增加对应
tolerations,或由管理员移除节点污点:1
kubectl taint nodes node-1 key=value:NoSchedule-
亲和性 / 标签不匹配:给目标节点打上 Pod selector 期望的标签,或修改
nodeSelector/nodeAffinity使其与现有节点匹配:1
kubectl label nodes node-1 disktype=ssd
PVC 未绑定:确认存在匹配的
StorageClass(动态供给),或手动创建 PV 并绑定;注意 PVC 的storageClassName要与集群中实际存在的名称一致。节点 NotReady:先按「节点 NotReady」专题把节点恢复为 Ready,调度才会继续。
操作命令(可直接复制执行)
下面是一组排查 Pending 的速查命令,按需复制:
1 | # 1. 查看 Pod 状态 |