云计算百科
云计算领域专业知识百科平台

K8s生产集群故障应急处置实战:节点NotReady、Pod雪崩与资源耗尽的现场排查复盘

兄弟们,今天复盘一个K8s生产集群的严重故障。

故障现象非常典型且致命:集群多个节点状态突变为 NotReady,核心业务Pod大面积陷入 CrashLoopBackOff,Service层直接爆出大量502错误,整个集群处于半瘫痪状态,业务完全不可用。

面对这种集群级故障,最考验SRE和运维的心理素质。今天就把这次真实故障的排查和处置过程拆解一下,全是现场实操的血泪经验,希望能帮大家在遇到类似情况时,能稳住阵脚,快速恢复。

🚨 故障初期“四不要”红线(保命必看):

  • 不要盲目重启所有节点:这会导致调度雪崩,原本还能跑的Pod全被挤到坏节点上,直接全军覆没。
  • 不要直接 delete 大量Pod:删了Pod就丢失了现场日志和排查线索,而且重建可能依然失败。
  • 不要在未排查前升级集群版本:故障期间做变更,等于蒙着眼睛开高速,出了事你都不知道是原故障还是升级引起的。
  • 不要随意修改kubelet配置:改错了直接导致节点彻底失联,连SSH进去救的机会都没有。

  • 一、 完整应急处置SOP:先稳住,再抢救

    遇到大故障,千万别一上来就想着“怎么把代码修好”或者“怎么把节点重启”,口诀是:先稳住集群,再抢救业务。

    完整流程如下:

  • 故障定级:拉群、通报,明确当前影响面。
  • 集群健康度快速摸底:看监控大盘,确认是单点问题还是全局问题。
  • 控制面状态确认:确认apiserver、etcd是否正常。
  • 节点层排查:找出NotReady的节点,看是死机还是组件挂了。
  • Pod/容器层排查:看业务Pod为什么起不来。
  • 网络与存储层排查:排查CNI、CoreDNS、PV/PVC。
  • 业务恢复:隔离故障点,快速恢复核心链路。
  • 根因定位:找背锅侠。
  • 复盘加固:擦屁股,防止二次翻车。

  • 二、 控制面与节点排查:摸清底牌

    节点 NotReady 是表象,背后可能是kubelet挂了、网络断了或者资源耗尽了。

    1. 快速查看集群与节点状态

    # 查看节点状态,找出NotReady的节点
    kubectl get nodes -o wide

    # 查看异常节点的详细事件(重点看 Conditions 和 Events)
    kubectl describe node <node-name>

    # 查看控制面组件状态(apiserver, scheduler, controller-manager)
    kubectl get pods -n kube-system -o wide

    2. 节点层深度排查(上SSH)

    登录到 NotReady 的节点,按以下顺序排查:

    # 1. 查kubelet状态和日志(最常见的背锅侠)
    systemctl status kubelet
    journalctl -u kubelet -f –since "1 hour ago" | grep -iE "error|fail|panic"

    # 2. 查容器运行时状态(containerd/docker)
    systemctl status containerd
    crictl info
    crictl ps -a | grep -v Running

    # 3. 查节点资源占用(重点看磁盘和inode!)
    top -c
    df -h # 看磁盘空间,特别是 /var/lib/kubelet 和 /var/lib/containerd
    df -i # 看inode使用率,inode耗尽也会导致kubelet停摆!

    # 4. etcd 健康检查
    # 如果是kubeadm部署的,可以直接用kubectl查
    kubectl get –raw /healthz/etcd
    # 或者进etcd容器查
    kubectl exec -it etcd-master -n kube-system — etcdctl endpoint health –endpoints=https://127.0.0.1:2379

    💡 常见节点故障模式:

    • 磁盘满/Inode满:容器日志没轮转,或者某个业务疯狂写临时文件。
    • OOM:节点物理内存耗尽,触发内核OOM Killer,把kubelet或容器运行时杀了。
    • 内核Panic/死机:硬件问题或内核Bug,只能硬重启。
    • 证书过期:经典老番,1年期满,apiserver或kubelet证书过期,节点直接失联。

    三、 Pod与工作负载排查:定位业务死因

    节点没问题,但Pod就是起不来,或者疯狂重启。

    1. 快速定位异常Pod

    # 按命名空间列出非Running状态的Pod
    kubectl get pods -n <namespace> | grep -v Running

    # 查看Pod详细事件和退出码(重点看 Last State 和 Events)
    kubectl describe pod <pod-name> -n <namespace>

    # 查看容器日志(注意:一定要加 –previous 看上一次崩溃前的日志!)
    kubectl logs <pod-name> -n <namespace> –previous –tail=100

    # 查看Deployment滚动状态,看是不是卡住了
    kubectl rollout status deployment/<deployment-name> -n <namespace>

    # 按时间排序查看命名空间Events,找最新报错
    kubectl get events -n <namespace> –sort-by='.lastTimestamp' | tail -n 20

    2. 常见异常状态的真实含义

    别只看字面意思,要懂背后的逻辑:

    • CrashLoopBackOff:容器启动后立刻退出,或者探针一直失败。K8s在尝试重启它,但间隔时间越来越长。真相:通常是代码有Bug启动报错、配置文件挂载错了、或者数据库连不上。
    • OOMKilled:容器内存超限被系统Kill。真相:不一定是代码内存泄漏!很可能是 resources.limits.memory 设得太抠,或者Java应用没配好JVM参数(没识别到容器内存限制)。
    • ImagePullBackOff / ErrImagePull:镜像拉不到。真相:镜像Tag写错了、Harbor密码变了、或者节点到镜像仓库的网络不通(DNS解析失败)。
    • ContainerCreating:一直卡在创建中。真相:通常是存储卷(PV/PVC)挂载失败,或者CNI网络插件分配IP失败。

    四、 网络与存储排查:打通任督二脉

    Pod起来了,但是互相不通,或者域名解析不了,这时候就要查网络了。

    1. 网络排查三连

    # 1. 查 Service 和 Endpoints(看后端有没有挂上Pod)
    kubectl get svc <svc-name> -n <namespace>
    kubectl get ep <svc-name> -n <namespace> # 如果ENDPOINTS为空,说明Pod探针失败或标签不匹配

    # 2. 测试 CoreDNS 解析
    kubectl exec -it <pod-name> -n <namespace>nslookup kubernetes.default
    kubectl exec -it <pod-name> -n <namespace>nslookup <your-service-name>

    # 3. 查 NetworkPolicy(是不是误拦截了)
    kubectl get networkpolicy -A

    # 4. 查 kube-proxy 和 CNI 插件日志
    kubectl logs <kube-proxy-pod> -n kube-system –tail=50
    kubectl logs <calico-node-pod> -n kube-system –tail=50 # 以Calico为例

    2. 存储排查

    # 查看 PVC 状态,如果是 Pending 说明存储供应失败
    kubectl get pvc -A

    # 查看 PV 详细事件
    kubectl describe pvc <pvc-name> -n <namespace>

    💡 集群网络故障典型表现:

    • Pod能起,但跨节点不通:CNI插件(如Calico/Flannel)挂了,或者底层物理网络(VXLAN/BGP)路由问题。
    • 域名解析失败:CoreDNS Pod异常,或者节点上的 resolv.conf 被篡改。
    • Service访问不通:kube-proxy没正常下发iptables/IPVS规则,或者后端Pod探针全挂导致Endpoints为空。

    🛠️ 终极杀器:如果以上命令看不出问题,直接上 tcpdump 抓包,或者在容器里用 curl -v 和 telnet 测端口,能解决99%的网络玄学问题。


    五、 业务恢复:分级处理,止血优先

    故障排查清楚了,接下来是恢复业务。记住:能摘除故障节点就摘除,别死磕修复,业务优先!

    1. 可快速恢复的场景

    • 代码/配置变更引起的雪崩:直接回滚。kubectl rollout undo deployment/<name> -n <namespace>
    • 单节点故障(如硬件损坏、内核Panic):直接隔离并驱逐Pod,让调度器把它调度到健康节点。# 标记节点不可调度
      kubectl cordon <node-name>
      # 驱逐节点上的Pod(注意加 –ignore-daemonsets 和 –delete-emptydir-data)
      kubectl drain <node-name> –ignore-daemonsets –delete-emptydir-data –force

    • 单点资源耗尽:临时扩容节点,或者调整HPA。

    2. 需谨慎操作的场景

    • etcd 数据损坏/丢失:
      • 前提:必须有最近的etcd备份!
      • 风险:恢复etcd会丢失备份点之后所有的集群状态变更(比如你刚建的Pod、刚改的配置全没了)。
      • 操作:停掉apiserver,使用 etcdctl snapshot restore 恢复数据,重启etcd和apiserver。不到万不得已,不要走这一步。
    • 节点底层OS/运行时彻底崩溃:不要尝试去重启kubelet或containerd,直接走上面的 cordon + drain 流程,然后让底层IaaS团队去重装系统或重建节点。

    六、 根因分析:找背锅侠

    业务恢复了,复盘不能少。常见故障诱因及排查路径:

  • 资源耗尽(内存/磁盘/inode):看Prometheus监控,找故障前5分钟哪个指标突变。查审计日志看是哪个命名空间的Pod在疯狂写日志。
  • 配置变更误操作:查 apiserver 的 audit log(审计日志),看故障时间点谁执行了 kubectl apply 或 kubectl delete。
  • 证书过期:看kubelet日志,如果有 x509: certificate has expired 字样,就是它了。
  • 网络策略误删/误配:查 NetworkPolicy 的变更记录。
  • 镜像拉取失败:查节点上的 crictl 日志或 /var/log/messages,看是不是 Harbor 挂了或者网络抖动。
  • 怎么找根因?
    不要拍脑袋!顺着 kubectl get events 的时间线,结合 Grafana 监控大盘的指标突变,再辅以 apiserver 审计日志,形成证据链。


    七、 事后加固:擦屁股的艺术

    故障处理完,如果不做加固,下次还会翻车。

  • 资源规范:强制要求所有Deployment必须配置 requests 和 limits,通过 OPA/Gatekeeper 或 Kyverno 做准入控制。
  • 节点资源预留:配置 kubelet 的 –kube-reserved 和 –system-reserved,给系统组件和OS留足内存和CPU,防止被业务Pod挤死。
  • Pod优先级与抢占:配置 PriorityClass,确保核心交易链路的Pod在资源不足时能抢占非核心任务的资源。
  • 监控告警补齐:把磁盘使用率、inode使用率、证书过期时间、etcd leader变更等指标加入告警,阈值调合理。
  • etcd 备份与演练:写个定时脚本备份etcd到OSS/S3。最重要的是:每个季度必须做一次恢复演练! 备份不等于能恢复。
  • 变更审批与灰度:生产环境严禁直接 kubectl apply,必须走CI/CD流水线,且核心服务必须配置滚动更新策略(maxSurge 和 maxUnavailable)。

  • 八、 总结:高频踩坑血泪教训

    最后,总结几个我见过无数人踩过的坑,大家引以为戒:

  • 盲目重启节点导致调度雪崩:节点只是网络抖动变成NotReady,你一去重启,上面的Pod全掉线,调度器瞬间把流量打到其他节点,直接把其他节点也压垮。
  • 不看Events就猜原因:上来就重启Pod,结果发现是 ConfigMap 没更新,重启一万次也没用。
  • 探针配置过激引发健康检查风暴:livenessProbe 的 timeoutSeconds 设得太短,或者接口本身响应慢,导致K8s疯狂杀Pod,把活着的业务也搞死了。建议:核心服务慎用 livenessProbe,多用 readinessProbe。
  • 磁盘满导致kubelet停摆:只监控了磁盘容量,没监控 inode。结果小文件太多把 inode 撑爆了,磁盘还有空间但 kubelet 直接罢工。
  • etcd备份从未演练过恢复:平时备份跑得欢,真出事了一恢复,发现备份脚本只备份了元数据没备份数据,或者密码丢了,直接原地去世。

  • K8s 运维就是一场修行,故障不可怕,可怕的是没有预案和复盘。希望这篇实战复盘能帮大家在遇到集群级故障时,做到心中有数,手中有剑。

    如果你觉得这篇文章对你有帮助,或者你也在生产环境踩过类似的坑,欢迎在评论区交流你的“血泪史”!

    觉得有用,别忘了点个赞、收藏一下,以备不时之需(毕竟排查故障时,你可能只想直接复制命令)!我们下期见!

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » K8s生产集群故障应急处置实战:节点NotReady、Pod雪崩与资源耗尽的现场排查复盘
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!