跳转至

排错手册

排错不是「猜一个原因然后重启」。先确定故障边界,再收集证据,最后验证假设。这份手册给你一套可以重复执行的流程,以及一张按现象索引的故障表。

难度 · 进阶 用途 · 故障处理 前置:核心对象、网络、存储

五步排错法

flowchart LR
  A[定义现象] --> B[确定边界]
  B --> C[收集证据]
  C --> D[提出假设]
  D --> E[验证并修复]
  E -->|未解决| C

图:不要跳过「确定边界」。同一个 502,可能是 Pod、Service、Ingress、CNI 或外部 LB 的问题。

  1. 定义现象:谁访问谁、什么时间、错误码/超时、影响范围。
  2. 确定边界:单个 Pod?单个节点?单个 namespace?全部服务?
  3. 收集证据:get、describe、logs、events、top、节点日志。
  4. 提出假设:一次只验证一个,写出「如果假设成立,应该看到什么」。
  5. 验证并修复:修复后做回归,确认没有引入新问题。

先取证,再重启

kubectl delete pod 会清掉容器日志与上一次退出状态。先执行 kubectl logs --previous、describe、保存事件,再考虑重启。

第一分钟做什么

# 1. 集群是否健康
kubectl get --raw='/readyz?verbose'

# 2. 节点是否 Ready
kubectl get nodes -o wide

# 3. 异常 Pod
kubectl get pods -A --field-selector=status.phase!=Running

# 4. 最近事件
kubectl get events -A --sort-by=.lastTimestamp | tail -30

# 5. 控制平面
kubectl get pods -n kube-system -o wide

如果 API 都连不上,先跳到「控制平面」一节,不要在应用层浪费时间。

按 Pod 状态索引

Pending

Pod 没有被调度到节点。

kubectl describe pod <pod> -n <ns> | sed -n '/Events/,$p'
事件关键词 原因 处理
Insufficient cpu/memory 节点资源不足 降 requests、扩容节点、清理僵尸 Pod
node(s) had untolerated taint 污点未容忍 加 toleration,或调度到其他节点
node affinity/selector 亲和性不满足 检查 nodeSelector、affinity、节点标签
persistentvolumeclaim not found PVC 不存在 创建 PVC 或修正名字
pod has unbound immediate PVC PVC 未绑定 describe pvc,检查 StorageClass
exceeded quota 资源配额 调整 ResourceQuota
no nodes available 没有可调度节点 检查节点状态与 cordon

ImagePullBackOff / ErrImagePull

kubectl describe pod <pod> -n <ns> | grep -A5 -i 'failed'
原因 验证 处理
镜像名 / tag 错 crictl pull <image> 修正镜像
私有仓库无凭据 imagePullSecrets 创建 docker-registry Secret
仓库不可达 节点上 curl registry 配 mirror / 代理
架构不匹配 docker manifest inspect 用多架构镜像
限流 事件中有 429 配镜像加速或重试

CrashLoopBackOff

容器启动后反复退出。

kubectl logs <pod> -n <ns> --previous
kubectl describe pod <pod> -n <ns> | grep -E 'Exit Code|Reason|Last State'
退出码 含义 常见原因
0 正常退出 前台进程结束,容器没有常驻进程
1 应用错误 配置错、依赖不可用、启动异常
127 命令不存在 command 路径错
137 被 SIGKILL / OOM 内存超限、liveness 重启
143 SIGTERM 优雅终止、被删除

Running 但 0/1

readiness 探针失败,Pod 不接收流量。

kubectl describe pod <pod> -n <ns> | grep -A10 -i readiness
kubectl exec <pod> -n <ns> -- wget -qO- http://localhost:<port>/<path>
kubectl get endpoints <svc> -n <ns>

常见原因:探针路径/端口错、应用启动慢但 initialDelaySeconds 太短、依赖未就绪、host 头不匹配。

Terminating 卡住

kubectl get pod <pod> -n <ns> -o yaml | grep -A3 finalizers
kubectl describe pod <pod> -n <ns>
  • finalizer 未清理:找到对应控制器;
  • 优雅终止超时:terminationGracePeriodSeconds;
  • 节点失联:kubectl delete pod --force --grace-period=0(确认容器已停)。

按故障域索引

Service 访问不通

