Kubernetes 排障手册:Pod 起不来的 10 种状态与定位路径

举报
yd_290186593 发表于 2026/11/05 18:17:18 2026/11/05
【摘要】 Pending、CrashLoopBackOff、ImagePullBackOff、OOMKilled——10 种 Pod 异常状态逐条给判断命令与根因,附三层排查顺序。

Pod 起不来时,kubectl get pods 只会给一行状态词。这行词背后可能是调度失败、镜像拉取失败、探针配置错误、资源超限,也可能是应用自己崩了。这篇按状态词组织,每个给出判断命令和最常见的根因。

第一层:Pod 还没被调度

1. Pending

**含义**:调度器找不到合适的节点。

**判断**:

kubectl describe pod <name> | grep -A 10 Events

**常见根因**:

| Events 里的关键词 | 根因 |

|---|---|

| Insufficient cpu / memory | 节点资源不足 |

| node(s) had taint | 节点有污点,Pod 没有 toleration |

| node(s) didn't match node selector | nodeSelector 写错 |

| node(s) didn't match Pod's node affinity | affinity 规则过严 |

| persistentvolumeclaim not found | PVC 不存在 |

| pod has unbound immediate PersistentVolumeClaims | PVC 没有绑定 PV |

**快速验证**:

# 看节点剩余资源
kubectl describe nodes | grep -A 5 "Allocated resources"

# 看节点污点
kubectl get nodes -o json | jq '.items[] | {name: .metadata.name, taints: .spec.taints}'

第二层:调度了但容器起不来

2. ImagePullBackOff / ErrImagePull

**含义**:镜像拉不下来。

**判断**:

kubectl describe pod <name> | grep -A 5 "Failed"

**四种根因**:

1. **镜像名或 tag 拼错** —— 最常见。注意 `latest` 在某些仓库被禁用

2. **私有仓库没有 imagePullSecrets**

3. **仓库凭证过期**

4. **节点无法访问仓库**(内网环境、防火墙)

**验证镜像是否可拉**:

# 在节点上直接试
crictl pull <image>
# 或
docker pull <image>

**修复私有仓库**:

kubectl create secret docker-registry regcred \
  --docker-server=<registry> \
  --docker-username=<user> \
  --docker-password=<pass>

# Pod spec 里引用
imagePullSecrets:
  - name: regcred

3. CreateContainerConfigError

**含义**:容器配置有问题,通常是引用的 ConfigMap/Secret 不存在。

**判断**:

kubectl describe pod <name> | grep -i "configmap\|secret\|error"

**常见根因**:

- ConfigMap 名字拼错

- Secret 在错误的 namespace(Secret 不能跨 namespace 引用)

- 引用的 key 不存在

**验证**:

kubectl get configmap <name> -n <ns>
kubectl get secret <name> -n <ns> -o jsonpath='{.data}'

4. RunContainerError

**含义**:容器创建成功但启动进程失败。

**判断**:

kubectl logs <name> --previous

**常见根因**:

- entrypoint 或 command 写错

- 镜像里没有该可执行文件

- 工作目录不存在

第三层:容器起来了但反复退出

5. CrashLoopBackOff

**含义**:容器启动后崩溃,kubelet 按指数退避重启(10s → 20s → 40s ... 最多 5 分钟)。

**判断顺序**:

# 1. 看当前日志
kubectl logs <name>

# 2. 看上次崩溃前的日志(关键)
kubectl logs <name> --previous

# 3. 看退出码
kubectl describe pod <name> | grep "Last State"

**退出码对照**:

| 退出码 | 含义 |

|---|---|

| 0 | 正常退出(说明进程跑完就结束了,可能是配置成 Job 而不是 Deployment) |

| 1 | 应用错误(最常见,看日志) |

| 137 | SIGKILL,通常是被 OOMKilled 或超时 |

| 143 | SIGTERM,被优雅终止 |

| 139 | 段错误 |

**最容易忽略的**:退出码 0 的 CrashLoop —— 应用正常运行完就退出了。这说明它本该是 Job/CronJob,不是 Deployment。

6. OOMKilled

**含义**:容器内存超过 limit 被杀。

**判断**:

kubectl describe pod <name> | grep -A 3 "Last State"
# 输出里会有 Reason: OOMKilled

