跳转到内容

K3s + Cilium 踩坑实录:Longhorn 插件无限重启?揪出 eBPF 路由脑裂的幕后黑手

🌱 创建: 2026/04/19 ⏱️ 更新: 2026/05/22

大家好,我是赛博包工头。欢迎来到赛博工地。

在咱们上一期对 K3s 故障节点进行了“核弹级强拆”并重新加入集群后,本以为可以顺利盖起 Longhorn 存储大坝了。结果,Longhorn 的核心存储特派员 longhorn-csi-plugin 却一直在无限崩溃重启(CrashLoopBackOff)。

表面上看是存储插件坏了,但经过一顿抽丝剥茧,最后发现:这根本不是存储的锅,而是一起典型的网络大动脉断裂案!

今天这篇排错实录,我们就来复盘一下如何解决这种“查号台还活着,但去查号台的路被炸断了”的底层网络脑裂问题。


💥 案发现场:伪装成存储故障的网络崩塌

Section titled “💥 案发现场:伪装成存储故障的网络崩塌”

当时查看 longhorn-csi-plugin 的崩溃遗言(Logs),发现了极其关键的一行报错:

E0419 00:36:26.346354 1 main.go:167] "Error connecting to CSI driver" err="context deadline exceeded"
time="2026-04-19T00:36:30.790662906Z" level=warning msg="Failed to initialize Longhorn API client Get \"http://longhorn-backend:9500/v1\": dial tcp: lookup longhorn-backend on 10.61.0.10:53: read udp 10.60.2.244:53943->10.61.0.10:53: i/o timeout. Retrying"

日志翻译: Longhorn 插件启动时,需要找集群内部的“114查号台”(CoreDNS,IP 为 10.61.0.10:53)去查询总控中心的地址。结果请求发出去后,如同石沉大海,直接报了 i/o timeout(连接超时)。因为拿不到总控地址,插件干脆拒绝启动,最后被 Kubelet 当做死进程给毙了。


🕵️‍♂️ 抽丝剥茧:派出侦察兵探路

Section titled “🕵️‍♂️ 抽丝剥茧:派出侦察兵探路”

为了验证是不是真的连不上 DNS,我跑到后台看了一眼 CoreDNS 的状态,发现它分明是 1/1 Running,活得好好的,安安稳稳地跑在 k3s-master-02 节点上。

接着,我拉起了一个带 nslookup 工具的 busybox 侦察兵进行极限测试:

Terminal window
kubectl run -i --tty --rm debug-net --image=busybox --restart=Never -- nslookup kubernetes.default

返回的结果非常绝望:

;; connection timed out; no servers could be reached

结论:查号台活得好好的,但去找查号台的路,全断了。


🧠 底层逻辑:大动脉为什么会断?

Section titled “🧠 底层逻辑:大动脉为什么会断?”

这要归咎于咱们这套集群的高级架构。

在安装 K3s 时,我们加上了 --disable-kube-proxy 参数。这意味着 Kubernetes 传统的基于 iptables 的内部流量转发机制被废弃了。全集群的 Service IP(包括内部 DNS 地址 10.61.0.10),全靠 Cilium 的 eBPF 机制在 Linux 内核底层进行拦截和高效转发。

但是!咱们刚才对 k3s-master-03 执行了“核弹级强拆”,导致整个集群的 Cilium 路由映射表(BPF Maps)出现了严重的数据断层和脑裂。

Cilium 彻底迷失了方向,不知道该怎么把 UDP 53 端口的请求跨节点发给 k3s-master-02 上的 CoreDNS,于是网络包在内核层直接被无情丢弃。底层网络一断,上层依赖内部域名的 Longhorn 存储插件自然跟着全军覆没。


🛠️ 抢修方案:网络管线“大换血”

Section titled “🛠️ 抢修方案:网络管线“大换血””

既然病根在底层的路由表缓存,咱们不需要重装,只需要强制集群对网络管线进行一次滚动重启(Rollout Restart),让 eBPF 重新绘制整张全网路由表即可。

请依次执行这排雷三把斧

第一斧:强制重建 Cilium 网络映射表

Section titled “第一斧:强制重建 Cilium 网络映射表”

让所有节点的 Cilium 特派员重新扫描集群,重写内核里的路由规则:

Terminal window
kubectl rollout restart ds cilium -n kube-system

(敲完后喝口水等个半分钟,让 3 个节点的 Cilium Pod 挨个重启完成)

第二斧:顺手重启查号台 (CoreDNS)

Section titled “第二斧:顺手重启查号台 (CoreDNS)”

为了防止 CoreDNS 本身残留什么僵尸缓存,给它也来一记还我漂漂拳:

Terminal window
kubectl rollout restart deploy coredns -n kube-system

第三斧:再次派出侦察兵验证验收

Section titled “第三斧:再次派出侦察兵验证验收”

等上面的网络和 DNS Pod 都处于 Running 状态后,重新敲一遍之前的测试命令:

Terminal window
kubectl run -i --tty --rm debug-net --image=busybox --restart=Never -- nslookup kubernetes.default

💡 预期结果: 只要这次没有报 timed out,而是瞬间返回了类似 Server: 10.61.0.10Address: 10.61.0.10:53 的解析结果(即便带了 NXDOMAIN 的小 Bug 也不影响),就说明全集群的大动脉彻底打通了!

大动脉一通,之前卡在 CrashLoopBackOfflonghorn-csi-plugin 就会瞬间找回组织,自动停止报错并挂载成功。

包工头施工笔记: 排查 K8s 故障时,如果上层应用报“连接超时”,不要急着重装应用。拔出网络排错“侦察兵”测一下底层连通性,往往能事半功倍。“遇到 eBPF 脑裂,一键 Rollout 重启网络插件”,这是赛博工地里必须掌握的保命神技!

最近更新: