Kubernetes集群故障分析与排查手册
一、故障概述
1. 集群基础信息
| 项目 | 详情 |
|---|---|
| 集群架构 | 单Master + 3 Worker节点 |
| 集群版本 | Kubernetes v1.20.8 |
| 业务组件 | KubeSphere v3.2.1、DevOps、监控日志体系、NFS存储、Ingress网关 |
| 容器运行时 | Docker |
| 网络插件 | Flannel |
2. 故障影响范围
- 控制面故障:Master节点状态丢失,kube-apiserver认证异常,集群管控能力失效
- 业务影响:KubeSphere控制台无法访问,NodePort端口不通,系统组件与KubeSphere全栈组件批量异常
- 持续时长:约1.5小时
- 最终结果:全部组件恢复正常,节点负载均衡分配,集群回归稳定运行状态
二、故障时间线与连锁链路
阶段1:控制面认证失效(触发源)
- 前置操作:集群证书续期后重启Master节点
- 现象:kubelet持续报错
User "system:anonymous" cannot list resource,节点k8s-master无法被识别 - 误操作:执行
kubectl delete node k8s-master尝试重置节点状态 - 后果:Master节点对象从etcd中彻底删除,kubelet客户端证书身份绑定失效,完全无法注册节点
阶段2:Pod批量重调度(连锁故障)
- 触发:Master节点NotReady超过容忍时间,K8s驱逐机制启动,全集群Pod触发重调度
- 现象:大量系统组件、KubeSphere组件被调度到资源空闲的
k8s-node3节点 - 隐患:
k8s-node3仅运行业务负载,无任何KubeSphere、系统核心组件的本地镜像缓存
阶段3:批量镜像拉取失败(故障爆发)
- 现象:全集群18+Pod进入
ImagePullBackOff状态,覆盖KubeSphere核心、监控、日志、DevOps、DNS、存储等全链路组件 - 直接原因:节点无本地镜像 + 公网Docker Hub/镜像仓库连通性异常,远程拉取全部失败
- 叠加问题:部分组件
imagePullPolicy为Always,强制远程拉取,即使本地有镜像也无法复用
阶段4:调度冲突与最终修复
- 临时方案:强制Pod调度到镜像完整的
k8s-node1,快速恢复服务 - 衍生问题:有状态组件滚动更新时,受
nodeSelector限制新Pod无节点可调度,进入Pending状态 - 最终优化:按组件角色分散调度到对应节点,修正镜像拉取策略,清理异常副本,集群全量恢复
三、分层根因分析
1. 控制面认证失效根因
Kubernetes节点身份采用证书绑定机制:
- kubelet客户端证书的CN字段为
system:node:<节点名>,与etcd中的节点对象UID强绑定 - 执行
delete node后,节点对象被销毁,原有客户端证书的身份不再被apiserver认可 - apiserver将无效证书的请求直接降级为匿名用户
system:anonymous,无任何集群操作权限,导致节点无法注册、持续报错
2. 批量镜像拉取失败根因
- 节点镜像分布不均:仅
k8s-node1和Master节点有完整的系统+KubeSphere镜像,node2、node3镜像缺失严重 - 重调度机制触发:Master节点异常后,调度器将大量Pod重新分配到node3,直接命中镜像空白节点
- 公网拉取能力缺失:集群无法稳定访问公网镜像仓库,远程拉取超时失败,最终进入
ImagePullBackOff退避状态
3. Pod调度Pending根因
- 为修复镜像问题给Deployment添加了
nodeSelector强制调度约束 - 滚动更新时,新Pod与旧Pod需调度到同一节点,但有状态组件(如MinIO)存在存储、端口独占限制,新Pod无法启动
- Master节点默认带有
node-role.kubernetes.io/master:NoSchedule污点,普通Pod无法调度,最终全部节点均不满足调度条件
四、标准化排查流程(同类故障通用)
场景1:节点NotReady / kubelet认证异常
排查步骤(由面到点)
-
第一步:确认节点全局状态
kubectl get nodes判断是单节点异常还是全集群异常,缩小排查范围。
-
第二步:查看kubelet核心日志(定位关键)
journalctl -u kubelet -f -n 50关键报错对应根因:
报错关键字 根因 system:anonymouskubelet客户端证书失效/身份不被认可 x509: certificate has expired证书已过期 x509: certificate signed by unknown authorityCA证书不匹配 node xxx not found节点对象不存在,无法注册 -
第三步:核对kubelet配置与证书有效性
# 查看kubelet配置 cat /etc/kubernetes/kubelet.conf # 验证客户端证书有效期与身份 openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -text -noout | grep -E "Subject:|Not After"正常证书Subject应为
CN=system:node:<节点名>, O=system:nodes。 -
第四步:验证apiserver连通性
curl --cacert /etc/kubernetes/pki/ca.crt https://<master-ip>:6443/version排除网络、端口、防火墙问题。
场景2:Pod ImagePullBackOff 镜像拉取失败
排查步骤
-
第一步:确认Pod调度节点与镜像信息
kubectl get pod <pod-name> -n <namespace> -o wide kubectl get pod <pod-name> -n <namespace> -o jsonpath='{.spec.containers[0].image}'明确Pod运行在哪个节点、使用的完整镜像名与标签。
-
第二步:查看具体拉取报错
kubectl describe pod <pod-name> -n <namespace> | tail -20报错对应根因:
报错关键字 根因 manifest for xxx not found镜像名/标签不存在,拼写错误 connection refused/timeout镜像仓库网络不通 no pull access/unauthorized镜像仓库认证失败 -
第三步:核对目标节点本地镜像
登录Pod调度的节点,执行:# Docker运行时 docker images | grep <镜像名> # Containerd运行时 crictl images | grep <镜像名>必须镜像名、仓库地址、标签完全一致,才会被识别为本地已有镜像。
-
第四步:核对镜像拉取策略
kubectl get deploy <工作负载名> -n <namespace> -o yaml | grep imagePullPolicyAlways:强制每次拉远程,失败直接报错IfNotPresent:本地有就用本地,没有才拉远程Never:仅用本地镜像,不拉远程
场景3:Pod Pending 调度失败
排查步骤
-
第一步:直接查看调度事件(90%问题可直接定位)
kubectl describe pod <pod-name> -n <namespace> | grep -A 10 Events事件对应根因:
事件关键字 根因 node(s) had taint, that the pod didn't tolerate节点有污点,Pod无对应容忍 node(s) didn't match Pod's node affinity不满足nodeSelector/节点亲和性规则 Insufficient cpu/memory节点资源不足 persistentvolumeclaim is already bound存储被旧Pod占用,有状态服务冲突 -
第二步:核对节点资源与标签
# 查看节点可分配资源 kubectl describe node <节点名> | grep -A 10 Allocatable # 查看节点标签 kubectl get node <节点名> --show-labels -
第三步:核对工作负载的调度规则
检查Deployment/StatefulSet的nodeSelector、affinity、tolerations配置,确认是否存在过度约束。
五、故障修复方案汇总
1. Master节点认证失效修复
应急快速恢复(优先保证集群可用)
直接用管理员配置覆盖kubelet配置,临时获得注册权限:
cp /etc/kubernetes/admin.conf /etc/kubernetes/kubelet.conf
chmod 644 /etc/kubernetes/kubelet.conf
systemctl restart kubelet
注意:此为应急方案,kubelet会持有管理员权限,故障恢复后需换回标准配置。
标准合规修复(生产推荐)
用集群CA签发符合节点身份规范的客户端证书,重建kubelet配置:
# 1. 停止kubelet,清理旧证书
systemctl stop kubelet
rm -rf /var/lib/kubelet/pki/kubelet-client-*.pem
mv /etc/kubernetes/kubelet.conf /etc/kubernetes/kubelet.conf.bak
# 2. 生成并签发节点证书
openssl genrsa -out /var/lib/kubelet/pki/kubelet-client.key 2048
openssl req -new -key /var/lib/kubelet/pki/kubelet-client.key \
-out /var/lib/kubelet/pki/kubelet-client.csr \
-subj "/CN=system:node:k8s-master/O=system:nodes"
openssl x509 -req -in /var/lib/kubelet/pki/kubelet-client.csr \
-CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial -out /var/lib/kubelet/pki/kubelet-client.crt -days 365
cat /var/lib/kubelet/pki/kubelet-client.crt /var/lib/kubelet/pki/kubelet-client.key > /var/lib/kubelet/pki/kubelet-client-current.pem
# 3. 生成标准kubelet配置
kubeadm init phase kubeconfig kubelet
systemctl restart kubelet
2. 批量镜像拉取失败修复
方案A:调度到有镜像节点(快速恢复)
给工作负载添加节点选择器,强制调度到镜像完整的节点:
kubectl patch deploy <工作负载名> -n <命名空间> \
-p '{"spec":{"template":{"spec":{"nodeSelector":{"kubernetes.io/hostname":"k8s-node1"}}}}}'
删除异常Pod触发重建:
kubectl delete pod <pod-name> -n <命名空间>
方案B:修正镜像拉取策略
将强制拉取改为优先使用本地镜像:
kubectl patch deploy <工作负载名> -n <命名空间> \
-p '{"spec":{"template":{"spec":{"containers":[{"name":"<容器名>","imagePullPolicy":"IfNotPresent"}]}}}}'
方案C:跨节点同步镜像(彻底解决)
- 在有镜像的节点打包镜像
docker save <镜像1> <镜像2> -o /tmp/images.tar.gz - 传输到目标节点
scp /tmp/images.tar.gz root@<目标节点IP>:/tmp/ - 目标节点导入镜像
docker load -i /tmp/images.tar.gz
3. Pod调度Pending修复
节点污点导致的无法调度
给Pod添加对应污点容忍,或移除节点污点(不推荐master节点操作):
# 示例:添加master污点容忍
kubectl patch deploy <工作负载名> -n <命名空间> \
-p '{"spec":{"template":{"spec":{"tolerations":[{"key":"node-role.kubernetes.io/master","effect":"NoSchedule"}]}}}}'
nodeSelector过度约束导致的无法调度
移除节点选择器,恢复默认调度:
kubectl patch deploy <工作负载名> -n <命名空间> \
--type json -p '[{"op":"remove","path":"/spec/template/spec/nodeSelector"}]'
六、预防与优化建议
1. 操作规范(规避人为故障)
- 绝对禁止删除单Master集群的控制面节点:节点异常优先排查kubelet、证书、网络,删除节点会触发身份失效、Pod重调度等连锁故障
- 证书续期后必须做验证:续期完成后检查
kubelet、apiserver、controller-manager状态,确认节点Ready、组件正常后再重启 - 集群核心操作前备份:修改证书、节点、调度规则前,备份
/etc/kubernetes目录,便于快速回滚
2. 镜像管理(解决拉取失败根因)
- 核心组件镜像全节点同步:系统组件、KubeSphere组件、存储网关等基础服务的镜像,提前同步到所有Worker节点,避免重调度后无镜像可用
- 搭建私有镜像仓库(如Harbor):统一管理集群所有镜像,配置镜像缓存,消除对公网仓库的依赖
- 规范镜像拉取策略:固定版本号的生产镜像统一使用
IfNotPresent,仅latest标签的测试环境使用Always
3. 调度优化(均衡负载+高可用)
- 核心组件分散部署:控制台、监控、日志、网关等组件按角色分配到不同节点,避免单节点压力过载,同时规避单点故障
- 配置Pod反亲和性:多副本组件添加节点反亲和规则,避免同一服务的多个副本调度到同一节点
- Master节点隔离:普通业务Pod禁止调度到Master节点,保留资源给控制面组件,避免资源争抢导致集群失控
4. 监控与告警
- 配置节点状态告警:节点NotReady超过1分钟立即告警
- 配置Pod异常告警:
ImagePullBackOff、Pending、CrashLoopBackOff状态持续超过5分钟告警 - 配置证书过期告警:提前30天告警证书过期,避免突发证书失效