马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
在 Kubernetes 里,Pod 是最小的可调度单元,容器跑在它里面。日常运维中两类状态最让人头疼:一个是 Pending,一个 CrashLoopBackOff。前者是根本没被调度上去,后者是上去了但反复崩溃重启。本文把这两种状态的成因、排查顺序、对应处理办法逐条拆开,并给出可复制的命令和配置片段。
一、两种状态分别是什么意思
1.1 Pending
Pending 表示 Pod 还没被调度到任何节点上。常见原因有三类:集群资源不足、调度约束不满足、存储没准备好。注意 Pending 不代表容器启动失败,它压根还没开始跑。
1.2 CrashLoopBackOff
CrashLoopBackOff 表示 Pod 启动后立刻退出,kubelet 不断尝试重启,随着失败次数增加,重启间隔按指数退避逐渐拉长(10 秒、20 秒、40 秒……)。它反映的是「起来了又挂了」这个循环,和 Pending 是完全不同的阶段。
二、Pending 的成因与排查
2.1 成因归类
- CPU / 内存不足:节点剩余资源达不到 Pod 的 requests 要求。
- 存储不足:PersistentVolume 申请(PVC)无法满足,比如 StorageClass 不对、后端存储没空间。
- 节点亲和性限制:nodeAffinity、nodeSelector、污点容忍(toleration)配置后找不到符合条件的节点。
- 资源请求值过高:requests 写得比实际节点大,一个节点都装不下。
2.2 排查四步
第 1 步,看状态:
kubectl get pods
输出示例:
NAME STATUS READY STATUS RESTARTS AGE
example-pod Pending 0/1 Pending 0 5m
确认是 Pending 后进入下一步。
第 2 步,描述 Pod,重点看 Events:
kubectl describe pod example-pod
Events 段会出现类似:
Events:
Type Reason Age From Message
-------- ------------------ ---- ---- -------
Warning FailedScheduling 5m default-scheduler 0/3 nodes are available: 3 Insufficient cpu.
这句话已经把结论给出来了:3 个节点里 CPU 都不够,调度失败。这是最快的定位手段,比任何日志 都直接。
第 3 步,看节点实际资源:
kubectl top nodes
输出大概是这样:
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
node1 3000m 90% 2000Mi 80%
node2 2000m 70% 1500Mi 60%
某个节点使用率接近 100%,就说明资源确实见底了。这里还有个隐藏点:如果节点上有 kubelet 预留资源(Reserved),即使显示不是 100% 也可能调度不进去,需要结合 kubectl describe node 里的 Allocated resources 一起看。
第 4 步,检查调度策略:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- SSD
如果有这类规则,要确认节点上是否真有 disktype=SSD 标签。requiredDuringScheduling 是硬约束,满足不了就永远 Pending。用 kubectl get nodes --show-labels 核对标签。
2.3 对应解决办法
- 释放资源:删掉不必要的 Pod、把低优先级的 Deployment 缩容。
- 调整 requests / limits:把资源请求值改到实际业务需要的量,别一刀切写大值。
- 扩容集群:云上直接加节点,本地加机器或解锁不可调度(cordon)的节点。
- 改调度策略:放宽或者删掉不合理的亲和性规则;用
kubectl taint nodes <node> <key>- 去掉多余的污点。
- 查网络插件:执行
kubectl get pods --namespace kube-system 确认 CNI 组件是否健康,网络插件异常也会导致 Pod 起不来。
三、CrashLoopBackOff 的成因与排查
3.1 成因归类
- 应用代码错误:启动即抛异常、端口写死、配置读取失败。
- 依赖缺失:缺少动态库、缺少配置文件、环境变量没给全。
- 资源不足:容器启动申请的资源超过节点可用量,被 OOMKill。
- 启动命令错误:command / args 写错,容器一启动就退出。
3.2 排查三步
第 1 步,看状态:
kubectl get pods
NAME STATUS READY STATUS RESTARTS AGE
example-pod CrashLoopBackOff 0/1 Error 5 2m
RESTARTS 数字在涨,说明确实在反复重启。
第 2 步,看上一次崩溃的日志 ,这一步最关键:
kubectl logs example-pod --previous
Error: Cannot find module 'app'
这类输出直接指向问题:缺依赖(模块)导致崩溃。--previous 参数取的是上一次容器实例的日志 ,容器已经重启过的话普通 kubectl logs 是空的,必须用这个参数。
第 3 步,describe 看 Events:
kubectl describe pod example-pod
重点看 Last State 和 Events 两段,能确认是不是 OOMKilled(Reason 里会显示 OOMKilling)。
3.3 对应解决办法
针对缺依赖这类情况,正确的处理是在镜像里把依赖装全;构建阶段就该在 CI 里跑一次冒烟启动测试,避免这类问题进到集群。
资源类问题调整资源声明:
resources:
requests:
memory: "128Mi"
cpu: "500m"
limits:
memory: "256Mi"
cpu: "1"
配置类问题检查 ConfigMap、Secret 挂载和环境变量;启动命令写错就改 command / args。另外,如果业务本身是「跑完就退」的任务型容器,把重启策略改成 Never 或 OnFailure,而不是无脑 Always:
restartPolicy: Always
用 Always 的话,一个本该退出的一次性任务会被无限重启,还会把日志和磁盘慢慢吃满。
四、一个通用的排查顺序
kubectl get pods 先确认真实状态到底是哪个。
kubectl describe pod <pod> 读 Events,大部分问题在这一步就有答案。
kubectl logs <pod> --previous 看崩溃前的输出。
kubectl top nodes / kubectl describe node 判断是不是集群层面的资源问题。
- 以上都看不出,再进容器(
kubectl exec -it)手动跑一遍启动命令,复现本地行为。
熟练之后这套顺序基本两分钟能定位八成问题。剩下的三成靠经验积累,但始终是「看状态 → 看事件 → 看日志 → 看资源」这条主线,跳过任何一步都会多绕圈子。
五、几句提醒
- Pending 是调度问题,CrashLoopBackOff 是应用问题,两者的工具箱完全不一样,别混着查。
- 给 requests 留余量,但别虚高,写太大反而把集群资源浪费掉并制造 Pending。
- 生产环境建议配好 PodDisruptionBudget 和资源配额(ResourceQuota),避免单个团队把节点资源吃光。
- CrashLoopBackOff 期间 Pod 会持续消耗 CPU,长时间不处理会拖垮节点,发现问题要尽快介入。
把 Pod 生命周期和调度机制搞清楚之后,这两种状态就不再是黑盒:Pending 看调度器为什么不选它,CrashLoopBackOff 看容器为什么留不住,方向对了,定位就快。
qidao123.com企服评测-应用市场 编辑提示 |