Kubernetes Pod 一直 Pending 排查全流程:从 describe events 到资源、污点、PVC 逐层定位
Kubernetes Pod 一直 Pending 排查全流程:从 describe events 到资源、污点、PVC 逐层定位上线时kubectl apply一把梭,结果kubectl get pods看到 Pod 卡在Pending十分钟不动。Pending 意味着调度器(scheduler)还没给这个 Pod 找到能落脚的节点,或者找到了节点但容器还没起来。它和CrashLoopBackOff(起来了又崩)是两码事——Pending 是根本没被调度上去。这篇按「怎么定位 → 五类常见原因 → 每类怎么修」的顺序,给一套能照着敲的排查流程。第一步:永远先看 describe 的 Events九成 Pending 问题的答案就写在kubectl describe最底下的 Events 里,别急着改 YAML。kubectl describe podpod-name-nnamespace翻到最下面的Events:段,重点看FailedScheduling这行。scheduler 会明确告诉你为什么调度不上去,比如:Events: Type Reason Message ---- ------ ------- Warning FailedScheduling 0/3 nodes are available: 3 Insufficient cpu.这行0/3 nodes are available后面的原因,直接决定你往哪个方向查。下面按最常见的几类 Message 分别讲。原因一:资源不够(Insufficient cpu/memory)Message 长这样:0/3 nodes are available: 3 Insufficient cpu.或Insufficient memory。意思是所有节点的可分配剩余资源都小于你 Pod 的requests。注意关键点:调度看的是requests 之和 vs 节点 allocatable,不是节点当前真实使用率。哪怕节点 CPU 实际只用了 10%,只要已调度 Pod 的 requests 加起来占满了,新 Pod 照样调度不上。先看节点到底还剩多少:kubectl describenodenode-name|grep-A6Allocated resources输出里Requests那列就是已被预定的量:Allocated resources: Resource Requests Limits cpu 3800m (95%) 6 (150%) memory 7Gi (90%) 10GiCPU requests 已经占到 95%,新 Pod 要 500m 自然塞不下。三种修法:# 修法1:调低 Pod 的 requests(前提是真的用不了那么多)resources:requests:cpu:200m# 从 500m 降下来memory:256Mi# 修法2:扩容节点(手动加节点或让 Cluster Autoscaler 自动加)kubectl get nodes# 确认加成功# 修法3:清理占着 requests 却闲置的 Podkubectltoppods-A--sort-bycpu# 找出「requests 高但实际使用低」的最容易被忽略的坑:某个 Pod 把requests.cpu写成了4(4 核),自己占满一台节点。写 requests 要按实际稳态用量估,不要照着 limits 抄。原因二:节点有污点(Taints),Pod 没配容忍(Tolerations)Message:node(s) had untolerated taint {key: value}。节点被打了污点(比如 master 节点默认带node-role.kubernetes.io/control-plane:NoSchedule),普通 Pod 不配 toleration 就被排斥。看节点污点:kubectl describenodenode-name|grepTaints# Taints: node-role.kubernetes.io/control-plane:NoSchedule两种修法。如果这个污点确实该被这个 Pod 容忍(比如 DaemonSet 要跑在所有节点上),给 Pod 加 toleration:tolerations:-key:node-role.kubernetes.io/control-planeoperator:Existseffect:NoSchedule如果是节点被误打了污点(比如之前 drain 后忘了恢复),把污点去掉:# 注意 key 后面加个减号表示删除kubectl taint nodesnode-namenode-role.kubernetes.io/control-plane:NoSchedule-还有一种自动加的污点要小心:节点 NotReady 或磁盘压力大时,K8s 会自动打node.kubernetes.io/not-ready等污点,这时候要去修节点本身,而不是加 toleration 硬塞。原因三:nodeSelector / affinity 把自己框死了Message:node(s) didnt match Pods node affinity/selector。你给 Pod 加了nodeSelector或nodeAffinity,但没有节点带对应的 label。# 比如要求节点有 disktypessd 标签nodeSelector:disktype:ssd排查:看有没有节点真带这个 label。kubectl get nodes --show-labels|grepdisktype# 空 → 没有任何节点带这个标签,自然调度不上修法二选一:给目标节点打上 label,kubectl label nodesnode-namedisktypessd或者放宽约束。硬亲和(requiredDuringScheduling)调不上就直接 Pending,如果只是「优先」而非「必须」,改成软亲和preferredDuringSchedulingIgnoredDuringExecution,匹配不到时也能退而求其次调到别的节点。原因四:PVC 没绑上(pod has unbound immediate PersistentVolumeClaims)Message:pod has unbound immediate PersistentVolumeClaims。Pod 挂了个 PVC,但这个 PVC 没找到能绑定的 PV,Pod 就跟着一起 Pending。先看 PVC 自己的状态:kubectl get pvc-nnamespace# NAME STATUS VOLUME CAPACITY STORAGECLASS# data Pending (空)PVC 也是 Pending,再 describe 它:kubectl describe pvc data-nnamespace常见两种根因:一是storageClassName写错或不存在,动态供应器根本没被触发;二是集群没装 provisioner(比如裸机集群没配 storage class)。kubectl get storageclass# 确认 class 名字存在、且有 default 标记修法:PVC 的storageClassName对上真实存在的 class;裸机环境要么手动创建 PV 静态绑定,要么装个 provisioner(如 local-path-provisioner)。原因五:调度上了但容器起不来(ContainerCreating 卡住)有时 Pod 不是纯 Pending,而是ContainerCreating长时间不动——已经调度到节点了,但 kubelet 在拉镜像或挂卷时卡住。还是 describe 看 Events:Failed to pull image ... ImagePullBackOff:镜像名/tag 写错,或私有仓库缺imagePullSecrets。MountVolume.SetUp failed:卷挂载失败,常是 PV 后端(NFS/云盘)不可达。镜像拉取失败最常见,先手动在节点上验证镜像能不能拉:# 私有仓库要给 Pod 配 imagePullSecretskubectl create secret docker-registry regcred\--docker-server你的仓库--docker-usernameuser--docker-passwordpwd然后在 Pod spec 里引用:spec:imagePullSecrets:-name:regcred一条命令快速缩小范围排查前先用这条把「所有异常 Pod 事件」一次性捞出来,比逐个 describe 快:# 按最近事件排序,直接看到 FailedScheduling 原因kubectl get events-nnamespace--sort-by.lastTimestamp|grep-i-Efail|pending|insufficient小结Pod Pending 的排查心法是「先问 scheduler 为什么调不上去」,而不是瞎改 YAML:第一步永远是kubectl describe pod看 Events 里的FailedScheduling,原因都写在那。Insufficient cpu/memory:比的是 requests 之和 vs 节点 allocatable,不是真实使用率 → 降 requests、扩节点或清闲置 Pod。untolerated taint:节点有污点 → 加 toleration 或删污点,自动打的污点要修节点本身。didn’t match node selector/affinity:约束太死没节点匹配 → 打 label 或把硬亲和改软亲和。unbound PVC:存储没绑上 → 查 storageClass 是否存在、有没有 provisioner。ContainerCreating 卡住:已调度但拉镜像/挂卷失败 → 查镜像名和 imagePullSecrets。一句话记忆点:Pending 看 scheduler,CrashLoop 看容器日志——describe 的 Events 段是这两类问题共同的第一现场。