做 Kubernetes 运维的同学,十有八九都遇到过 Pod 各种状态异常的问题。
半夜三点收到告警,发现 Pod 在 CrashLoopBackOff 里挣扎,这种场景估计大家都经历过。
本文结合实战经验,梳理一套通用的 Pod 故障排查流程,帮你快速定位问题。
一、先看懂 Pod 状态
Pod 的状态是排查的起点,不同状态对应不同的排查方向。
arduino
kubectl get pods -o wide
重点关注 STATUS 和 RESTARTS 两列:
| 状态 | 含义 | 紧急程度 |
|---|---|---|
| CrashLoopBackOff | 容器持续崩溃重启 | 🔴 立刻处理 |
| ImagePullBackOff | 镜像拉取失败 | 🔴 立刻处理 |
| Pending | Pod 未被调度 | 🟡 30分钟内处理 |
| Running 但不健康 | 容器在跑但服务异常 | 🔴 立刻处理 |
| Evicted | 节点资源不足被驱逐 | 🟡 30分钟内处理 |
二、CrashLoopBackOff:容器启动失败
这是最常见的故障状态,背后原因可能有多种。
排查步骤
1. 查看容器日志(最先做)
ini
# 查看当前日志
kubectl logs <pod-name> --tail=100
# 查看上一次崩溃的日志(关键!)
kubectl logs <pod-name> --previous
# 实时追踪日志
kubectl logs <pod-name> -f
2. 查看 Pod 事件
sql
kubectl describe pod <pod-name>
重点看 Events 部分,Kubernetes 会在这里给出失败原因的描述。
3. 常见根因分析
应用启动失败
makefile
# 典型错误:连接数据库超时
Error: Connection refused: mysql-service:3306
解决方案:检查依赖服务是否就绪,配置合理的启动超时时间。
OOMKilled(内存溢出)
vbnet
Exit Code: 137
OOMKilled: true
解决方案:合理设置 resources limits
vbnet
Exit Code: 137
OOMKilled: true
健康检查配置不当
yaml
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30 # 关键:避免冷启动误杀
periodSeconds: 5
failureThreshold: 3
三、ImagePullBackOff:镜像拉取失败
这个问题排查相对简单。
1. 检查镜像地址
ini
# 查看 Pod 使用的镜像
kubectl get pod <pod-name> -o jsonpath='{.spec.containers[].image}'
2. 常见原因
| 原因 | 现象 | 解决方案 |
|---|---|---|
| 镜像名拼写错误 | ErrImagePull | 修正镜像地址 |
| 私有仓库无权限 | ImagePullBackOff | 配置 imagePullSecrets |
| 节点网络不通 | ImagePullBackOff | 检查网络策略 |
| 镜像版本不存在 | ErrImagePull | 确认 tag 是否正确 |
3. 私有仓库配置示例
ini
# 创建 Secret
kubectl create secret docker-registry my-registry \
--docker-server=registry.example.com \
--docker-username=admin \
--docker-password=xxxxx
# Pod 中引用
spec:
imagePullSecrets:
- name: my-registry
四、Pending:调度失败
Pending 状态说明 Pod 还没被调度到节点上。
1. 查看调度原因
css
kubectl describe pod <pod-name> | grep -A 10 Events
常见原因:
- 资源不足 :
Insufficient CPU/Memory - 调度约束不满足:nodeSelector、affinity、taints/tolerations 冲突
- PVC 未绑定:存储依赖未就绪
2. 节点资源检查
perl
kubectl describe node | grep -A 5 "Allocated resources"
3. 污点和容忍度问题
vbnet
# Pod 需要的容忍度
spec:
tolerations:
- key: "disk-pressure"
operator: "Exists"
effect: "NoSchedule"
五、Running 但不健康
Pod 状态显示 Running,但服务响应异常。
1. 检查探针状态
bash
kubectl describe pod <pod-name>
# 看 Containers 下的 Readiness 和 Liveness
2. 端口配置核对
Service 配置中容易混淆的三个端口:
| 字段 | 含义 | 示例 |
|---|---|---|
| port | Service 暴露端口 | 80 |
| targetPort | 转发到 Pod 的端口 | 8080 |
| containerPort | Pod 内应用监听的端口 | 8080 |
3. Service Selector 检查
csharp
# 查看 Pod 标签
kubectl get pods --show-labels
# 查看 Service 的 selector
kubectl get svc <service-name> -o jsonpath='{.spec.selector}'
两者必须匹配,否则流量无法到达 Pod。
六、实用排查命令清单
ini
# 1. 快速定位所有异常 Pod
kubectl get pods --field-selector=status.phase!=Running -A
# 2. 查看集群事件(按时间排序)
kubectl get events --sort-by='.lastTimestamp'
# 3. 进入容器调试
kubectl exec -it <pod-name> -- sh
# 4. 使用调试镜像临时进入
kubectl debug <pod-name> -it --image=nicolaka/netshoot
# 5. 端口转发测试
kubectl port-forward <pod-name> 8888:8080
# 6. 网络连通性测试
kubectl exec <pod-name> -- curl -I http://<service-name>:80
七、生产环境建议
1. 完善监控告警
yaml
# Prometheus 告警规则示例
- alert: PodCrashLoop
expr: kube_pod_container_status_restarts_total > 3
for: 5m
labels:
severity: critical
2. 规范健康检查配置
所有服务必须配置 readinessProbe 和 livenessProbe,关键服务建议加 startupProbe。
3. 资源配额规范
yaml
resources:
requests:
cpu: "100m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
总结
Pod 故障排查的核心是建立清晰的排查路径:
状态 → 事件 → 日志 → 配置 → 网络
按这个顺序逐层排查,能解决绝大多数问题。
最后说一句:转行做运维前期确实会遇到很多"没见过的状态",但只要掌握了排查方法论,很多问题其实没那么可怕。
有问题欢迎评论区交流。