K8s Pod 异常排查
问题
Kubernetes 集群中 Pod 出现 Pending、CrashLoopBackOff、ImagePullBackOff 等异常状态,如何排查?
答案
Pod 状态排查流程
Pending 排查
# 查看 Pod 事件,找到 Pending 原因
kubectl describe pod <pod-name> -n <namespace>
# 常见 Pending 原因:
# 1. 资源不足
# Events: FailedScheduling: Insufficient cpu / memory
# 解决:扩容节点 或 调低 requests
kubectl top nodes # 查看节点资源使用率
# 2. 节点 Taint 不匹配
# Events: didn't match Pod's tolerations
kubectl get nodes -o json | jq '.items[].spec.taints'
# 3. PVC 未绑定
# Events: pod has unbound persistent volume claims
kubectl get pvc -n <namespace>
# 4. 节点 selector / affinity 无匹配
kubectl get nodes --show-labels
CrashLoopBackOff 排查
# 1. 查看容器日志(当前+上一次)
kubectl logs <pod-name> -n <namespace>
kubectl logs <pod-name> -n <namespace> --previous
# 2. 查看 Pod 事件和退出码
kubectl describe pod <pod-name> -n <namespace>
# Last State: Terminated
# Exit Code: 1 → 应用错误
# Exit Code: 137 → OOMKilled (128+9=SIGKILL)
# Exit Code: 143 → SIGTERM (128+15)
# 3. 进入容器调试(如果容器能启动)
kubectl exec -it <pod-name> -- /bin/sh
# 4. 使用临时调试容器(容器无法启动时)
kubectl debug <pod-name> -it --image=busybox --target=<container>
退出码速查
| 退出码 | 含义 | 常见原因 |
|---|---|---|
| 0 | 正常退出 | 容器任务完成 |
| 1 | 应用错误 | 代码异常、配置错误 |
| 126 | 权限不足 | 文件不可执行 |
| 127 | 命令不存在 | PATH / 镜像缺依赖 |
| 137 | SIGKILL (OOM) | 内存超限 |
| 139 | SIGSEGV | 段错误 |
| 143 | SIGTERM | 正常终止信号 |
ImagePullBackOff 排查
# Events: Failed to pull image / unauthorized / not found
# 1. 检查镜像名和 tag 是否正确
# 确认能手动拉取
docker pull registry.example.com/app:v1.2.3
# 2. 检查 imagePullSecrets
kubectl get pod <pod-name> -o yaml | grep -A 5 imagePullSecrets
kubectl get secret <secret-name> -o yaml
# 3. 更新/创建 Registry Secret
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=user \
--docker-password=pass \
-n <namespace>
OOMKilled 排查
# 确认是 OOMKilled
kubectl describe pod <pod-name> | grep -A 5 "Last State"
# Reason: OOMKilled
# 查看当前内存使用
kubectl top pod <pod-name>
# 解决方案:
# 1. 增大 resources.limits.memory
# 2. 排查应用内存泄漏
# 3. JVM 应用:确保 -Xmx < limits.memory(留 30% 给非堆)
Evicted 排查
# 节点资源压力导致 Pod 被驱逐
kubectl get pods --field-selector=status.phase=Failed | grep Evicted
# 查看驱逐原因
kubectl describe pod <evicted-pod> | grep -A 3 "Status:"
# 常见:DiskPressure, MemoryPressure
# 批量清理 Evicted Pod
kubectl get pods --all-namespaces --field-selector=status.phase=Failed \
-o json | jq -r '.items[] | select(.status.reason=="Evicted") |
"\(.metadata.namespace) \(.metadata.name)"' | \
while read ns name; do kubectl delete pod $name -n $ns; done
常见面试问题
Q1: K8s Pod 排查的通用三步法?
答案:
# 第一步:看状态
kubectl get pod <name> -o wide
# 第二步:看事件(几乎所有问题都能在这里找到线索)
kubectl describe pod <name>
# 第三步:看日志
kubectl logs <name> # 当前日志
kubectl logs <name> --previous # 上次崩溃日志
kubectl logs <name> -c <container> # 多容器时指定
这三步能解决 90% 的 Pod 问题。
Q2: Pod 一直 Terminating 怎么处理?
答案:
- 检查 Finalizer:
kubectl get pod <name> -o yaml | grep finalizer,如有异常 finalizer 可以手动清除 - 检查 PDB:PodDisruptionBudget 可能阻止删除
- preStop Hook 超时:容器的 preStop 钩子执行时间过长
- 强制删除:
kubectl delete pod <name> --grace-period=0 --force(最后手段)