Skip to content

故障排查

排查 Kubernetes 问题时,先确定故障层级,再检查事件、状态条件和日志。直接删除 Pod 可能暂时掩盖问题,但不会解释根因。

排查顺序

基础信息:

bash
kubectl get nodes -o wide
kubectl get pods -A -o wide
kubectl get events -A --sort-by=.lastTimestamp
kubectl describe pod <pod> -n <namespace>
kubectl logs <pod> -n <namespace> --all-containers
kubectl logs <pod> -n <namespace> --previous

Events 具有保留期限,只适合作为近期线索,长期分析需要集中日志、指标和审计系统。

Pod Pending

常见原因:

  • requests 超过节点可分配资源。
  • nodeSelector、Affinity、TopologySpread 或污点无法满足。
  • PVC 未绑定或存储拓扑不匹配。
  • ResourceQuota、准入策略或调度器插件拒绝。
bash
kubectl describe pod <pod> -n <namespace>
kubectl get nodes -L topology.kubernetes.io/zone
kubectl describe node <node>
kubectl get pvc,pv,storageclass -A

重点阅读 Pod Events 中 scheduler 给出的 FailedScheduling 原因,不要只通过增加节点解决所有 Pending。

ImagePullBackOff

检查镜像名称、tag、平台架构、仓库连通性和凭据:

bash
kubectl describe pod <pod> -n <namespace>
kubectl get serviceaccount <sa> -n <namespace> -o yaml
kubectl get secret <pull-secret> -n <namespace> -o yaml

节点侧可使用 CRI 工具验证:

bash
sudo crictl pull <image>
sudo crictl images

避免在排错输出中泄露 registry credential。

CrashLoopBackOff

CrashLoopBackOff 表示容器反复退出并进入指数退避,不是具体根因。检查:

bash
kubectl logs <pod> -n <namespace> --previous
kubectl get pod <pod> -n <namespace> \
  -o jsonpath='{range .status.containerStatuses[*]}{.name}{" exit="}{.lastState.terminated.exitCode}{" reason="}{.lastState.terminated.reason}{"\n"}{end}'

常见原因包括启动命令错误、配置缺失、依赖不可用、OOM、文件权限和探针配置错误。退出码 137 通常需要结合 OOMKilled、节点内存和 cgroup 指标确认,不能只看数字下结论。

Service 无法访问

从选择器到后端逐层验证:

bash
kubectl get service <service> -n <namespace> -o yaml
kubectl get endpointslice -n <namespace> \
  -l kubernetes.io/service-name=<service> -o wide
kubectl get pods -n <namespace> --show-labels
kubectl exec -n <namespace> <client-pod> -- \
  curl -v http://<service>:<port>

检查 Service selector、Pod readiness、port/targetPort、NetworkPolicy 和应用实际监听地址。应用只监听 127.0.0.1 时,其他 Pod 无法通过 Pod IP 访问。

DNS 故障

bash
kubectl get pods,service -n kube-system -l k8s-app=kube-dns
kubectl logs -n kube-system -l k8s-app=kube-dns
kubectl exec <pod> -n <namespace> -- cat /etc/resolv.conf
kubectl exec <pod> -n <namespace> -- nslookup kubernetes.default.svc

需要区分:

  • Service 名称不存在。
  • CoreDNS Pod 或 Service 异常。
  • NetworkPolicy 阻止 UDP/TCP 53。
  • 节点上游 DNS 配置形成转发环路。
  • 使用了错误的 namespace 或 cluster domain。

PVC 无法挂载

bash
kubectl describe pvc <pvc> -n <namespace>
kubectl describe pod <pod> -n <namespace>
kubectl get volumeattachment
kubectl get csinode,csidriver
kubectl get pods -A | grep -i csi

检查 StorageClass、accessModes、volumeBindingMode、节点/可用区拓扑、CSI controller/node plugin 和云盘状态。ReadWriteOnce 通常表示单节点读写,不等于单 Pod;需要严格单 Pod 挂载时使用驱动支持的 ReadWriteOncePod

Node NotReady

bash
kubectl describe node <node>
kubectl get lease -n kube-node-lease <node> -o yaml
sudo systemctl status kubelet containerd
sudo journalctl -u kubelet --since '30 min ago'
sudo crictl info

重点检查 kubelet 心跳、运行时、磁盘/内存/PID 压力、证书、时间同步、CNI 和节点到 API Server 的网络。

调试容器和节点

镜像缺少 shell 或调试工具时使用临时容器:

bash
kubectl debug -it <pod> -n <namespace> \
  --image=nicolaka/netshoot --target=<container>

调试节点:

bash
kubectl debug node/<node> -it --image=ubuntu

临时容器和节点调试通常具有较高权限,应受 RBAC、准入和审计约束。生产环境应使用经过审核并固定 digest 的调试镜像。

常用诊断输出

bash
kubectl get --raw='/readyz?verbose'
kubectl api-resources
kubectl auth can-i --list -n <namespace>
kubectl top nodes
kubectl top pods -A
kubectl cluster-info dump --output-directory=/tmp/cluster-info

kubectl top 依赖 Metrics Server;它反映近期资源指标,不代替长期监控。