在 Kubernetes 生产环境中,最让人头疼的往往不是“功能不会用”,而是集群突然出现异常时,不知该从何入手进行排查。
Node NotReady、Pod Pending 以及 CrashLoopBackOff 这三种状态,几乎覆盖了绝大部分 K8s 日常故障场景。本文将为你梳理一套标准化的排查路径,帮助你高效定位问题根源。
1. Node NotReady:节点为何“离线”?
现象与影响
当你执行 kubectl get nodes 命令时,发现某个节点状态显示为 NotReady。
NAME STATUS ROLES AGE VERSION
node-1 NotReady <none> 45d v1.27.x
此状态将直接导致该节点上的 Pod 被驱逐、新 Pod 无法调度至此,并可能引发业务流量中断。
问题本质
节点状态变为 NotReady,核心原因是集群的 Node Controller 无法持续收到来自该节点 kubelet 组件的心跳报告。问题通常出在节点自身的资源、kubelet 进程或网络连通性上。
排查步骤(按优先级)
-
查看节点详细状态
执行 kubectl describe node <node-name>,重点关注 Conditions 部分,检查是否存在 MemoryPressure(内存压力)、DiskPressure(磁盘压力)或 PIDPressure 等异常,并确认 KubeletReady 条件的状态。
-
检查 Kubelet 服务状态
kubelet 是节点与apiserver通信的代理,它的异常是导致节点失联的直接原因。
systemctl status kubelet # 查看服务状态
journalctl -u kubelet -f # 查看服务日志,排查启动错误或证书过期等问题
常见问题包括:kubelet 进程崩溃、证书过期、无法连接 apiserver(网络或认证问题)。
-
检查节点资源是否耗尽
资源耗尽是导致kubelet异常或节点被标记为压力的常见原因。
- 磁盘空间:使用
df -h 和 df -i 检查磁盘使用率和 inode 使用情况。
- 内存:使用
free -h 检查可用内存。内存不足不仅影响应用,也会导致kubelet等系统组件运行异常。
-
排查网络连通性问题
- 确认节点到 Kubernetes
apiserver 的网络是否通畅。
- 检查防火墙或云服务商安全组规则是否阻止了必要的端口通信。
- 检查 CNI(容器网络接口)插件是否正常工作,Pod 网络是否正常。
经验总结:遇到 Node NotReady,应首先聚焦于节点层面的问题(系统资源、kubelet、网络),而非其上的 Pod。
2. Pod Pending:为何迟迟无法调度?
现象
Pod 状态持续为 Pending,这意味着它尚未被调度到任何一个工作节点上运行。
问题本质
调度器(Scheduler)无法为 Pod 找到一个满足所有约束条件的合适节点。问题出在调度层面,而非容器运行时。
排查路径
-
查看 Pod 事件(Events)
执行 kubectl describe pod <pod-name>,这是最关键的一步。在 Events 部分,调度器通常会给出明确的失败原因,例如:
Warning FailedScheduling 3s (x2 over 3s) default-scheduler 0/5 nodes are available:
1 node(s) had untolerated taint {node.kubernetes.io/disk-pressure: },
2 Insufficient cpu,
2 node(s) didn't match Pod's node affinity/selector.
-
分析常见原因
- 资源不足:Pod 请求(
requests)的 CPU 或内存过大,集群所有节点均无法满足。可通过 kubectl describe node 查看各节点已分配和可分配资源。
- 调度约束不满足:
- 节点选择器(nodeSelector) / 节点亲和性(nodeAffinity):Pod 要求的节点标签不存在。
- 污点与容忍(Taints and Tolerations):目标节点存在 Pod 无法容忍的污点。
- Pod 反亲和性(podAntiAffinity):避免与某些 Pod 同节点运行的规则导致无节点可调度。
- 存储卷(PVC)绑定失败:如果 Pod 使用了持久化存储(PersistentVolumeClaim),出现类似
pod has unbound immediate PersistentVolumeClaims 的事件。需检查 StorageClass 是否存在、PersistentVolume 是否充足或 accessMode 是否匹配。
经验总结:Pod Pending 等同于调度条件问题,首要任务是解读调度器给出的失败事件。
3. CrashLoopBackOff:Pod 为何反复重启?
现象
Pod 状态为 CrashLoopBackOff,这是 Kubernetes 的一种退避重启状态,意味着容器启动后很快失败,然后被系统重启,陷入循环。
问题本质
容器内的应用进程自身启动失败或异常退出。Kubernetes 只是按照重启策略(默认为 Always)不断尝试重启它。
标准排查路径
-
查看容器日志
这是定位应用自身问题的首要方法。
kubectl logs <pod-name> # 查看当前容器日志
kubectl logs <pod-name> --previous # 查看上一个崩溃容器的日志(尤其重要)
日志中常见线索:配置文件解析错误、依赖的服务(如数据库)连接失败、启动参数错误、权限问题等。
-
检查容器启动命令
执行 kubectl describe pod <pod-name>,检查 Containers 部分定义的 command 和 args。确保它们正确无误,并且没有错误地覆盖了镜像中的 ENTRYPOINT。
-
检查探针(Probe)配置(高频故障点)
在云原生应用部署中,存活探针(livenessProbe)和就绪探针(readinessProbe)配置不当是导致 CrashLoopBackOff 的常见原因。
livenessProbe 过于敏感:在应用尚未完全启动或偶发负载高时,探针失败导致容器被杀死重启。
- 未设置合理的初始延迟:
initialDelaySeconds 设置过短,应用还在初始化,探针就开始检查并失败。
- 探针失败触发的是容器重启,而非调度失败,因此需仔细调整探针配置以适应应用的启动特性。
-
检查是否被 OOMKilled
在 kubectl describe pod <pod-name> 的输出中,查看容器上次终止的原因。
Last State: Terminated
Reason: OOMKilled
Exit Code: 137
Exit Code 137 通常表示进程因内存超出限制(limit)而被系统终止。需要调整 Pod 的内存 limits 或优化应用内存使用。
经验总结:CrashLoopBackOff 约等于应用启动失败,排查的第一入口永远是容器日志。
快速定位对照表
为了帮助你更快决策,可以参考以下排查方向对照表:

终极排障原则:分清层次与边界
有效的 Kubernetes 故障排查遵循“先看状态层级,再定责任边界”的原则:
Node NotReady → 问题在节点层(系统、kubelet、网络)。
Pod Pending → 问题在调度层(资源、约束、存储)。
Pod CrashLoopBackOff → 问题在应用层(配置、依赖、探针、资源限制)。
遵循这一原则,可以避免在复杂故障面前陷入盲目。切记,不要一遇到问题就习惯性地执行 kubectl delete pod,这往往会掩盖真正的根因,是排障初期最应避免的操作。
|