kubectl get svc <svc> -n <ns> -o yaml
kubectl get endpoints <svc> -n <ns>
kubectl get endpointslice -n <ns> -l kubernetes.io/service-name=<svc>
kubectl get pods -n <ns> --show-labels
检查点 正常 异常处理
selector 与 Pod 标签一致 修正 selector
Endpoints 有 Pod IP 检查 readiness、namespace
targetPort 与容器端口一致 修正端口名/号
NetworkPolicy 允许来源 加放行规则
DNS nslookup svc.ns 有结果 查 CoreDNS
kube-proxy Pod Running 查规则 / 日志

DNS 解析失败

kubectl get pods -n kube-system -l k8s-app=kube-dns
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=50
kubectl run dns --image=busybox:1.36 --rm -it --restart=Never -- \
  nslookup kubernetes.default
  • CoreDNS Pod 是否 Ready;
  • 是否被 NetworkPolicy 阻断 53 端口;
  • /etc/resolv.conf 的 nameserver 是否是 Service CIDR 内的地址;
  • 跨 namespace 是否用了短名。

Ingress 502 / 404

kubectl get ingress -n <ns> -o yaml
kubectl get svc -n ingress-nginx
kubectl logs -n ingress-nginx deploy/ingress-nginx-controller --tail=100
kubectl get endpoints <backend-svc> -n <ns>
  • 404:host / path 不匹配,或 IngressClass 不对;
  • 502:后端未 Ready、端口错、协议错(HTTPS 后端需注解);
  • 504:后端超时,检查 proxy-read-timeout 与应用性能。

PVC Pending

kubectl describe pvc <pvc> -n <ns>
kubectl get storageclass
kubectl get pv
kubectl get pods -n kube-system | grep -E 'csi|provisioner'
原因 处理
没有默认 StorageClass 指定 storageClassName 或设默认
WaitForFirstConsumer 先创建使用它的 Pod
容量不足 / 访问模式不匹配 调整请求或 PV
provisioner Pod 异常 查 CSI 日志
拓扑限制 用 allowedTopologies 或本地 PV

节点 NotReady

kubectl describe node <node>
ssh <node> 'systemctl status kubelet; journalctl -u kubelet -n 100 --no-pager'
ssh <node> 'df -h; free -h; systemctl status containerd'
原因 现象 处理
kubelet 挂了 Kubelet stopped posting 重启 kubelet,查配置
磁盘压力 DiskPressure 清理镜像/日志
内存压力 MemoryPressure 驱逐低优先级 Pod
网络插件异常 CNI Pod 未就绪 重启 CNI
证书过期 kubelet 报 x509 轮换证书
时间不同步 TLS 错误 修 NTP

控制平面异常

kubectl get pods -n kube-system
kubectl get --raw='/readyz?verbose'
sudo crictl ps | grep -E 'kube-apiserver|etcd|kube-controller|kube-scheduler'
sudo journalctl -u kubelet -n 200 --no-pager
  • API Server 起不来:看静态 Pod 清单 /etc/kubernetes/manifests/ 与容器日志;
  • etcd 异常:检查磁盘、证书、/var/lib/etcd 空间;
  • 证书过期:kubeadm certs check-expiration;
  • 全部静态 Pod 异常:检查 kubelet 与容器运行时。

资源与性能

kubectl top nodes
kubectl top pods -A --sort-by=cpu
kubectl describe node <node> | sed -n '/Allocated resources/,/Events/p'
kubectl get pod <pod> -o jsonpath='{.status.qosClass}'
  • CPU 高但未限流:看应用本身;
  • CPU 被 throttle:提高 limits 或优化;
  • 内存持续增长:查泄漏,设置合理 limit;
  • 节点磁盘满:清理未使用镜像 crictl rmi --prune。

常用证据命令

kubectl get events -n <ns> --sort-by=.lastTimestamp
kubectl describe pod <pod> -n <ns>
kubectl logs <pod> -n <ns> --all-containers --tail=200
kubectl logs <pod> -n <ns> --previous
kubectl get pod <pod> -n <ns> -o yaml
kubectl get endpoints,endpointslice -n <ns>
kubectl get pvc -n <ns>
kubectl get --raw='/readyz?verbose'

不要做的事

  • 不要一上来就删 Pod / 重启节点;
  • 不要同时改多个变量;
  • 不要在没看 Events 的情况下猜镜像问题;
  • 不要把 latest 镜像用于生产;
  • 不要用 --force 删除有状态 Pod 而不确认数据;
  • 不要把「Pod Running」当成「服务可用」。

延伸阅读