CCE Pod 一直 Pending 或 CrashLoopBackOff:按调度、镜像、探针三层排查的 7 步

举报
yd_293948692 发表于 2026/11/07 12:17:06 2026/11/07
【摘要】 CCE Pod 卡在 Pending 或 CrashLoopBackOff 时,先分层定位再动手:按调度、镜像、探针三层,用 kubectl 事件、日志与探针验证 7 步排查,附验证标准与常见坑清单。

一、背景与问题

在华为云云容器引擎 CCE 里部署一个新版本后,最常见的两种“卡住”状态是 Pending 和 CrashLoopBackOff:前者是 Pod 一直等不到节点来运行,后者是容器反复启动、退出、再启动。两种状态的表象很像“服务起不来”,但根因完全不在同一层。直接删 Pod、重启 Deployment 往往只能让计数器归零,几分钟后又回到原样。

正确的做法是先分层定位:Pending 先查调度层,CrashLoopBackOff 先查镜像与应用层,最后再查探针与资源层。本文按这个顺序给出 7 步排查法,每一步都有可执行的命令和“做完算通过”的标准。

二、前置条件

  1. 已开通 CCE 集群,集群状态正常,节点处于 Ready。
  2. 本地已安装 kubectl,并已在 CCE 控制台的集群详情页下载 kubeconfig,完成 kubectl cluster-info 能正常返回。
  3. 知道出问题的工作负载所在的命名空间和名称,下文用 <namespace>、<deployment>、<pod> 代替,请替换为实际值。
  4. 操作前先确认这是一次可回滚的变更:Deployment 的镜像、副本数、资源请求可以改回去,不要直接删生产命名空间。

三、分步操作

第 1 步:看清现状,先看事件再动手

kubectl get pods -n <namespace> -o wide
kubectl get events -n <namespace> --sort-by=.lastTimestamp | tail -n 30

先记下三件事:Pod 的 STATUS、RESTARTS 次数、所在 NODE。RESTARTS 在短时间内快速增长,基本是应用或探针问题;NODE 一直为空,基本是调度问题。事件(Events)里经常直接写着原因,例如 FailedScheduling、Failed to pull image、BackOff,先读事件能省掉一半弯路。

第 2 步:Pending——查节点资源与调度约束

kubectl describe pod <pod> -n <namespace>
kubectl get nodes
kubectl top nodes
kubectl describe node <node-name>

在 describe pod 的 Events 末尾找调度失败的原因,常见有三类:节点 CPU 或内存不足、Pod 的 resources.requests 要得太多、节点选择器或污点把所有节点都排除了。先看 kubectl top nodes 确认节点真实余量,再看 describe node 的 Allocated resources 一栏。

处理办法按原因区分:资源不足就先降低 requests 或给集群扩一个节点;requests 是照抄模板写大的,改回与实际用量接近的值;用了 nodeSelector 或 affinity,先确认标签确实打在节点上,命令是 kubectl get nodes --show-labels。

第 3 步:Pending——查存储与镜像拉取

如果调度已经成功但容器迟迟不进入 Running,还要查两处:持久卷和镜像。

kubectl get pvc -n <namespace>
kubectl describe pod <pod> -n <namespace> | grep -A 5 -i "volume\|mount"

PVC 一直处于 Pending,说明存储类或容量配额有问题,先不要反复重启 Pod。镜像拉取失败会在 Events 里出现 ImagePullBackOff,多半是镜像地址、标签写错,或私有镜像仓库的访问凭证不对。先用 kubectl get pods -n <namespace> 确认状态,再到 CCE 控制台核对镜像地址,改镜像要用 kubectl set image 而不是手改 Pod。

第 4 步:CrashLoopBackOff——先看日志,再看上一次的日志

kubectl logs <pod> -n <namespace>
kubectl logs <pod> -n <namespace> --previous
kubectl describe pod <pod> -n <namespace>

容器已经退出时,logs 可能什么都没有,这时 --previous 是关键,它看的是上一个已经退出容器的日志。日志里的第一条报错往往就是根因:配置文件路径不对、环境变量缺失、数据库连不上、端口被占用。describe pod 的 Last State 一栏会写退出码,退出码 1 多半是应用报错,137 多半是被 OOMKilled,也就是内存超了。

