K8s Pod 一直处于 Pending 状态排查(调度失败)
2026-08-11 00:53:03 # Kubernetes

当我们执行 kubectl apply 创建 Pod 后,通过 kubectl get pod 发现 Pod 长时间处于 Pending 状态,无法被调度到节点运行。本文结合实际排障经验,系统梳理 Pending 的常见原因、定位思路与解决方法。

问题现象与背景原因

典型现象:

1
2
3
kubectl get pod
NAME READY STATUS RESTARTS AGE
web-7d8f9c6b4-x2k9p 0/1 Pending 0 5m

Pending 表示 Pod 已被 API Server 接收、写入 etcd,但调度器(kube-scheduler)还没有为它找到合适的节点。常见根因可分为五类:

  1. 集群资源不足:节点 CPU / 内存 / 可调度 Pod 数(--max-pods)已被占满,新 Pod 的 requests 无法满足。
  2. 节点污点(Taint)未被容忍:节点打了 NoSchedule / NoExecute 污点,而 Pod 没有配置对应的 tolerations
  3. 节点亲和性 / 反亲和性不满足nodeSelectornodeAffinitypodAntiAffinity 规则在现有节点上无法匹配。
  4. PVC 未绑定:Pod 引用了 persistentVolumeClaim,但对应的 PVC 处于 Pending(无可用 PV 或无匹配 StorageClass)。
  5. 节点全部 NotReady:所有节点处于 NotReady,调度器无节点可选。

排查过程(思路与定位方法)

第一步:看调度失败的具体原因。 describe 的 Events 末尾通常会直接给出 FailedScheduling 的原因,这是最快的定位入口:

1
kubectl describe pod web-7d8f9c6b4-x2k9p

关注 Events 区类似如下信息:

1
2
3
4
Events:
Type Reason Message
---- ------ -------
Warning FailedScheduling 0/3 nodes are available: 3 Insufficient memory.

第二步:根据 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 foundPVC not bound → 存储问题,进入「PVC」分支。
  • 0/N nodes are available: N node(s) were not ready → 先解决节点 NotReady。

第三步:各分支的确认命令。

资源不足时,查看节点实际可分配资源与已用情况:

1
2
kubectl top node
kubectl describe node node-1 | sed -n '/Allocated resources/,/Events/p'

污点问题时,查看节点上的污点:

1
2
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
kubectl describe node node-1 | grep -A3 Taints

亲和性 / 标签问题时,核对节点标签与 Pod selector 是否一致:

1
2
kubectl get nodes --show-labels
kubectl get pod web-7d8f9c6b4-x2k9p -o jsonpath='{.spec.nodeSelector}'

PVC 问题时,确认 PVC 与 StorageClass 状态:

1
2
3
kubectl get pvc
kubectl describe pvc data
kubectl get storageclass

提示:调度失败几乎都能从 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 1. 查看 Pod 状态
kubectl get pod -o wide

# 2. 查看调度失败事件(核心)
kubectl describe pod <pod-name> | grep -A20 Events

# 3. 节点资源水位
kubectl top node
kubectl describe node <node-name> | sed -n '/Allocated resources/,/Events/p'

# 4. 节点污点一览
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints

# 5. 节点标签(核对亲和 / selector)
kubectl get nodes --show-labels

# 6. PVC 绑定情况
kubectl get pvc
kubectl describe pvc <pvc-name>

# 7. 移除导致无法调度的污点
kubectl taint nodes <node-name> <key>=<value>:NoSchedule-

# 8. 给节点打标签以匹配 nodeSelector
kubectl label nodes <node-name> <key>=<value>