Kubernetes故障排查的系统性方法论
Kubernetes集群的故障排查不同于传统服务器运维——一个Pod启动失败可能涉及镜像拉取、资源调度、存储挂载、网络策略、RBAC权限等十多个环节。靠经验拍脑袋定位问题效率极低,系统性的排查路径是:先看事件(Event)再看日志(Log),先查控制面再查数据面,先看状态再看配置。
这篇手册整理了生产环境最常见的6类Kubernetes故障,每类给出从现象到根因的完整诊断步骤。
Pod CrashLoopBackOff:最常见也最容易被误判
CrashLoopBackOff表示容器启动后反复崩溃退出的循环状态。直接看kubectl logs往往看不到有效信息——因为容器已退出,需要加–previous参数查看上一次的日志。
# 查看Pod状态
kubectl get pods -n production
# NAME READY STATUS RESTARTS AGE
# api-server-5d7f8c6b9 0/1 CrashLoopBackOff 7 12m
# 查看上一次退出的日志
kubectl logs api-server-5d7f8c6b9 -n production --previous
# 查看Pod事件
kubectl describe pod api-server-5d7f8c6b9 -n production | grep -A20 Events
# 常见Exit Code含义
# Exit 1: 应用程序错误(配置错误、依赖缺失)
# Exit 137: OOMKilled(内存超限被杀)
# Exit 139: Segmentation Fault
# Exit 143: SIGTERM正常退出
OOMKilled场景的排查路径:
# 确认是否OOMKilled
kubectl describe pod api-server-5d7f8c6b9 -n production | grep -i oom
# Last State: Terminated Reason: OOMKilled Exit Code: 137
# 解决方案1:增大资源限制
resources:
limits:
memory: '2Gi' # 从1Gi增大到2Gi
requests:
memory: '1Gi'
# 解决方案2:JVM堆内存必须小于limit
# 常见错误:JVM -Xmx2g 但容器limit也是2Gi
# JVM实际内存 = 堆(2g) + 元空间 + 线程栈 + 堆外内存
# 容器limit应设为 -Xmx的1.5~2倍
env:
- name: JAVA_OPTS
value: '-Xmx1g -Xms1g -XX:+UseG1GC'
应用自身错误导致的CrashLoopBackOff,常见模式是启动时依赖的服务未就绪(数据库、Redis等):
# Init Container等待依赖就绪
initContainers:
- name: wait-for-db
image: busybox:1.36
command: ['sh', '-c', 'until nc -z mysql-service 3306; do echo waiting; sleep 2; done']
- name: wait-for-redis
image: busybox:1.36
command: ['sh', '-c', 'until nc -z redis-service 6379; do echo waiting; sleep 2; done']
ImagePullBackOff:镜像拉取失败的分层排查
镜像拉取失败在私有仓库场景下高频出现,排查步骤:
# 查看详细错误信息
kubectl describe pod <pod-name> | grep -A5 'Events'
# 常见错误类型:
# Failed to pull image: rpc error: NotFound
# Failed to pull image: rpc error: Unauthorized
# Failed to pull image: rpc error: Net/http: request timeout
# 1. 检查imagePullSecrets是否配置
kubectl get sa default -o yaml | grep imagePullSecrets
# 2. 创建registry secret
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=pull-user \
--docker-password=<password> \
--docker-email=ops@example.com
# 3. 在Pod/Deployment中引用
spec:
imagePullSecrets:
- name: regcred
网络层面的镜像拉取超时,在云环境中多见于跨区域拉取:
# 配置容器运行时镜像代理(containerd)
# /etc/containerd/config.toml
[plugins.'io.containerd.grpc.v1.cri'.registry.mirrors]
[plugins.'io.containerd.grpc.v1.cri'.registry.mirrors.'docker.io']
endpoint = ['https://mirror.gcr.io']
# 重启containerd
sudo systemctl restart containerd
节点NotReady:从kubelet到网络的完整排查
节点NotReady意味着kubelet停止向API Server汇报状态,超过node-monitor-grace-period(默认40秒)后节点被标记为NotReady。
# 查看节点条件和事件
kubectl describe node <node-name>
# 关注Conditions部分:
# Ready Unknown → kubelet失联
# MemoryPressure True → 节点内存紧张
# DiskPressure True → 节点磁盘满
# NetworkUnavailable True → 网络插件问题
# SSH到节点检查kubelet状态
sudo systemctl status kubelet
sudo journalctl -u kubelet --since '10 minutes ago'
# 常见原因1:磁盘满导致kubelet无法写文件
df -h /var/lib/kubelet
df -h /var/lib/containerd
# 清理废弃镜像和容器
crictl rmp --all # 删除停止的容器
ctr -n k8s.io image rm $(ctr -n k8s.io image ls -q | head -50)
# 常见原因2:kubelet证书过期
openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates
# 如果已经过期,需要重新签发
sudo kubeadm certs renew all
sudo systemctl restart kubelet
PVC Pending:存储挂载失败的排查路径
PVC一直处于Pending状态,常见原因包括:
# 查看PVC状态和事件
kubectl get pvc -n production
kubectl describe pvc data-pvc -n production
# 原因1:没有可用的PV满足PVC要求
# 检查StorageClass是否有可用PV
kubectl get storageclass
kubectl get pv | grep Released # Released的PV可回收
# 原因2:StorageClass的provisioner异常
kubectl get pods -n kube-system | grep csi
kubectl logs csi-driver-controller -n kube-system
# 原因3:PVC的accessModes与PV不匹配
# RWO (ReadWriteOnce) → 只能被单节点挂载
# RWX (ReadWriteMany) → NFS/CEPH等共享存储
# 如果PVC请求RWX但只有RWO的PV,会一直Pending
动态供给失败的具体排查:
# 检查CSI驱动日志
kubectl logs -n kube-system csi-rbdplugin-controller-0
# 常见错误:
# 'failed to create volume' → Ceph集群连接问题
# 'pool not found' → StorageClass配置的pool不存在
# 'insufficient quota' → Ceph配额不足
Service无法访问:网络策略和DNS的双面排查
Service不可达的排查需要区分ClusterIP、NodePort和LoadBalancer三个入口层级:
# 1. 集群内DNS解析验证
kubectl run tmp --image=busybox:1.36 --rm -it --restart=Never -- \
nslookup api-service.production.svc.cluster.local
# 2. ClusterIP直连测试
kubectl run tmp --image=busybox:1.36 --rm -it --restart=Never -- \
wget -qO- http://api-service.production:8080/health
# 3. Endpoints检查(最容易被忽略)
kubectl get endpoints api-service -n production
# 如果Endpoints为 → selector匹配不到Pod
# 检查selector标签是否与Pod标签一致
# 4. NetworkPolicy阻断
kubectl get networkpolicy -n production
# 检查是否有deny-all策略或未放行特定端口
CoreDNS故障会导致全集群DNS解析失败:
# 检查CoreDNS状态
kubectl get pods -n kube-system -l k8s-app=kube-dns
kubectl logs -n kube-system -l k8s-app=kube-dns
# CoreDNS配置检查
kubectl get configmap coredns -n kube-system -o yaml
# 常见问题:stubdomain配置错误、forward规则冲突
# 强制重启CoreDNS
kubectl rollout restart deployment coredns -n kube-system
构建系统化的故障排查SOP
生产环境Kubernetes集群的故障排查效率,取决于SOP的系统化程度。核心原则:
1. 现象归类优先于逐条排查——CrashLoopBackOff、NotReady、Pending三类覆盖80%以上的故障
2. Event和Log是黄金信息源——kubectl describe和kubectl logs –previous是前两步必做动作
3. 控制面和数据面分离排查——先确认API Server/etcd/scheduler健康,再排查节点和Pod
4. 变更溯源——90%的故障发生在变更后1小时内,先查最近一次Deployment/ConfigMap变更
将以上排查路径整理为运维Runbook,配合Prometheus告警自动关联诊断脚本,能把平均故障定位时间(MTTI)从30分钟压缩到5分钟以内。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetes-ji-qun-gu-zhang-pai-cha-shi-zhan-cong/