第 5 步:CrashLoopBackOff——查镜像与启动命令

kubectl set image deployment/<deployment> <container>=<image>:<tag> -n <namespace>
kubectl rollout status deployment/<deployment> -n <namespace>

排查重灾区是三处:镜像标签写成了不存在的版本、镜像里根本没有要启动的命令、启动命令依赖的文件没有打进镜像。先在本地或测试环境用同一条镜像手动跑一次,确认它能启动;再核对 Deployment 里 command 和 args 是否与镜像的入口一致。改镜像后用 rollout status 观察滚动更新是否完成,不要同时改多个变量。

第 6 步:查探针与资源限制

探针配得太急,是“应用明明启动了、Pod 却一直重启”的常见原因。先把探针的配置读出来:

livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 10
  periodSeconds: 10
readinessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 5

如果应用启动本身就要 20 秒以上,而 initialDelaySeconds 只给了 5 秒,探针会在应用还没准备好时就判定失败并重启容器。先把 initialDelaySeconds 放宽到大于应用实测启动时间,再进容器里亲手验证探针地址:

kubectl exec -it <pod> -n <namespace> -- sh
curl -v http://localhost:8080/healthz

curl 返回 200 才算探针地址真实可用;返回 404 或连接拒绝,说明探针路径或端口写错了。资源限制也要同时看:limits.memory 设得比应用峰值还小,容器会被 OOMKilled,表现为退出码 137,这时要调大 limits,而不是反复重启。

第 7 步:确认修复并做滚动验证

kubectl apply -f deployment.yaml
kubectl rollout status deployment/<deployment> -n <namespace>
kubectl get pods -n <namespace> -w

修复后不要只看一次结果:先等 rollout status 显示成功,再用 -w 观察至少 3 分钟,确认新 Pod 持续 Running、RESTARTS 不再增长、旧 Pod 已被正常回收。随后用业务方式验证一次,例如访问 Service 的 ClusterIP 或通过负载均衡访问业务接口,返回正常才算完成。

四、验证方法

完成后的状态应当同时满足以下四条,缺一不可:

  1. kubectl get pods -n <namespace> 里目标 Pod 的 STATUS 是 Running,READY 是 1/1 或 2/2。
  2. 观察 3 分钟以上,RESTARTS 不再增长。
  3. kubectl get events -n <namespace> --sort-by=.lastTimestamp 里不再出现新的 FailedScheduling、ImagePullBackOff、BackOff 事件。
  4. 通过 Service 或负载均衡访问业务接口一次,返回符合预期的结果。

五、常见坑

  1. 只删 Pod 不改根因。Deployment 会按模板重建一个一模一样的 Pod,问题原样复现。
  2. 同时改镜像、资源、探针三个变量。改完好了也不知道是哪一个起的作用,下次还会踩同一个坑。
  3. 探针地址只在本地验证过。容器内的监听地址、端口、路径只要有一处不同,探针就会误判。
  4. 把 requests 和 limits 混为一谈。requests 决定能不能调度上去,limits 决定会不会被杀掉,两者要分别配。
  5. 忽略事件的时间。Events 只保留一段时间,排障时先看最新事件,不要拿昨天的事件套今天的问题。
  6. 私有镜像凭证过期。镜像地址没变,突然拉取失败时,先核对镜像凭证的有效期和命名空间里的 Secret 是否还在。

六、小结清单

  • Pending:先读 Events,再看节点余量、requests、节点选择器与污点,最后看 PVC 与镜像拉取。
  • CrashLoopBackOff:先看本次与上一次日志,再看退出码与镜像、启动命令,最后看探针与内存限制。
  • 探针:initialDelaySeconds 要大于应用实测启动时间,探针地址要在容器内用 curl 亲手验证。
  • 改动一次只动一个变量,改完用 rollout status 与 3 分钟观察确认,业务访问正常才算完成。

只要按“调度、镜像、探针”三层顺序走,大多数 Pending 与 CrashLoopBackOff 都能在半小时内定位到具体原因,而不是靠反复重启碰运气。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。