如何在香港服务器的Debian系统中结合VXLAN+EVPN,构建跨机房低延迟网络?

凌晨 1:40,我盯着香港葵涌机房两块 25G 链路上忽明忽暗的绿灯,另一头将军澳机房里的小伙伴在 Slack 里回我一个 ✅。客户要的是两个机房活跃-活跃、RTT < 2 ms、同网段漂移迁移和不中断维护。我们把方案聚焦到 VXLAN + EVPN:
- VXLAN 负责二层封装,跨 L3 承载层(Underlay)跑。
- EVPN(BGP 控制平面)负责分发 MAC/IP、网关信息,避免泛洪。
这篇文章,我按我当晚部署的顺序、踩过的坑、现场的应急操作,把细节讲全,既讲得让新同学能照着做,也让老兵能看得过瘾。
1. 目标与边界
业务目标
- 两地机房(HK1=葵涌,HK2=将军澳)互为生产;
- 同一租户网段可跨机房漂移(例如 10.10.10.0/24);
- 端到端 RTT <= 2 ms(香港本地专线/互联网混合);
- 变更可滚动发布,无“全网黑”。
技术边界
- 设备以x86 服务器 + Debian 12为主,ToR 交换机仅做 L3 转发(不开厂商 EVPN 功能,节省成本);
- EVPN 控制平面用 FRR 9.x;
- Underlay 可走运营商 L3/MPLS 或加密隧道(WireGuard/IPsec),本文示例用 WireGuard;
- VXLAN 走 UDP/4789,单播模式(EVPN 控制平面学习,禁泛洪学习)。
2. 现场硬件与版本(实测参数)
| 项目 | HK1(葵涌) | HK2(将军澳) |
|---|---|---|
| 服务器型号 | Dell R6525(双 EPYC 7413) | Dell R6525(双 EPYC 7413) |
| 内存 | 256 GB DDR4 | 256 GB DDR4 |
| 网卡 | Mellanox ConnectX-5 EN(25GbE ×2) | Mellanox ConnectX-5 EN(25GbE ×2) |
| 系统 | Debian 12 (bookworm) kernel 6.1 | Debian 12 (bookworm) kernel 6.1 |
| FRR | 9.1(frr, frr-pythontools) | 9.1 |
| 时钟 | chrony(对齐到香港授时) | chrony |
| 角色 | Leaf×6 + RR×2 | Leaf×6 + RR×1 |
说明:我们在每个机房至少放 1 台 BGP Route Reflector(RR),跨机房再各放一台,保证控制平面三节点容灾(3 台 RR)。
3. 地址/VNI/角色规划
3.1 Underlay IP(用于 RR 与 Leaf 建立 iBGP)
| 角色 | 节点 | Loopback | Underlay MTU | 说明 |
| RR | rr-hk1-1 | 10.255.0.11/32 | 1500(或 9000) | iBGP 源地址 |
| RR | rr-hk1-2 | 10.255.0.12/32 | 1500(或 9000) | |
| RR | rr-hk2-1 | 10.255.0.21/32 | 1500(或 9000) | |
| Leaf | hk1-leaf-[1..6] | 10.255.1.x/32 | 1500(或 9000) | 作为 VTEP 源 |
| Leaf | hk2-leaf-[1..6] | 10.255.2.x/32 | 1500(或 9000) | 作为 VTEP 源 |
MTU 提醒:VXLAN 头开销约 50 bytes。若上游仅 1500,建议把业务接口 MTU降到 1450(或协商启用 9000 jumbo)。
3.2 VNI/VLAN/子网
| 业务 | VLAN | VNI | 子网 | 网关(Anycast) |
| app-tenant-a | 10 | 10010 | 10.10.10.0/24 | 10.10.10.1/24 |
| db-tenant-a | 20 | 10020 | 10.20.20.0/24 | 10.20.20.1/24 |
| 管理/O&M | 99 | 10999 | 10.99.99.0/24 | 10.99.99.1/24 |
| L3 VNI(IRB) | - | 5000 | 0.0.0.0/0(虚拟) | 承载 type-5 路由 |
我们用对称 IRB设计:每个 Leaf 都承载 SVI(Anycast GW),互通走 L3 VNI 5000 的 type-5 路由,路径对称、收敛快。
4. Underlay(跨机房 L3)与安全
两地之间有一条低时延运营商专线 + 备份互联网。我们在每个 Leaf/RR 上起一个 WireGuard(wg0),只把 EVPN 控制平面与必要的监控走 wg0(数据面 VXLAN 可直接走物理/专线)。
/etc/wireguard/wg0.conf(示例)
[Interface]
Address = 172.31.0.11/32
PrivateKey = <RR_OR_LEAF_PRIVATE_KEY>
ListenPort = 51820
MTU = 1420
[Peer]
PublicKey = <peer_rr_hk2_key>
AllowedIPs = 172.31.0.21/32
Endpoint = rr-hk2-1.example.hk:51820
PersistentKeepalive = 15
生产中建议用 Ansible/Salt 统一下发密钥、AllowedIPs;MTU 1420 是常用起步值,结合路径 MTU 进一步微调。
5. Debian 基线与内核/网卡调优
安装包
apt update && apt install -y frr frr-pythontools bridge-utils vlan iproute2 ethtool wireguard-tools chrony tcpdump
内核参数(/etc/sysctl.d/99-evpn.conf)
# VXLAN/UDP 相关缓冲
net.core.rmem_max = 33554432
net.core.wmem_max = 33554432
net.ipv4.udp_mem = 98304 262144 393216
net.ipv4.udp_rmem_min = 4096
net.ipv4.udp_wmem_min = 4096
# 邻居表容量
net.ipv4.neigh.default.gc_thresh1 = 4096
net.ipv4.neigh.default.gc_thresh2 = 8192
net.ipv4.neigh.default.gc_thresh3 = 16384
# 允许非对称路由环境下的返回路径(看场景)
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
# 开启转发(IRB)
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
网卡 offload 建议(视驱动而定:ConnectX 通常保留 GRO/GSO,关闭 LRO,开启 TSO)
ethtool -K eth0 lro off
ethtool -K eth0 gro on gso on tso on
# 多队列中断绑核(示例,只展示思路)
for i in /proc/irq/*/eth0-TxRx-*; do echo 1 > $i/smp_affinity_list; done
6. L2/L3 设备与桥接结构
我们不依赖 OVS,全部走 Linux 原生 vlan-aware bridge + VXLAN 设备。
/etc/network/interfaces(Leaf 示例)
auto lo
iface lo inet loopback
post-up ip addr add 10.255.1.11/32 dev lo
# 物理上行(到 ToR)
auto eth0
iface eth0 inet manual
mtu 9000
auto eth1
iface eth1 inet manual
mtu 9000
# 聚合成 bond0(可选 LACP)
auto bond0
iface bond0 inet manual
bond-mode 802.3ad
bond-slaves eth0 eth1
bond-miimon 100
bond-lacp-rate 1
mtu 9000
# 主桥,VLAN 感知
auto br0
iface br0 inet manual
bridge_ports bond0
bridge_stp off
bridge_vlan_aware yes
mtu 9000
# VXLAN 设备(与 EVPN 协作,learning 由控制平面负责)
auto vxlan10010
iface vxlan10010 inet manual
pre-up ip link add vxlan10010 type vxlan id 10010 local 10.255.1.11 dstport 4789 nolearning
pre-up bridge vlan add dev vxlan10010 vid 10 pvid untagged
post-down ip link del vxlan10010
mtu 8950
# 把 vxlan 设备、VLAN 子接口都并入 br0
iface br0 inet manual
bridge_ports bond0 vxlan10010
# SVI(Anycast GW,IRB)
auto br0.10
iface br0.10 inet static
address 10.10.10.1/24
mtu 8950
# 其他业务网络按上面模式增加 vxlan10020、br0.20 ...
关键点:vxlan 设备加 nolearning,交给 EVPN 来下发 FDB(外部学习,extern_learn)。在新内核+FRR 里,zebra 会把 EVPN 路由转换为内核 FDB 项。
7. FRR(EVPN+BGP)配置
7.1 FRR 守护进程开关(/etc/frr/daemons)
zebra=yes
bgpd=yes
evpn=yes
# 其他保持缺省
7.2 Leaf(VTEP)上的 /etc/frr/frr.conf(核心片段)
frr version 9.1
service integrated-vtysh-config
hostname hk1-leaf-01
# Loopback 作为 BGP update-source,也是 VTEP 源
interface lo
ip address 10.255.1.11/32
# 把 VXLAN 与桥的绑定告知 FRR(evpn 集成)
evpn
vni 10010
rd 65001:10010
route-target import 65001:10010
route-target export 65001:10010
bridge-domain br0 10
exit-vni
vni 10020
rd 65001:10020
route-target import 65001:10020
route-target export 65001:10020
bridge-domain br0 20
exit-vni
# L3 VNI(对称 IRB)
vni 5000 l3
rd 65001:5000
route-target import 65001:5000
route-target export 65001:5000
exit-vni
router bgp 65001
bgp router-id 10.255.1.11
no bgp default ipv4-unicast
neighbor RR peer-group
neighbor RR remote-as 65001
neighbor 10.255.0.11 peer-group RR
neighbor 10.255.0.12 peer-group RR
neighbor 10.255.0.21 peer-group RR
update-source lo
address-family l2vpn evpn
neighbor RR activate
advertise-all-vni
advertise-default-gw
advertise-svi-ip
exit-address-family
# (可选)用于 Underlay/北向路由的 IPv4/IPv6 AFI/SAFI 按需开启
advertise-default-gw + advertise-svi-ip:让其它 VTEP 学到本地 SVI 的网关 MAC/IP,实现 Anycast GW。
7.3 RR(Route Reflector)/etc/frr/frr.conf(简化)
frr version 9.1
service integrated-vtysh-config
hostname rr-hk1-1
router bgp 65001
bgp router-id 10.255.0.11
no bgp default ipv4-unicast
neighbor EVPN-CLients peer-group
neighbor EVPN-CLients remote-as 65001
neighbor EVPN-CLients update-source lo
neighbor EVPN-CLients route-reflector-client
# 把所有 Leaf 加入
neighbor 10.255.1.11 peer-group EVPN-CLients
neighbor 10.255.1.12 peer-group EVPN-CLients
# ... 其它 leaf
neighbor 10.255.2.11 peer-group EVPN-CLients
address-family l2vpn evpn
neighbor EVPN-CLients activate
retain route-target all
exit-address-family
RR 不需要创建 VNI/桥;它只负责分发 EVPN 路由(type-2/3/5)。
8. 验收与可观测性
BGP/EVPN 路由
vtysh -c "show bgp l2vpn evpn summary"
vtysh -c "show evpn vni"
vtysh -c "show bgp l2vpn evpn route type mac-ip"
内核转发表/FDB
bridge fdb show dev vxlan10010 | head
bridge vlan show dev br0
ip neigh show dev br0.10
数据包验证
tcpdump -ni any udp port 4789
ping -I br0.10 10.10.10.23 -c 3
时延抽样(真实一晚的抓取)
| 指标 | 改造前(L3 路由+NAT+防火墙) | 改造后(EVPN 对称 IRB) |
| HK1 ↔ HK2 RTT(ICMP p50) | 2.4 ms | 1.6 ms |
| 微服务 A→B(p95 应用级) | 28 ms | 6.4 ms |
| 跨机房迁移中断 | 3~5 s | < 300 ms(ARP 抑制+Anycast GW) |
注意:应用级延迟降低的核心来自路径对称与就近出口,而非“魔法加速”。
9. 常见坑与现场处理手记
MTU 黑洞:
- 现象:TCP 大包跨机房超时,小包正常。
- 排查:tracepath, tcpdump 看到 DF 报文被丢。
- 解决:下调 br0/br0.10/vxlan 的 MTU(1450/8950),或协调上游开 9000。
rp_filter 误伤回程:
- 现象:对称 IRB 下,返回路径偶尔不同,内核严格 RP 过滤丢包。
- 解决:将 rp_filter=0(宽松模式),或在边界强制 ECMP 哈希一致。
VXLAN learning 冲突:
- 现象:忘了 nolearning,内核与 EVPN 同时学习,FDB 抖动。
- 解决:VXLAN 设备关闭学习;以 EVPN 为准。
Anycast GW MAC 不一致:
- 现象:不同 Leaf 的 br0.10 MAC 不同,网关漂移不稳定。
- 解决:显式设置统一 GW MAC:ip link set dev br0 address 02:00:00:00:10:01,并在所有 leaf 统一;或使用 FRR 的 default-gw 广告。
Route-Target(RT)打错:
- 现象:某 VNI 在 HK2 学不到 HK1 的主机 MAC/IP。
- 解决:比对 show bgp l2vpn evpn route,统一 rt both 65001:VNI。
防火墙拦 UDP/4789:
- 现象:控制面邻居都好,数据面不通。
- 解决:南北/东西向 ACL 全面放行 VXLAN 端口,并留监控。
时钟漂移引发奇怪 Bug:
- 现象:某节点邻居频繁 flap,抓包看 Keepalive 正常。
- 解决:Chrony 对齐;BFD 超时也要结合真实 RTT 设置(如 tx/rx 300/300/900 ms)。
FRR 版本不一致:
- 现象:老版本 Leaf 不认识新字段,EVPN 路由被丢。
- 解决:生产前统一 FRR 版本(9.x+)。
10. 滚动变更与回退策略
灰度:先在 1 条 VNI(如 10010)启用 EVPN,对单一租户做 AB 对比,稳定后推广。
回退:保留原有 L3 互联路径,FRR 支持 no advertise-all-vni/按 VNI 下线;必要时 shutdown VXLAN 设备回落。
可观测:Prometheus + node_exporter + 自定义 vtysh 导出脚本,抓 BGP 邻居状态、VNI 数量、FDB 项计数、收敛时间。
11. 性能小抄(我们线上验证有效)
- GRO/GSO 开,LRO 关;
- txqueuelen 设为 5000(大流量突发场景);
- IRQ 绑核 + RPS/XPS 打散;
- net.ipv4.neigh.*gc_thresh* 翻倍,避免邻居垃圾回收;
- WireGuard 仅走控制面(小带宽),数据面直通专线;
- BFD 配合 EVPN:跨机房设较宽松超时,避免抖动;
- 流哈希按 5 元组,确保对称 IRB 下 A→B 与 B→A 同路径。
12. 最小化可复现(PoC)脚本段
创建 VNI 与桥(片段)
ip link add vxlan10010 type vxlan id 10010 local 10.255.1.11 dstport 4789 nolearning
ip link set vxlan10010 up
ip link add name br0 type bridge vlan_filtering 1
ip link set br0 up
# 绑定到桥并配置 VLAN 10
ip link set vxlan10010 master br0
bridge vlan add dev vxlan10010 vid 10 pvid untagged
# SVI 网关
ip link add link br0 name br0.10 type vlan id 10
ip addr add 10.10.10.1/24 dev br0.10
ip link set br0.10 up
FRR 一键下发(Ansible 变量模板化):略(生产请用模板/变量管理)。
13. 绿灯常亮的那一刻
凌晨 3:05,我们把最后一个租户的 VNI 也切过去,show bgp l2vpn evpn route 里 MAC/IP 学习干净利落。Grafana 的 p95 曲线从 20+ ms 掉到个位数,冷通道的风依旧呼啦啦,但心里不再凉。客户发来一句:“这回,跨机房迁移终于像拖拽窗口一样顺滑了。”
VXLAN+EVPN 并不是银弹,但当你把 MTU、网关、RT、时钟、Offload 这些小齿轮都校准,它就会像一台润滑良好的机车,在香港这座城市的光纤里安静而迅速地奔跑。
14. 附录:完整清单(可直接对照)
14.1 FRR Leaf 基础模板(精简)
frr version 9.1
service integrated-vtysh-config
hostname ${hostname}
interface lo
ip address ${loopback}/32
# EVPN VNI 映射
% for v in vnis:
evpn
vni ${v.id}
rd 65001:${v.id}
route-target import 65001:${v.id}
route-target export 65001:${v.id}
bridge-domain br0 ${v.vlan}
exit-vni
% endfor
# L3 VNI
evpn
vni 5000 l3
rd 65001:5000
route-target import 65001:5000
route-target export 65001:5000
exit-vni
router bgp 65001
bgp router-id ${loopback}
no bgp default ipv4-unicast
neighbor RR peer-group
neighbor RR remote-as 65001
neighbor 10.255.0.11 peer-group RR
neighbor 10.255.0.12 peer-group RR
neighbor 10.255.0.21 peer-group RR
update-source lo
address-family l2vpn evpn
neighbor RR activate
advertise-all-vni
advertise-default-gw
advertise-svi-ip
exit-address-family
14.2 网络接口模板(Debian ifupdown)
auto lo
iface lo inet loopback
post-up ip addr add ${loopback}/32 dev lo
auto bond0
iface bond0 inet manual
bond-mode 802.3ad
bond-slaves eth0 eth1
mtu ${mtu}
auto br0
iface br0 inet manual
bridge_ports bond0 ${vxlan_ports}
bridge_stp off
bridge_vlan_aware yes
mtu ${mtu}
# 动态渲染各 VNI/VLAN
% for v in vnis:
auto vxlan${v.id}
iface vxlan${v.id} inet manual
pre-up ip link add vxlan${v.id} type vxlan id ${v.id} local ${loopback} dstport 4789 nolearning
pre-up bridge vlan add dev vxlan${v.id} vid ${v.vlan} pvid untagged
post-down ip link del vxlan${v.id}
auto br0.${v.vlan}
iface br0.${v.vlan} inet static
address ${v.gateway}
mtu ${mtu_minus50}
% endfor
到这里,方案、配置、坑与解法就都摆在桌面上了。如果你也在香港两地跑机房、也在为跨机房低延迟和不停服迁移发愁,希望这份实操手记,能让你夜里少吹一点冷风。