Kubernetes故障排查的系统性方法论
Kubernetes集群出问题时,最怕的不是某个Pod挂掉,而是排障过程像无头苍蝇——日志看了一堆,命令跑了一通,却没定位到根因。系统化排障的核心是缩小范围:从集群→节点→Pod→容器→应用,逐层定位。
排查的第一步永远是确认故障的层级。集群级别的问题(API Server不可达、节点NotReady)和Pod级别的问题(CrashLoopBackOff、OOMKilled)的排查路径完全不同。
Pod CrashLoopBackOff:最常见的在线故障
CrashLoopBackOff意味着容器启动后反复崩溃,Kubelet不断重试。排查流程:
# 查看Pod状态和事件
kubectl get pod myapp-7f9b8c6d4-x2k1j -o wide
kubectl describe pod myapp-7f9b8c6d4-x2k1j
# 关键信息在Events部分和Last State中
# Last State: Terminated Reason: Error Exit Code: 137 → OOMKilled
# Last State: Terminated Reason: Error Exit Code: 1 → 应用异常退出
# Last State: Terminated Reason: Completed Exit Code: 0 → 主进程正常退出但非长期运行
不同Exit Code的根因方向:
Exit Code 137 (OOMKilled):容器内存超限。查看资源限制和实际使用:
kubectl describe pod myapp-7f9b8c6d4-x2k1j | grep -A5 "Limits"
# 解决方案:调大resources.limits.memory,或优化应用内存使用
kubectl patch deployment myapp -p '{"spec":{"template":{"spec":{"containers":[{"name":"myapp","resources":{"limits":{"memory":"2Gi"}}}]}}}}'
Exit Code 1:应用自身报错。查看容器日志:
# 当前容器日志
kubectl logs myapp-7f9b8c6d4-x2k1j
# 上一次崩溃的容器日志(关键!)
kubectl logs myapp-7f9b8c6d4-x2k1j --previous
Exit Code 0:命令执行完就退出了。常见于Job类型的镜像被Deployments使用,或entrypoint脚本执行完毕。检查Dockerfile的ENTRYPOINT和CMD是否正确。
Pod一直Pending:调度失败诊断
Pod长时间Pending意味着调度器无法为其找到合适节点:
kubectl get pod myapp-7f9b8c6d4-x2k1j -o jsonpath='{.status.conditions[0].message}'
常见原因及对应方案:
Insufficient cpu/memory:集群资源不足。检查节点实际可用量:
kubectl top nodes
kubectl describe node node1 | grep -A5 "Allocated resources"
node(s) had volume node affinity conflict:PVC绑定的PV有节点亲和性限制,导致Pod只能调度到特定节点但该节点资源已满。这种情况需要检查StorageClass的volumeBindingMode是否为WaitForFirstConsumer:
kubectl get storageclass standard -o yaml | grep volumeBindingMode
# WaitForFirstConsumer: 延迟绑定,Pod调度后再创建PV
# Immediate: 立即绑定,可能导致亲和性冲突
MatchNodeSelector / NodeAffinity:标签选择器过于严格。列出节点标签确认:
kubectl get nodes --show-labels
kubectl get pod myapp-7f9b8c6d4-x2k1j -o yaml | grep -A10 affinity
Service无法访问:网络层排障
Pod正常但Service访问不通,从底层往上排查:
# 1. Pod自身是否健康
kubectl exec -it myapp-7f9b8c6d4-x2k1j -- curl -s http://localhost:8080/healthz
# 2. Service ClusterIP是否可达(从集群内Pod测试)
kubectl run tmp --image=busybox --rm -it --restart=Never -- wget -qO- http://myapp-svc:8080/healthz
# 3. 检查Endpoints是否正常关联
kubectl get endpoints myapp-svc
# 如果ENDPOINTS为none,说明selector匹配不到任何Pod
kubectl describe svc myapp-svc | grep Selector
kubectl get pods -l app=myapp # 确认Pod标签
iptables/IPVS规则检查:
# iptables模式
iptables -t nat -L KUBE-SERVICES | grep myapp-svc
# IPVS模式
ipvsadm -Ln | grep 10.96.0.100 # 替换为Service ClusterIP
DNS解析问题:
# 从Pod内测试DNS
kubectl run tmp --image=busybox --rm -it --restart=Never -- nslookup myapp-svc.default.svc.cluster.local
# CoreDNS日志
kubectl logs -n kube-system coredns-6d4b75cb7d-xxxx
# 如果DNS查询超时,检查CoreDNS的ready探针和上游DNS配置
节点NotReady:Kubelet问题诊断
节点状态变为NotReady时,SSH登录该节点排查:
# 检查kubelet状态
systemctl status kubelet
journalctl -u kubelet --since "10 min ago"
# 常见原因1: PLEG超时(Pod Lifecycle Event Generator)
# 日志特征: "PLEG is not healthy"
# 原因: Docker/containerd运行时卡死,或节点I/O负载过高
# 临时解决: 重启容器运行时
systemctl restart containerd
# 常见原因2: 磁盘压力
df -h /var/lib/kubelet
# kubelet默认磁盘使用率>85%触发DiskPressure,停止调度新Pod
# 清理不用的镜像和已退出容器
crictl rmp -a # 清理已退出容器
crictl rmi -a # 清理不用的镜像
etcd集群健康检查
etcd是Kubernetes的数据存储,etcd异常会导致整个集群不可用:
# 检查etcd成员健康
ETCDCTL_API=3 etcdctl endpoint health --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key
# 检查etcd性能指标
ETCDCTL_API=3 etcdctl endpoint status -w table --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key
# 重点关注:DB SIZE是否超过2GB警告线,是否有member处于learner状态
etcd慢查询告警(committed index too far behind)通常意味着某个成员磁盘I/O慢。SSD是etcd节点的硬性要求,机械盘环境必须迁移。
排障工具箱与快捷命令
# 快速查看集群整体状态
kubectl get --raw='/readyz?verbose'
kubectl get events --sort-by='.metadata.creationTimestamp' -A
# 资源配额和使用率一览
kubectl resource-capacity # 需安装resource-capacity插件
# 网络连通性快速测试
kubectl run netshoot --image=nicolaka/netshoot --rm -it --restart=Never -- bash
# 一行命令收集所有Pod的最近错误日志
kubectl get pods -A --field-selector=status.phase=Failed -o name | xargs -I{} kubectl logs {} --tail=50
Kubernetes排障的关键是层级定位:先确认是控制面还是数据面的问题,再逐层下钻。盲目进容器看日志只会浪费时间。建立从集群→节点→Pod→容器→应用的排查顺序,配合describe、logs、events三板斧,绝大多数故障都能在15分钟内定位到根因。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetes-ji-qun-gu-zhang-pai-cha-shi-zhan-cong-2/