扔掉电话簿

扔掉电话簿

💡 原文英文,约2400词,阅读约需9分钟。
📝

内容提要

Fly.io 重建了机器间私有网络 6PN。旧设计让每台主机保存全平台数十万条机器地址映射,同步困难且难以监控。新方案改为按需查询:VXLAN 遇到未知地址时触发事件,s6pnforwarderd 查询本地数据库后写入路由,每台主机仅保留约 100 至 200 条记录。地址无需转换,故障可观测,路由可绕行,并通过逐主机灰度切换安全上线。

🔎

延伸解读

从全量同步到按需查询的设计转向

旧方案要求每台主机在 eBPF map 中保存全平台数十万条机器地址映射,并通过 Corrosion 订阅全舰队更新。文章指出,各主机实际持有的条目数差异巨大,说明同步并未真正生效,且缺乏监控手段。新方案将路由表缩减到 100 至 200 条,只在 VXLAN 遇到未知地址时触发查询,由 s6pnforwarderd 查本地 SQLite 后写入路由。这本质上是把“推”模式换成“拉”模式,用首次访问延迟换取可观测性和可维护性。

首次连接约一秒延迟是明确代价

按需查询并非没有成本。文章说明,当两台从未通信过的 Machine 首次连接时,第一包到达尚无路由的主机,会触发查询;查询本身通常低于 100ms,但首包可能被丢弃,依赖 TCP 重传,而 Linux 默认重传超时为 1 秒,因此首次连接可能耗时约一秒。后续连接则直接走已写入的路由。作者提到未来可能通过暂存首包来修复。读者应把这一延迟视为设计取舍,而非故障。

故障域缩小,但新会话依赖控制面

新设计下,若 drift-agent 或 s6pnforwarderd 崩溃,已存在的路由继续工作,受影响的是新会话和刚迁移的 Machine。文章承认,刚迁移机器在旧设计下也是故障模式,而“从未通信过的机器无法建立新连接”是新引入的问题。不过相比每台主机持续加载全舰队路由,作者认为这是更小的代价。此外,路由可经中间主机转发,为绕开坏链路和构建高可用网关提供了基础。

灰度切换与失败关闭的安全设计

迁移没有停机窗口,而是让每台主机选择加入。新路径只处理带 0xfdaa fwmark 的包,且 udp-xdp 仅在满足条件时打标;未升级主机仍走旧 WireGuard 路径,形成暂时的非对称路由。安全上,udp-xdp 先校验源和目标 6PN 地址属于同一网络再打标,只有打标包才进入新路由表,因此若 udp-xdp 加载失败,流量不会通过,网络失败关闭。这种顺序避免了“先路由后过滤”在过滤器失效时放行全部流量的风险。

❓

Q&A

Fly.io 为什么要重建 6PN 私有网络?

旧设计让每台主机保存全平台数十万条机器地址映射(电话簿),同步困难且难以监控;新方案改为按需查询,每台主机仅保留约 100 至 200 条记录。

新的 6PN 网络是如何实现按需查询地址的?

VXLAN 遇到未知地址时触发 netlink 事件,drift-agent 监听并处理,s6pnforwarderd 订阅事件流后查询本地 Corrosion SQLite 数据库,然后写入一条路由,后续数据包直接通过。

新设计相比旧电话簿方案有哪些优势?

路由表极小(100-200 条),无需全平台订阅;故障可观测;路由可绕行(通过转发绕开坏链路);地址无需转换,两端一致便于调试;且网络故障时安全关闭(fail closed)。

新方案上线时如何保证安全切换?

新旧系统并行运行,逐主机灰度切换。新 VXLAN 路径只处理带 0xfdaa fwmark 的数据包,且仅当新组件运行、功能标志开启、且是发往其他主机的出站 6PN 流量或从 vxlan0 入站(非 wg0)时才打标记。旧主机继续使用旧路径,最终全部切换后删除旧代码。

新设计有哪些代价或局限性?

首次连接未知机器时,第一个数据包需等待查询(通常 <100ms),但 TCP 重传超时默认 1 秒,因此首次连接可能延迟约 1 秒;若 drift-agent 或 s6pnforwarderd 崩溃,已有路由仍工作,但新连接和刚迁移的机器会受影响。

新 6PN 网络如何实现路由绕行和故障绕开?

因为路由只是“将数据包发往某主机 over VXLAN”,下一跳不必是最终主机。开启转发后,收到发往已不在此主机的流量可转发给正确主机,从而绕开坏链路,并构建高可用网关而无需全量副本。

🏷️

标签

➡️

继续阅读