当K8s节点“失联”:一次完整的故障排查与根因分析实录

2025.12.30 奇思妙想 1338
33BLOG智能摘要
深夜告警响起,一个K8s工作节点突然“失联”,状态从Ready变为NotReady,部分服务开始出现异常。这并非一次简单的故障,而是一次直抵系统核心的深度诊断之旅。本文将完整还原这次惊心动魄的排障实录:从控制平面视角的初步定位,到深入问题节点检查Kubelet进程与日志;从容排查器运行时与网络插件的连环依赖,到最终揪出“幕后真凶”——一个因内存泄漏而触发OOM Killer的“元凶”应用Pod。文章不仅提供了一套从“确认问题”到“根因恢复”的清晰操作路径,更总结了一份宝贵的节点健康排查清单,助你在下一次告警响起时,能迅速定位问题、从容化解危机,完成一次漂亮的运维实战。
— 此摘要由33BLOG基于AI分析文章内容生成,仅供参考。

当K8s节点“失联”:一次完整的故障排查与根因分析实录

当K8s节点“失联”:一次完整的故障排查与根因分析实录

深夜,告警铃声划破了宁静。监控大屏上,一个Kubernetes工作节点(Node)的状态从“Ready”跳变成了“NotReady”。集群虽然还在运行,但部分Pod已经飘红,服务开始出现零星超时。作为一名运维老兵,我知道,一次标准的“节点失联”排障之旅开始了。这不仅仅是敲几个命令,更是一次对集群健康状况的深度体检。下面,就是我这次排查的完整记录,希望能为你下次遇到类似问题提供清晰的路径。

第一步:确认问题与初步定位

首先,别慌。登录到Kubernetes控制平面节点,用最直接的命令看看集群节点状态。

kubectl get nodes

输出清晰地显示,名为 `node-worker-02` 的节点状态是 `NotReady`。`kubectl describe node node-worker-02` 命令能提供更多细节,但有时节点失联会导致这个命令卡住或返回超时。这时,我的习惯是转向集群的“上帝视角”——查看控制平面组件的日志。

# 查看kube-controller-manager日志,它负责节点状态管理
kubectl logs -n kube-system kube-controller-manager-master-node --tail=50 | grep -i node-worker-02

# 或者查看kubelet自己上报的状态(如果apiserver还能收到信息)
kubectl describe node node-worker-02 | grep -A 10 -B 5 Conditions

在 `describe` 命令的输出中,我重点关注 `Conditions` 字段。如果看到 `Ready` 状态为 `False`,并且 `Reason` 显示 `NodeStatusUnknown` 或 `KubeletStop`,这通常意味着控制平面(apiserver)已经有一段时间(默认40秒的心跳超时时间,加上5分钟的容忍窗口)没有收到来自该节点上 `kubelet` 的心跳了。

第二步:登陆问题节点,检查Kubelet

既然控制平面联系不上节点,那就直接SSH到 `node-worker-02` 上。这是最关键的一步,大部分根因都在这里。

1. 检查kubelet进程:

systemctl status kubelet

果然!服务处于 `inactive (dead)` 状态。尝试启动它:`sudo systemctl start kubelet`。如果启动失败,立刻查看日志:

sudo journalctl -u kubelet --since="1 hour ago" -f

踩坑提示: 我遇到过几次因为节点磁盘空间满(`/var` 或 `/` 分区)导致 kubelet 无法写入证书或日志而崩溃的情况。所以,启动前先顺手检查一下磁盘:

df -h

第三步:深入挖掘:资源与依赖

如果kubelet能启动但节点状态依然无法恢复,或者kubelet反复崩溃,就需要深入了。

2. 检查容器运行时: Kubelet 依赖容器运行时(如 containerd 或 docker)。

systemctl status containerd  # 或用 docker,取决于你的CRI
sudo ctr images list  # 检查containerd是否正常响应

有一次,一个异常的容器进程耗尽了PID,导致 containerd 无法创建新的容器,间接拖死了 kubelet。

3. 检查网络插件: 节点失联也可能是网络问题。Calico、Flannel等插件的Pod是否在该节点上运行正常?

# 在控制平面节点查看该节点上的系统Pod
kubectl get pods -n kube-system -o wide | grep node-worker-02

如果网络插件Pod是 `CrashLoopBackOff` 状态,需要进一步排查该节点的网络配置(如网卡、路由、防火墙)。实战经验: 我就曾被一台物理服务器上的防火墙规则坑过,它清除了CNI插件所需的iptables链。

第四步:根因浮现与恢复

经过一番排查,这次的问题根源是:系统内存不足,触发OOM Killer,杀掉了kubelet进程。 在 `journalctl` 日志中看到了清晰的 `Out of memory` 记录。

查看内存使用情况:

free -h
top

发现是一个部署在该节点上的应用Pod发生了内存泄漏,吃光了资源。临时解决方案是重启该Pod(或从控制平面驱逐节点上的Pod):

# 从控制平面驱逐节点上的所有Pod(会触发在其他健康节点重建)
kubectl drain node-worker-02 --ignore-daemonsets --delete-emptydir-data

注意: `drain` 命令在节点恢复通信后才能成功。如果节点完全失联,你可能需要强制删除Pod:`kubectl delete pod –force –grace-period=0`,但这有数据丢失风险。

在清理了问题Pod并确认kubelet稳定运行后,将节点重新加回集群调度:

kubectl uncordon node-worker-02

最后,通过 `kubectl get nodes` 确认节点状态恢复为 `Ready`。

总结:构建你的排查清单

一次“节点失联”事件,其实就是对以下清单的依次检查:

  1. 控制平面视角: `kubectl get/describe node` 查看状态和事件。
  2. 节点基础服务: SSH登录,检查 `kubelet`、`容器运行时` 进程与日志。
  3. 系统资源: 磁盘空间、内存、CPU、PID数是否耗尽?
  4. 网络与依赖: 网络插件Pod是否正常?节点网络连通性(到apiserver)是否完好?
  5. 底层基础设施: 如果是云主机,检查云提供商控制台;物理机则检查硬件(如NIC、RAID卡)状态。

每次排查都是一次学习。建议将关键的检查命令写成脚本,或在监控系统中为节点资源(内存、磁盘、kubelet心跳)设置更灵敏的预警,这样才能在“失联”演变为“灾难”前,优雅地将其化解。希望这篇实录能让你在下一次告警响起时,更加从容。

评论