节点 IPv6 前缀漂移:一次「只是告警」背后的跨节点 Pod 网络静默失效
本文最后更新于:2026年11月4日 晚上
前言
之前国庆 homelab 升级为 ipv4 + ipv6 双栈,近期又对 4 个节点进行了更新和重启。结果发现:一条 kubelet 告警,每 10 秒重复一次。
1 | |
第一反应通常是配置没对齐,重启一下 k3s 就完事。
实际取证的结果比这个严重得多:跨节点 IPv6 pod 通信已经断了,只是业务侧没报出来。
告警和真实影响面之间,差了整整一层。
现象
时间点:2026-10-29。
同一轮重启里,ISP 重新委派了 IPv6 前缀:
- 旧:
240e:xxxxxxxx:ae43::/64 - 新:
240e:xxxxxxxx:6440::/64
集群是 4 节点 k3s 双栈,Ubuntu 26.04,内核 7.0.0-42。
/etc/rancher/k3s/config.yaml 的 node-ip 里写的是旧 GUA 的字面量。
新前缀下发后,那个地址不再存在于任何接口上。
kubelet 每 10 秒做一次 secondaryNodeIP 校验,失败,相关字段就不写入 Node 状态。
Node 对象的 IPv6 InternalIP 停在旧地址上。
根因
节点 IPv6 身份绑定在了 ISP 下发的 GUA 字面量上。
GUA 由运营商给,前缀什么时候轮换由 ISP 说了算。
家庭宽带的场景下,前缀轮换是常态,不是异常。
把节点身份写死在一个运营商随时会改的地址上,这个设计本身就有问题。
取证:告警之外的真实影响
告警只是入口,真正要看的是网络 Cilium 那边。
Cilium agent 启动时读取节点地址,写入 CiliumNode 对象。
旧地址写进去之后,auto-direct-node-routes 生成不出跨节点 IPv6 直连路由。
修复前 ip -6 route 里只有本机 pod 的 /64,没有任何一条跨节点路由。
跨节点 IPv6 pod 通信实际中断。
集群上 pod(semaphore、mysql)的 IPv6 EndpointSlice 指向一个不存在的地址。
📝Notes:
这类失效不触发业务告警。pod 本身是 Running 的,断的是跨节点路径。
方案取舍
四个方向摆出来对比:
| 方案 | 做法 | 代价 |
|---|---|---|
| A | 节点 IPv6 改用站点 ULA,GUA 只留接口做出站 / NAT | 一次性改动,之后不随 ISP 漂移 |
| B | systemd ExecStartPre 每次重算 GUA |
每次漂移都要重启,Node / Endpoint 全变 |
| C | 向 ISP 申请静态前缀 | 最干净,家庭宽带通常拿不到 |
| D | 退回单栈 IPv4 | 与既有双栈规格冲突,要重建 pod |
最终方案选 A。
我的判断是:节点身份只需要在站点内稳定可达,不需要绑定运营商前缀。
GUA 保留在接口上,出站和 NAT 照常用。
Pod 的 /56 和 Service 的 /112 网段不变,业务侧无感知。
选定的 ULA 是 fdb5:xxxxxxxx:1::/64,主机位 ::11 到 ::14:
::11→ n100-jumper-0::12→ n100-jumper-1::13→ n100-jumper-2::14→ n100-cheshi-0
实现:几处改动
- 修改
/etc/netplan/60-homelab-ula.yaml写入固定的规划好的 ULA IPv6 地址并netplan apply
YAML 内容如下:
1 | |
IPv4 地址和默认路由都保留,不需要重写 cloud-init 生成的 50-cloud-init.yaml。该文件 YAML 内容示例如下:
1 | |
📝Notes:
netplan 多文件按文件名排序合并,
60-homelab-ula.yaml排在50-cloud-init.yaml之后。
生效路径:只重启 k3s 不够
只重启 k3s, 不重启 cilium agent: 这是整个处置里最容易漏的一步。
改完 config.yaml 重启 k3s,Node 对象的 InternalIP 会更新。但 cilium-dbg node list 里还是旧地址。跨节点路由还是缺的。Cilium agent 只在启动时读取 Node 地址,写进 CiliumNode。Node 更新了它不会自己重新读。必须逐台重启 cilium agent。
重启后 cilium-dbg node list 的 IPv6 列变成各自 ULA,ip -6 route 里出现 via <对方 ULA> 的直连路由。
📝Notes:
逐台重启,别一把全停。agent 停掉期间该节点的 pod 网络会短暂中断。
验证
线上验收覆盖 6 个维度:
- 4 台 Node 的 IPv6 InternalIP 均为规划 ULA,状态 Ready
secondaryNodeIP计数为 0cilium-dbg node list的 IPv6 列是各自 ULA- 出现 3 条跨节点直连路由
- 跨节点 pod IPv6 连通,三个业务命名空间 Running 且 HTTP 可用
TestNodeAddressingPASS
路由器侧也做了只读核查:LAN 是 br-lan 桥,没有 ULA 配置,没有该 /64 路由与邻居表项。节点间 IPv6 走二层转发,路由器不需要改动。
总结
本次的经验教训:
- 节点 IPv6 身份不该绑定 ISP 下发的 GUA,站点内可达就够了
- 告警的严重程度和实际影响面不一定对得上,要自己取证
- Cilium agent 只在启动时读 Node 地址,Node 更新不会自动传导过去
- netplan 多文件对
addresses是追加语义,独立文件可以只写 ULA
千磨万击还坚劲,任尔东西南北风。
IPv6 GUA 地址前缀会漂,架构不该跟着漂。
以上。