**根因分析**:

# 看实际用了多少
kubectl top pod <name>

# 看 limit 设置
kubectl get pod <name> -o jsonpath='{.spec.containers[*].resources}'

**注意 JVM 类应用的坑**:容器 limit 是 512Mi,但 JVM 默认堆按宿主机内存算,可能开到 2G,直接被 kill。必须显式设置:

-XX:MaxRAMPercentage=75.0

7. Terminating(卡住不消失)

**含义**:Pod 收到删除请求但无法终止。

**判断**:

kubectl get pod <name> -o jsonpath='{.metadata.deletionTimestamp}'
kubectl describe pod <name> | grep -i finalizer

**三种根因**:

1. **finalizer 未清理**(最常见)

2. **preStop hook 卡住**

3. **节点失联**(NotReady 节点的 Pod 无法正常删除)

**强制删除(慎用)**:

kubectl delete pod <name> --grace-period=0 --force

强制删除后如果 Pod 仍在,说明是 API Server 与 kubelet 状态不一致,需要清理 etcd 里的记录或重启 kubelet。

第四层:Pod Running 但不可用

8. Running 但 READY 0/1

**含义**:容器在跑,但 readinessProbe 没通过,所以不接收流量。

**判断**:

kubectl describe pod <name> | grep -A 5 "Readiness"

**常见根因**:

| 现象 | 根因 |

|---|---|

| connection refused | 应用还没开始监听,initialDelaySeconds 太短 |

| HTTP 404 | probe 路径写错 |

| timeout | 应用响应慢,timeoutSeconds 太小 |

| 一直失败但应用正常 | probe 端口写错(写成了容器端口而非应用端口) |

**调试技巧**:

# 进容器手动测探针
kubectl exec -it <name> -- curl -v localhost:8080/health

9. Evicted

**含义**:节点资源压力大,kubelet 驱逐了 Pod。

**判断**:

kubectl describe pod <name> | grep -i "evict\|pressure"
kubectl get events --field-selector reason=Evicted

**根因**:节点磁盘、内存或 PID 达到驱逐阈值。

**验证**:

kubectl describe node <node> | grep -A 8 "Conditions"
# 看 MemoryPressure / DiskPressure / PIDPressure

10. Completed(意外完成)

**含义**:容器正常退出且不需要重启(restartPolicy: OnFailure 或 Never)。

**问题**:如果这是 Deployment 的 Pod,说明配置错了 —— Deployment 期望长期运行。

**修复**:改用 Job 或 CronJob。

三层排查顺序

遇到 Pod 异常,按这个顺序查,能覆盖 90% 情况:

# 第 1 层:状态和事件
kubectl get pod <name> -o wide
kubectl describe pod <name>          # 看 Events 段落

# 第 2 层:日志
kubectl logs <name>
kubectl logs <name> --previous       # 崩溃前的日志

# 第 3 层:进容器
kubectl exec -it <name> -- sh
kubectl debug -it <name> --image=busybox

一张速查表

| 状态 | 第一命令 | 最常见根因 |

|---|---|---|

| Pending | describe 看 Events | 资源不足 / 污点 / PVC |

| ImagePullBackOff | describe 看 Failed | 镜像名错 / 无凭证 |

| CreateContainerConfigError | describe 看 error | ConfigMap/Secret 缺失 |

| CrashLoopBackOff | logs --previous | 应用报错 / 退出码 0 |

| OOMKilled | describe 看 Last State | limit 太小 / JVM 堆 |

| Terminating | 看 finalizer | finalizer 未清理 |

| READY 0/1 | describe 看 Readiness | 探针配置错误 |

| Evicted | get events | 节点资源压力 |

小结

Pod 排障的核心不是记住 10 种状态,而是理解**三个阶段**:

1. **调度阶段**(Pending)—— 资源、亲和性、PVC

2. **启动阶段**(ImagePull / ConfigError / RunContainerError)—— 镜像、配置、命令

3. **运行阶段**(CrashLoop / OOM / Probe / Evicted)—— 应用、资源、健康检查

每个阶段的排查工具不同:调度看 Events,启动看 describe,运行看 logs。

真正省时间的做法是**先看 describe 的 Events 段落**——它直接告诉你 kubelet 的判断,比猜快得多。

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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