在 kind 集群里用不可满足的资源请求复现 Pod Pending,练习阅读调度事件

演练目标

环境准备

安装 Docker、kind 和 kubectl,本机至少留 2 GB 空闲内存。整个实验使用独立集群,结束后直接删除。

kind create cluster --name lab-pending
kubectl cluster-info --context kind-lab-pending
kubectl get nodes

minikube 用户可以用 minikube start -p lab-pending 替代,后续命令不变,清理时改用 minikube delete -p lab-pending。确认节点为 Ready 后再注入故障。

注入故障

先创建一个正常 Deployment,再把 requests 调到单节点无法满足的大小:

kubectl create deployment pending-lab --image=nginx:1.27-alpine --replicas=1
kubectl rollout status deployment/pending-lab --timeout=60s
kubectl set resources deployment/pending-lab --requests=cpu=64,memory=128Gi

kind 单节点通常只有几核和几 GB 内存,新的 Pod 会一直 Pending。也可以额外注入 nodeSelector:

kubectl patch deployment pending-lab --type=merge \
  -p '{"spec":{"template":{"spec":{"nodeSelector":{"disk":"nvme"}}}}}'

观察现象

kubectl get pods -l app=pending-lab -o wide
kubectl describe pod -l app=pending-lab | sed -n '/Events:/,$p'
kubectl get events --sort-by=.lastTimestamp | tail -20
kubectl describe node lab-pending-control-plane | sed -n '/Allocated resources/,/Events/p'
kubectl get resourcequota,limitrange -A

预期 Pod 状态为 Pending,NODE 列为 <none>;Events 中出现 0/1 nodes are available: 1 Insufficient cpu 或 1 Insufficient memory;节点已分配资源接近上限。加上 nodeSelector 后还会出现 node(s) didn't match Pod's node affinity/selector。

判断与定位

  1. Pending 的第一手证据是 describe pod 末尾的 Events,调度器会把不可调度的原因写清楚。
  2. 用 describe node 对比 Allocatable 与 Allocated resources。节点 Capacity 不等于可分配量,系统组件会预留一部分。
  3. requests 决定调度,limits 不参与调度。把 limits 调大但 requests 很小,Pod 仍可能被调度后因资源竞争被驱逐。
  4. 容易误判:PVC 使用 WaitForFirstConsumer 时,PVC 在 Pod 调度前一直是 Pending,这是正常行为,不是存储故障。另一个误判是把 Pending 当成容器启动失败;Pending 阶段容器根本没有创建。
  5. 如果 Events 显示 no nodes available,先看节点是否 NotReady,而不是继续调低 requests。

修复

把 requests 调回合理范围,或移除不存在的 nodeSelector:

kubectl set resources deployment/pending-lab --requests=cpu=100m,memory=64Mi
kubectl patch deployment pending-lab --type=json \
  -p '[{"op":"remove","path":"/spec/template/spec/nodeSelector"}]' 2>/dev/null || true
kubectl rollout status deployment/pending-lab --timeout=120s
kubectl get pods -l app=pending-lab -o wide

Pod 应变为 Running 并调度到节点上。真实环境中也可以扩容节点、降低 requests、清理占用资源的 Pod,或调整 affinity/taints。修复后继续观察几分钟,确认没有因为资源竞争再次被驱逐。

清理与回滚

kubectl delete deployment pending-lab --ignore-not-found
kind delete cluster --name lab-pending

如果使用 minikube,执行 kubectl delete deployment pending-lab 后运行 minikube delete -p lab-pending。

复盘

延伸阅读

读完自测

  1. 为什么调大 limits 不一定能让 Pending 的 Pod 调度成功?
  2. WaitForFirstConsumer 模式下 PVC 一直 Pending,是否一定是故障?
  3. describe pod 中应该重点看哪一部分来判断调度失败原因?
答案
  1. 调度器依据 requests 而不是 limits 分配资源;requests 超过节点可分配量时仍然无法调度。
  2. 不一定。该模式会等 Pod 被调度后再绑定卷,没有 Pod 使用 PVC 时 Pending 是预期行为。
  3. 看末尾的 Events,特别是 FailedScheduling 事件中的节点过滤原因。