上一篇 下一篇 分享链接 返回 返回顶部

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

发布人:Minchunlin 发布时间:2025-09-05 09:12 阅读量:862


凌晨 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

到这里,方案、配置、坑与解法就都摆在桌面上了。如果你也在香港两地跑机房、也在为跨机房低延迟和不停服迁移发愁,希望这份实操手记,能让你夜里少吹一点冷风。

目录结构
全文