跳到主要内容

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 / 镜像缺依赖
137SIGKILL (OOM)内存超限
139SIGSEGV段错误
143SIGTERM正常终止信号

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 怎么处理?

答案

  1. 检查 Finalizerkubectl get pod <name> -o yaml | grep finalizer,如有异常 finalizer 可以手动清除
  2. 检查 PDB:PodDisruptionBudget 可能阻止删除
  3. preStop Hook 超时:容器的 preStop 钩子执行时间过长
  4. 强制删除kubectl delete pod <name> --grace-period=0 --force(最后手段)

相关链接