深色模式
K8s 故障排查手册
摘要:本文按「看到什么状态 → 查什么 → 怎么处理」的形式,整理 K8s 最常见异常的完整排查路径。遇到问题时直接按状态对号入座即可,无需从头推理。
适用环境
- 可用 K8s 集群 +
kubectl - 已安装 metrics-server(排查资源类问题时需要)
- 具备查看 kube-system 命名空间日志的权限
操作步骤
一、通用第一板斧
不论什么异常,先跑这三条,80% 的问题能定位:
bash
kubectl get pod <pod> -o wide
kubectl describe pod <pod> # 重点看 Events
kubectl logs <pod> --previous --tail=1001
2
3
2
3
二、Pending
bash
kubectl describe pod <pod> | grep -A5 Events1
| Events 提示 | 原因 | 处理 |
|---|---|---|
0/N nodes are available: insufficient cpu | 资源不足 | 降低 requests 或扩容节点 |
didn't match node selector/affinity | 调度约束不满足 | 检查 nodeSelector、taints |
had untolerated taint | 节点有污点 | 加 tolerations 或清理污点 |
persistentvolumeclaim not found | PVC 不存在/未绑定 | 检查 PVC 与 StorageClass |
快速确认节点余量:
bash
kubectl describe node <节点> | grep -A8 "Allocated resources"
kubectl get node -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints1
2
2
三、ImagePullBackOff / ErrImagePull
bash
kubectl describe pod <pod> | grep -A3 "Failed to pull image"1
常见原因:镜像名或 tag 拼错、私有仓库未配置 imagePullSecrets、网络不通仓库、仓库限流(匿名拉取配额)。
bash
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=user --docker-password=pass
kubectl patch serviceaccount default -p '{"imagePullSecrets":[{"name":"regcred"}]}'1
2
3
4
2
3
4
四、CrashLoopBackOff
bash
kubectl logs <pod> --previous
kubectl describe pod <pod> | grep -A5 "Last State"1
2
2
| Last State 的 Reason | 含义 |
|---|---|
Error (exitCode 1/2) | 应用启动失败,看日志 |
OOMKilled | 内存超限,调大 limits |
Completed | 主进程正常退出但 restartPolicy=Always → 命令写错 |
容器起来了立刻退出,多半是启动命令退出(如只写了 CMD ["sh"]),需要长期运行的前台进程。
五、OOMKilled
bash
kubectl get pod <pod> -o jsonpath='{.status.containerStatuses[0].lastState.terminated}'
kubectl top pod <pod> --containers1
2
2
处理:调大 limits.memory;Java 应用注意 JVM 堆外的元空间与直接内存。
六、Readiness/Liveness 探针失败
bash
kubectl describe pod <pod> | grep -A6 "Readiness probe failed\|Liveness probe failed"1
处理:确认健康检查接口真实返回码、端口是否正确、initialDelaySeconds 是否够长。
七、Terminating 卡住
bash
kubectl get pod <pod> -o jsonpath='{.metadata.finalizers}'
kubectl describe node <节点> # 节点是否 NotReady1
2
2
节点失联导致的卡死,强制删除:
bash
kubectl delete pod <pod> --force --grace-period=01
危险
强制删除会绕过优雅退出。对有状态服务可能造成数据不一致,仅在节点已确认不可恢复时使用。
八、节点 NotReady
bash
kubectl describe node <节点> | grep -A10 Conditions
ssh <节点> "systemctl status kubelet containerd; journalctl -u kubelet -n 50"1
2
2
常见:kubelet 挂了、容器运行时挂了、磁盘满(df -h)、内存不足、证书过期。
bash
df -h /var/lib/kubelet /var/lib/containerd
free -h
sudo kubeadm certs check-expiration1
2
3
2
3
九、CreateContainerConfigError
引用的 ConfigMap / Secret / PVC 不存在或 key 名不对:
bash
kubectl describe pod <pod> | grep -A3 "Error"
kubectl get cm,secret,pvc -n <命名空间>1
2
2
十、Service 无后端
bash
kubectl get ep <svc>
kubectl get pod -l <selector> --show-labels1
2
2
十一、控制面异常
bash
kubectl -n kube-system get pod
kubectl get --raw /healthz
sudo journalctl -u kubelet -f1
2
3
2
3
etcd 空间满会导致 apiserver 只读,需压缩碎片:
bash
sudo ETCDCTL_API=3 etcdctl compact <revision>
sudo ETCDCTL_API=3 etcdctl defrag1
2
2
验证
- [ ] 能根据 Pod 状态在本文找到对应排查路径
- [ ]
describe的 Events 段能读懂 - [ ] 对每个异常知道该看日志还是看事件
常见坑
- 只看
get pod不看describe:真实原因全在 Events 里。 - 容器反复重启却只看当前日志:必须加
--previous。 - 一出问题就删 Pod:销毁了现场,也未必能修复(控制器会按同样的错误配置重建)。
- 忽略节点层问题:Pod 异常的根因常常是节点磁盘满或 kubelet 异常。
- 在生产直接改线上对象:改完没记录,GitOps 同步后又回退。