PVE 的 EVPN 区域可以理解为“VXLAN 数据通道 + BGP EVPN 控制平面 + 可配置的三层网关/路由”。普通 VXLAN Zone 主要让不同节点上的 VM 处于同一张虚拟二层网;EVPN Zone 则进一步用于管理这些网络的路由,让不同 VNet 之间、甚至跨集群的网络互通成为可能。[1]

1
2
3
4
5
VM → VNet → PVE 节点上的 VXLAN
│
BGP EVPN 控制平面
│
其他节点的 VNet / 网关

这里 VXLAN 负责传数据,BGP EVPN 负责交换网络与路由信息。PVE 使用 FRRouting(FRR)运行 EVPN 控制器,因此配置 EVPN 不只是新增一个 Zone,还需要配置相应的 Controller。[1]

它比普通 VXLAN 多了什么?

能力 普通 VXLAN Zone EVPN Zone
跨节点延伸同一 VNet 的二层网络 可以 可以
在 VNet 上配置供 VM 使用的网关 不作为其主要功能 支持;可使用各节点相同的网关地址
不同 VNet 间的三层路由 需另行设计 可通过 EVPN/VRF 配置
对接外部网络 需另配网关和路由 可配置 Exit Node(出口节点),但仍须规划上游路由/SNAT

PVE 文档说明,EVPN VNet 可以使用各节点相同的网桥网关地址供客户机使用;跨 VNet 路由由 VRF 等机制配合实现。这不表示新建 EVPN Zone 后,所有 VNet 就会自动互通或自动上网。[1]

在 PVE 中大致怎么配置?

  1. 先让节点间的底层 IP 网络互通,并确认防火墙和 MTU 允许 VXLAN 流量。
  2. 在参与节点上准备 FRR;创建 EVPN Controller,规划 ASN 及节点间的对等连接方式。
  3. 创建 EVPN Zone,关联 Controller,设置一个专用于路由互联的 VRF VXLAN ID;它不能与业务 VNet 的 VXLAN ID 重复。
  4. 在 Zone 下创建 VNet,分别设置其 VXLAN Tag;需要三层网关时,再为 VNet 配置子网和网关。
  5. 如需访问 EVPN 外部网络,再规划 Exit Node、默认路由、上游回程路由或 SNAT;最后在 SDN 页面 应用并验证。[1]

选择建议:只想让两台 PVE 上的 VM 共享一个二层网段,先用普通 VXLAN,配置更简单;需要多个虚拟子网之间路由、分布式网关,或较复杂的跨节点/跨站点网络时,再考虑 EVPN。它的配置和排障成本也明显更高。

最后提醒两点:EVPN 使用 VXLAN 封装,底层 MTU 为 1500 时,业务侧通常按 1450 规划;而且 VXLAN 本身不加密,跨不可信网络仍需另行建立安全链路。[1]

一套先打通两个 VNet 之间通信的 PVE EVPN 最小示例;先不配置出口上网,避免把 BGP、网关和外部回程路由一起混进来。示例参数请替换成你的真实节点地址和空闲网段,不要直接照搬到生产网络。配置顺序参照 PVE 官方的 EVPN 示例。[1]

示例目标

假设已有 3 台 PVE 节点,节点间用于通信的 IP 分别是:

节点 节点间通信 IP
pve1 192.168.0.1
pve2 192.168.0.2
pve3 192.168.0.3

要创建两张虚拟网络:

VNet VXLAN ID 子网 VM 网关
evnet1 11000 10.0.1.0/24 10.0.1.1
evnet2 12000 10.0.2.0/24 10.0.2.1

前提:三台节点的通信 IP 已经互相可达,网络允许节点之间的 VXLAN UDP 流量;这些子网和 VXLAN ID 没有与现有配置冲突。底层链路 MTU 如果是 1500,本例将虚拟网络及 VM 网卡按 1450 规划。[1]

具体步骤

1. 准备 FRR

EVPN Controller 依赖 FRRouting。在每台参与的 PVE 节点上,按你使用的 PVE 版本核对并安装所需的 frr-pythontools,启用 FRR 服务。官方文档给出的准备命令是:[1]

1
2
3
apt update
apt install frr-pythontools
systemctl enable frr.service

正式操作前确认底层网络、防火墙和节点管理连接正常;更改生产节点网络时保留控制台或带外访问。

2. 新建 EVPN Controller

进入 数据中心 → SDN → 控制器(Controllers),新增 EVPN Controller,示例填写:

1
2
3
ID:evpnctl
ASN:65000
Peers:192.168.0.1,192.168.0.2,192.168.0.3

这里的 Peers 是 PVE 节点用于建立对等连接的地址,不是 VM 的地址;65000 是示例私有 ASN,使用前应与你现有 BGP 规划核对。[1]

3. 新建 EVPN Zone

进入 数据中心 → SDN → 区域(Zones),新增 EVPN:

1
2
3
4
5
ID:evpnzone
VRF VXLAN ID:10000
Controller:evpnctl
MTU:1450
节点:pve1、pve2、pve3

10000 是这个 Zone 用于三层路由互联的 VXLAN ID,必须与下面两个业务 VNet 的 11000、12000 不同。出口节点(Exit Nodes)先留空:本轮目标只是验证两个内部子网互通。[1]

4. 建两个 VNet 和子网

进入 数据中心 → SDN → VNets:

  1. 新建 evnet1,区选 evpnzone,**标记(Tag)**填 11000;在它下面新增子网 10.0.1.0/24,网关填 10.0.1.1。
  2. 新建 evnet2,区选 evpnzone,标记填 12000;在它下面新增子网 10.0.2.0/24,网关填 10.0.2.1。

这里的 Tag 是 VXLAN ID,不是你交换机上的 VLAN ID。EVPN 属于三层区域,配置的子网网关会部署在对应 VNet 上,供 VM 使用。[1]

然后回到 数据中心 → SDN 点击应用(Apply)。只点各个窗口里的“创建”,还不算完成部署。[1]

5. 配置 VM 并测试

例如在 pve1 上让 VM1 的网卡连接 evnet1,在 pve2 上让 VM2 连接 evnet2。在客户机系统内,或通过适用的 Cloud-Init,分别设置:

1
2
VM1:10.0.1.100/24,网关 10.0.1.1,MTU 1450
VM2:10.0.2.100/24,网关 10.0.2.1,MTU 1450

先让 VM1 测试到 10.0.1.1,VM2 测试到 10.0.2.1,再从 VM1 测试 10.0.2.100,反向也测一次。PVE 官方示例使用同样的“双 VNet、双子网”方式验证跨 VNet 互通。[1]

如果还要让 VM 上网,下一步才设置 Exit Nodes,并处理外部网关到 10.0.1.0/24、10.0.2.0/24 的回程路由,或根据拓扑设计 SNAT。只配 Exit Node 而没有回程路径,常见现象是 VM 的包发得出去、回不来。[1]

实战

创建EVPN控制器 - 节点建立EVPN-BGP邻居

  • ID:控制器名称
  • ASN:BGP 互联AS,内部维护使用保留AS即可
  • 对端:所有加入EVPN-VXLAN的节点

FRR新增配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

+router bgp 65001
+ bgp router-id 100.64.91.104
+ no bgp hard-administrative-reset
+ no bgp default ipv4-unicast
+ coalesce-time 1000
+ no bgp graceful-restart notification
+ neighbor VTEP peer-group
+ neighbor VTEP remote-as 65001
+ neighbor VTEP bfd
+ neighbor 100.64.91.61 peer-group VTEP
+ neighbor 100.64.91.62 peer-group VTEP
+ neighbor 100.64.91.63 peer-group VTEP
+ !
+ address-family l2vpn evpn
+ neighbor VTEP activate
+ neighbor VTEP route-map MAP_VTEP_IN in
+ neighbor VTEP route-map MAP_VTEP_OUT out
+ advertise-all-vni
+ exit-address-family
+exit
+!
+route-map MAP_VTEP_IN permit 1
+exit
+!
+route-map MAP_VTEP_OUT permit 1

创建EVPN区域

  • ID:区域名称
  • Primary Controller:选择上面创建的EVPN控制器
  • VRF-VXLAN Tag:是这个 EVPN 区域用于三层路由互联的 VXLAN ID (打通不同VXLAN区域三层),非业务VNets VXLAN VNI。

创建EVPN VNets

创建EVPN VNets - 子网

EVPN外部通信

Proxmox VE 9.2 三节点 EVPN/VXLAN 生产环境搭建与外部网络互联教程

适用版本:Proxmox VE 9.2(基于 Debian 13.5 “Trixie”,默认内核 7.0)[16]
文档中所有 GUI 选项名与官方 SDN 文档一致;CLI 片段仅作核对与自动化用途。
重要前提:官方把「核心 SDN」列为完全支持,但复杂路由(FRRouting)与控制器集成仍标注为 tech preview[6]。生产环境务必先在测试集群验证,并配合订阅与变更窗口。


1. 目标与架构

1.1 要达成的目标

编号 目标 关键机制
G1 三台 PVE 主机上任意 VM/CT 处于同一二层/三层网段,可任意迁移 EVPN + VXLAN Overlay,VNet 上配置 anycast 网关
G2 不同 VNet 之间按需互通(东西向),互不泄漏 EVPN Zone 内的 VRF(VRF VXLAN ID 独立于 VNet 的 VXLAN ID)[6]
G3 内部网段能访问外部网络(互联网/办公网/SAN 管理网) Exit Node 向 EVPN 网络通告默认路由 [6]
G4 外部网络能主动访问内部网段(北向) 出口路由器上的回程路由(静态或 BGP 动态)[6][13]
G5 跨站点/跨集群扩展(可选) Route-target Import、外部路由器作为 EVPN peer、WireGuard Fabric 承载跨站点 Underlay [6][16]
G6 生产可用性 多出口节点 + 主出口、rp_filter 调整、HA、监控与回滚流程

1.2 参考拓扑(本文示例)

graph TB
  subgraph EXT["外部网络"]
    UP["上游 L3 网关/核心路由器
10.10.10.1 (ASN 65100)"] INT["互联网 / 办公网"] UP --- INT end subgraph CL["PVE 9.2 三节点集群 (ASN 65000)"] P1["pve1
Underlay 10.10.10.11
Exit Node (Primary)"] P2["pve2
Underlay 10.10.10.12
Exit Node"] P3["pve3
Underlay 10.10.10.13"] P1 ---|"Underlay L3 / Fabric
VXLAN 4789/udp"| P2 P2 ---|" "| P3 P1 ---|" "| P3 end UP ---|"同网段 / VLAN trunk"| P1 UP ---|" "| P2 subgraph OV["EVPN Overlay (VRF vrf_evpn-zone, VNI 10000)"] V1["vnet-prod
VNI 11000
10.20.1.0/24 gw 10.20.1.1"] V2["vnet-dmz
VNI 12000
10.20.2.0/24 gw 10.20.2.1"] end P1 --> V1 P2 --> V1 P3 --> V2

1.3 地址与参数规划表(示例,落地时替换成你自己的)

项 取值 说明
集群节点 pve1 / pve2 / pve3 三节点,建议奇数(仲裁)
Underlay 网段 10.10.10.0/24 物理口 / bond 所在网段,网关 10.10.10.1
节点 Underlay IP .11 / .12 / .13 同时作为 VTEP 源 IP(未用 loopback 时)[6]
节点 Loopback(可选) 10.255.0.11-13/32 走 Fabric / BGP 控制器时用,VTEP 取 loopback [6]
Overlay ASN 65000 私有 ASN,同一节点上所有 EVPN 控制器必须同一 ASN[7]
外部路由器 ASN 65100 仅动态互联时使用
EVPN Zone ID evpn-zone VRF 名将是 vrf_evpn-zone
VRF VXLAN ID 10000 必须与所有 VNet 的 VXLAN ID 不同 [6]
VNet prod vnet-prod,Tag 11000,10.20.1.0/24,gw 10.20.1.1 anycast 网关
VNet dmz vnet-dmz,Tag 12000,10.20.2.0/24,gw 10.20.2.1 anycast 网关
Zone MTU 1450 VXLAN 封装占 50 字节,默认即 1450 [6]
VXLAN 端口 4789/udp 默认值,可改(vxlan-port)[6]
出口节点 pve1, pve2;Primary = pve1 多出口需配 Primary [6]

1.4 MTU 计算(生产最容易踩的坑)

承载方式 物理 MTU Overlay MTU 计算
纯 VXLAN over 1500 1500 1450 1500 − 50 [6]
纯 VXLAN over 9000(jumbo) 9000 8950 9000 − 50
WireGuard 上跑 VXLAN(跨站点) 1500 约 1390 1500 − 60(WG IPv4) − 50 [8]
VXLAN + IPsec(strongswan 传输模式) 1500 1370 1500 − 80(IPsec IPv6 最坏情况) − 50 [6]

所有 VM/CT 的网卡 MTU 也要同步设成 Zone MTU,否则会出现「ping 通但 TCP 卡住」的典型 PMTU 黑洞。


2. 前置条件与集群基线

2.1 版本与软件包(三节点全做)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 1) 确认版本
pveversion -v | head -5

# 2) SDN 核心包(8.1 起默认安装,升级来的集群需手动补)
apt update && apt install -y libpve-network-perl ifupdown2

# 3) 复杂路由依赖 FRR(opt-in)
apt update && apt install -y frr frr-pythontools
systemctl enable --now frr

# 4) 如需 WireGuard Fabric(9.2 新增能力)
apt install -y wireguard-tools

# 5) 确认 /etc/network/interfaces 末尾包含 SDN 引入行
tail -3 /etc/network/interfaces
# 必须存在: source /etc/network/interfaces.d/*

上面第 2、3、5 步与官方安装说明一致 [6]。

2.2 网络与系统基线检查

1
2
3
4
5
6
7
8
# 三节点互相可达(Underlay 必须全互联,或通过 L3 路由可达)
for i in 11 12 13; do ping -c1 -W1 10.10.10.$i; done

# 时间同步(证书/集群/日志排查依赖)
timedatectl status | grep -E 'synchronized|NTP'

# 转发开启
sysctl net.ipv4.ip_forward net.ipv6.conf.all.forwarding

2.3 防火墙放行清单

用途 协议/端口 方向
VXLAN 隧道 UDP 4789 节点 ↔ 节点
BGP(iBGP VTEP / eBGP 上行) TCP 179 节点 ↔ 节点、节点 ↔ 外部路由器
OSPF / OpenFabric(如用 Fabric 做 Underlay) IP 89 节点 ↔ 节点(直连口)
WireGuard Fabric UDP 51820(默认) 节点 ↔ 节点、节点 ↔ 外部 peer [6]
集群通信 TCP 8006、5405-5412(corosync)等 节点 ↔ 节点

注意:PVE 的 datacenter 防火墙若启用,需显式放行上述东西向流量;SDN 会为 VNet 自动生成 IPSet(vnet-all、vnet-gateway 等)供规则引用 [6]。


3. 第一步:搭建 Underlay(三种方案,选一)

Overlay 要求节点之间 IP 可达、且能承载 VXLAN。三节点用全互联最简单。

方案 A:现有物理 L3 网络(最省事,推荐起步)

节点保留原有 vmbr0 + 物理口 IP(10.10.10.11-13/24,网关 10.10.10.1),三节点在同一 VLAN/网段即可。

  • 优点:零额外组件,排障直观。
  • 缺点:节点 IP 即 VTEP IP,节点 IP 变更会牵动 Overlay [6]。

方案 B:SDN Fabric(OpenFabric / OSPF,PVE 9.0+)

适合 spine-leaf 或希望动态路由、双上联自动收敛的场景。

GUI:Datacenter → SDN → Fabrics → Add Fabric,选择 OpenFabric 或 OSPF;随后用「+」把节点加入并选择承载接口 [6]。

关键项:

  • IPv4 Prefix:例如 10.255.0.0/24,用于校验所有节点 Router-ID 落在该前缀内 [6]。
  • Router-ID:每节点唯一,系统会自动创建同名 dummy 接口作为 loopback(被动)[6]。
  • Interface IP:可用 /31 点对点地址,未配 IP 的接口按点对点处理 [6]。
  • OSPF 还支持 Redistribute(把 bgp/connected/kernel/static 引入 OSPF,并可挂路由映射过滤)[6]。

方案 C:WireGuard Fabric(PVE 9.2 新增,跨机房/跨公网加密)

WireGuard 本身只提供隧道,需配合 OSPF/BGP 才能动态路由;适合「两个数据中心走公网、链路要加密」[8][6]。

要点 [6]:

  • Fabric 上设 Persistent Keepalive(穿过有状态防火墙/NAT 时保活)。
  • 节点分 Internal(PVE 节点,填 Endpoint = 其他节点连接本节点用的 IP/主机名)与 External(非 PVE 设备,需填对端 Public Key、Endpoint = IP:端口、Allowed IPs)。
  • 每个接口会自动生成密钥对,私钥存于 /etc/pve/priv/wg-keys.cfg。
  • 系统会按 peer 的 Allowed IPs 自动生成内核路由;不想要可用 Skip Route Generation。
  • 记得 apt install wireguard-tools [6]。

提醒:VXLAN 自身不加密,跨站点务必叠加 WireGuard 或 IPsec [6]。


4. 第二步:创建 EVPN 控制器、Zone、VNet、Subnet

全部在 Datacenter → SDN 下操作,改完必须在 SDN 主面板点 Apply 才生效(改动先进入 pending 状态,可整体原子下发)[6]。

4.1 创建 EVPN 控制器

Datacenter → SDN → Controllers → Add → EVPN

字段 示例值 说明
ID evpnctl
ASN # 65000 用私有 ASN;同一节点上所有 EVPN 控制器必须同 ASN [7]
SDN Fabric (方案 B/C 时选对应 Fabric) 作为 Underlay,可自动生成 peer 列表 [6]
Peers 10.10.10.11,10.10.10.12,10.10.10.13 也可以填外部节点或路由反射器 [6]
Nodes 留空或指定节点 只在特定节点建立 EVPN 会话 [6]
Peer Group Name 默认 VTEP 定义多个 EVPN 控制器时,附加控制器必须用自定义 peer group 名 [7]
BGP Mode auto auto = 传统行为(iBGP;若存在 BGP 控制器则复用其会话);也可显式选 external 做 eBGP [6]
ebgp-multihop 视需要 仅在 BGP Mode = external 且非直连/用 loopback 时使用 [6]
入/出 Route Map 视需要(9.2 新增) 对收到的/发出的路由做过滤与属性改写 [6][16]

VTEP IP 自动派生规则(决定隧道源地址,务必理解)[6]:

  1. 若控制器关联了带 loopback 的 BGP/IS-IS 控制器 → 用 loopback IP;
  2. 否则若 peer 列表里某个 IP 就是本机配置的 IP → 用该 IP;
  3. 否则在默认路由表里查第一个 peer IP 的路由,取路由条目的源地址作为 VTEP IP —— 这条在动态 Fabric 环境下有坑:Apply 时内核路由表必须已有该条目 [6]。

4.2 创建 EVPN Zone

Datacenter → SDN → Zones → Add → EVPN

字段 示例值 说明
ID evpn-zone VRF 名会变成 vrf_evpn-zone
VRF VXLAN ID 10000 专用于 VNet 之间路由互通,必须与 VNet 的 VXLAN ID 不同 [6]
Primary Controller evpnctl 用于自动派生 VTEP IP [6]
Additional Controllers (可选) 9.2 起可挂多个控制器,附加控制器负责通告本 Zone 的 L2VPN EVPN 路由 [6]
VNet MAC Address 可留空自动生成 所有 VNet 的 anycast MAC [6]
Exit Nodes pve1,pve2 出口节点,向 EVPN 网络通告默认路由 [6]
Primary Exit Node pve1 多出口时强制走主出口;要用 SNAT 或上游不支持 ECMP 时必须设 [6]
Exit Nodes Local Routing 按需 需要从出口节点本身访问 VM/CT 服务时打开(默认只做「真实网络 ↔ EVPN」转发)[6]
Advertise Subnets 有静默虚机时打开 通告整段子网(Type-5),解决多 IP/静默主机不可达 [6]
Disable ARP ND Suppression 有漂移 IP 时打开 抑制 ARP/ND 会破坏「IP 漂移但 MAC 变化」的浮动地址场景 [6]
Route-target Import 跨 DC/对接外部 EVPN 时填 导入外部 EVPN 的 RT 列表 [6]
MTU 1450 默认 1450 [6]
VXLAN Port 4789 默认 [6]
Nodes pve1,pve2,pve3 Zone 部署范围

4.3 创建 VNet 与 Subnet

VNets → Add:

VNet Zone Tag(VXLAN ID)
vnet-prod evpn-zone 11000
vnet-dmz evpn-zone 12000

选中 VNet → Subnets → Add:

Subnet Gateway SNAT
10.20.1.0/24 10.20.1.1 先不勾(见 6.1.4)
10.20.2.0/24 10.20.2.1 先不勾

Gateway 就是 anycast 网关,每台节点上的 VNet 网桥都是同一个 IP,虚机把网关指向它即可,迁移后无需改配置 [6]。

4.4 Apply 并核对落盘配置

点 SDN → Apply 后,配置会写入 /etc/pve/sdn/(随 pmxcfs 同步到全集群),并翻译成 ifupdown2 / FRR 配置 [6]。核对形态如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# /etc/pve/sdn/controllers.cfg
evpn: evpnctl
asn 65000
peers 10.10.10.11,10.10.10.12,10.10.10.13

# /etc/pve/sdn/zones.cfg
evpn: evpn-zone
controller evpnctl
vrf-vxlan 10000
exitnodes pve1,pve2
exitnodes-primary pve1
mtu 1450

# /etc/pve/sdn/vnets.cfg
vnet: vnet-prod
zone evpn-zone
tag 11000
vnet: vnet-dmz
zone evpn-zone
tag 12000

# /etc/pve/sdn/subnets.cfg
subnet: evpn-zone-10.20.1.0-24
vnet vnet-prod
gateway 10.20.1.1
subnet: evpn-zone-10.20.2.0-24
vnet vnet-dmz
gateway 10.20.2.1

生产建议:不要手改这些文件,用 GUI/API 改,再用 pvesh get /cluster/sdn 或 GUI 的 pending 面板核对;把 /etc/pve/sdn/ 纳入备份/版本管理(它记录了 .running-config 与 .version)[6]。

等价的 API 写法(便于自动化):

1
2
3
4
5
6
7
pvesh create /cluster/sdn/controllers -controller evpnctl -type evpn -asn 65000 \
-peers 10.10.10.11,10.10.10.12,10.10.10.13
pvesh create /cluster/sdn/zones -zone evpn-zone -type evpn -vrf-vxlan 10000 \
-controller evpnctl -exitnodes pve1,pve2 -exitnodes-primary pve1 -mtu 1450
pvesh create /cluster/sdn/vnets -vnet vnet-prod -zone evpn-zone -tag 11000
pvesh create /cluster/sdn/vnets/vnet-prod/subnets -subnet 10.20.1.0/24 -gateway 10.20.1.1
pvesh set /cluster/sdn # 应用(等价于 GUI 的 Apply)

5. 第三步:验证 Overlay(做互联之前必须先过这一关)

5.1 控制平面

1
2
3
4
5
6
7
8
9
10
11
# BGP 会话:三节点之间应为 Established,且 L2VPN EVPN 地址族有前缀
vtysh -c "show bgp l2vpn evpn summary"
vtysh -c "show bgp l2vpn evpn"

# VNI 与 VTEP 邻居
vtysh -c "show evpn vni"
vtysh -c "show evpn vni 11000"
vtysh -c "show evpn next-hops vni 11000"

# VRF 与路由(VRF 名为 vrf_<zoneid>)
vtysh -c "show ip route vrf vrf_evpn-zone"

在 9.2 的 Web UI 中也可以直接在 SDN/EVPN 监控视图里查看会话状态与学习到的路由 [8]。

5.2 数据平面

1
2
3
4
5
6
7
8
9
# VXLAN 接口与 VRF 相关接口
ip -d link show type vxlan
ip -d link show | grep -E 'vrfbr_|vrfvx_'

# 本地 MAC 学习
bridge fdb show dev vnet-prod | grep -v permanent | head

# ARP/ND 表(EVPN 会把远端 MAC/IP 以代理形式下发)
vtysh -c "show evpn arp-cache vni 11000"

5.3 端到端

  1. 在 pve1 上建一台 Debian VM,接 vnet-prod,IP 10.20.1.100/24,网关 10.20.1.1,MTU 1450。
  2. 在 pve3 上建一台 VM 接 vnet-dmz,IP 10.20.2.100/24,网关 10.20.2.1,MTU 1450。
  3. 10.20.1.100 ping 10.20.2.100 —— 应通。这就是「跨 VNet 三层互通」,走的是 Zone 的 VRF [6]。
  4. 把 VM 从 pve1 热迁移到 pve2,再 ping 一次 —— 应通(anycast 网关 + EVPN 重学习)。

官方示例的判定标准也是这三条:同 Zone 不同 VNet 的虚机互相 ping 通即算 Overlay 正常 [6]。


6. 第四步:与外部网络互联(四种模式,按需组合)

先明确两个方向:

  • 南向/出向(内部 → 外部):由 Exit Node 通告默认路由解决 [6]。
  • 北向/入向(外部 → 内部):必须让外部路由器知道「去 10.20.x.0/24 要走哪个出口节点」。这一条没有例外,只是静态还是动态的区别 [6][13]。

6.1 模式 A:Exit Node + 静态回程路由(最稳、最常用,建议生产首选)

6.1.1 原理

Zone 里指定 Exit Nodes 后,出口节点会向 EVPN 网络通告一条默认路由;虚机的网关仍指向 anycast 网关,节点查 VRF 路由发现默认路由指向出口节点,于是把包交给出口节点,出口节点再按自己的物理默认网关送出 [6]。

数据流(以虚机在 pve3、出口为 pve1 为例)[13]:

1
VM(10.20.1.100) → anycast gw(10.20.1.1, 在 pve3) → pve1(出口, 10.10.10.11) → 上游(10.10.10.1) → 互联网

6.1.2 配置步骤

  1. Zone 中设 Exit Nodes = pve1,pve2,Primary Exit Node = pve1 [6]。
  2. 确认 pve1/pve2 有可用的物理默认网关:ip route show default。
  3. 在上游路由器/核心交换机上加回程路由(把 EVPN 网段指向出口节点)[6][13]:
1
2
3
4
5
6
7
# 上游设备(示例:Cisco/通用语法)
ip route 10.20.0.0/16 255.255.0.0 10.10.10.11
ip route 10.20.0.0/16 255.255.0.0 10.10.10.12 # 第二条用于冗余

# 若上游是 FRR/Linux:
ip route add 10.20.0.0/16 via 10.10.10.11
ip route add 10.20.0.0/16 via 10.10.10.12
  1. 上游支持 ECMP 时可两条等价;不支持 ECMP 时只保留指向 Primary Exit Node 的一条,与 Zone 的 Primary Exit Node 保持一致 [6]。

6.1.3 多出口节点必须调 rp_filter(否则表现为「有时通有时不通」)

多个出口节点时,包可能从 A 进、从 B 出,Linux 严格反向路径过滤会把回程包判为伪造而丢弃。官方示例给出的做法是建 drop-in sysctl 文件 [6]:

1
2
3
4
5
cat >/etc/sysctl.d/99-rp-filter.conf <<'EOF'
net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.all.rp_filter=0
EOF
sysctl --system

三节点都要做,并且要写进你的配置管理(Ansible/脚本),否则新建网桥或节点重装后会丢 [15]。注意 PVE 9 所在的 Debian 13 上 systemd-sysctl 不再读取 /etc/sysctl.conf,所以必须放 /etc/sysctl.d/。

6.1.4 如果上游加不了回程路由:用 SNAT

在 Subnet 上勾选 SNAT —— 在 EVPN Zone 中,转发由 EVPN 网关节点(出口节点)执行 [6]。这样内部虚机以出口节点 IP 出网,无需上游加路由,代价是外部无法主动访问这些虚机、也看不到真实源 IP。

SNAT 场景必须设置 Primary Exit Node,避免多出口各自 NAT 造成会话漂移 [6]。

6.1.5 出口节点自身要访问虚机服务

打开 Exit Nodes Local Routing(默认出口节点只在「真实网络 ↔ EVPN 网络」之间转发,本机不主动访问 EVPN 内的服务)[6]。

6.1.6 验证

1
2
3
4
5
6
7
8
9
10
11
12
13
# 出口节点上应能看到默认路由由 BGP 学到(type-5 默认路由)
vtysh -c "show bgp l2vpn evpn route type prefix"
vtysh -c "show ip route vrf vrf_evpn-zone" | head

# 在非出口节点上看是否选到了出口
vtysh -c "show ip route vrf vrf_evpn-zone" | grep '0.0.0.0/0'

# 从虚机出网并观察路径
ping -c2 1.1.1.1
traceroute -n 1.1.1.1 # 第二跳应为出口节点的物理网关

# 抓包定位(在出口节点)
tcpdump -ni any host 10.20.1.100 and not port 22

6.2 模式 B:与外部路由器跑 BGP,动态互通(不依赖静态路由)

适用于上游是真正的三层设备(FRR、Arista、Juniper、Cisco NX-OS 等,且支持 EVPN)。不要用不支持 EVPN 的家用/软路由做这件事(社区经验明确建议换成正经核心路由器)[15]。

6.2.1 两种可行做法

B-1:把外部路由器拉进 EVPN 会话 —— EVPN 控制器的 Peers 允许包含外部节点或路由反射器 [6]。PVE 9.2 支持为一个 Zone 配置多个 EVPN 控制器,因此推荐:

  1. 新建第二个 EVPN 控制器 evpnctl-ext:
    • ASN 仍填 65000(同一节点上所有 EVPN 控制器必须同 ASN)[7]
    • Peers = 上游路由器 IP(如 10.10.10.1)
    • Peer Group Name 必须自定义(如 VTEP_EXT),因为附加控制器不能再用默认的 VTEP [7]
    • BGP Mode = external;若用 loopback 互联再加 ebgp-multihop [6]
    • 需要精细控制时挂上入/出 Route Map(9.2)[6][16]
  2. 回到 Zone,把 evpnctl-ext 加进 Additional Controllers,由它负责把本 Zone 的 L2VPN EVPN 路由通告出去 [6]
  3. 上游路由器侧(以 FRR 为例):
1
2
3
4
5
6
7
8
9
10
11
12
13
router bgp 65100
bgp ebgp-requires-policy
no bgp default ipv4-unicast
neighbor 10.10.10.11 remote-as 65000
neighbor 10.10.10.11 description pve1-evpn
neighbor 10.10.10.12 remote-as 65000
neighbor 10.10.10.13 remote-as 65000
!
address-family l2vpn evpn
neighbor 10.10.10.11 activate
neighbor 10.10.10.12 activate
neighbor 10.10.10.13 activate
exit-address-family
  1. RT 必须对得上。先在 PVE 节点上读出实际使用的 RT,再在上游按该 RT 做 import,不要凭猜测写:
1
vtysh -c "show bgp l2vpn evpn route detail" | grep -i "Extended Community" | sort -u

PVE 侧自动派生的 RT 与控制器 ASN 关联(因此官方强调跨 Fabric 要保持 ASN 一致)[6];把租户网段导入上游的 VRF 时,用上游平台对应的 import / route-target import 语句。

B-2:只把 EVPN 网段以 IPv4 单播形式通告出去(上游不需要懂 EVPN):

  • 用 BGP 控制器做 eBGP,把 Zone 网段以普通 IPv4 路由发给上游(BGP 控制器可用于按节点定义不同 ASN 做 EBGP,也可用于向外部 BGP peer 导出 EVPN 路由)[6]。
  • 或使用 9.2 的 BGP Fabric:Fabric 支持把 connected / kernel / static / ospf 重新分发进 BGP,并可用 Route Map 逐源整形 [6][16]。

⚠️ 一个已知边界:PVE SDN 会把租户网络严格隔离在各自的 VRF 里,GUI 没有「把默认路由表泄漏进租户 VRF」的开关;如果需要 VRF 内访问宿主机默认表(例如让租户直接借用宿主默认网关),社区做法是在 /etc/frr/frr.conf.local 里追加 [15]:

1
2
3
4
router bgp 65000 vrf vrf_evpn-zone
address-family ipv4 unicast
import vrf default
exit-address-family

官方已表示正在做 Fabric 的 VRF 支持与 VRF 间泄漏 [15]。这是非官方变通方案,且 /etc/frr/frr.conf.local 是节点本地文件,不随 pmxcfs 同步,必须用配置管理工具分发,升级前先在测试环境验证。

6.2.2 BGP Fabric 与 EVPN 组合时的 ASN 规则(9.2)

  • 用 BGP Fabric 作 EVPN Underlay 时,Overlay(VTEP)会话默认是 iBGP,使用 EVPN 控制器的 ASN;每个节点的 Fabric ASN 通过 local-as 施加在 Underlay 邻居组上 [6]。
  • 因此EVPN 控制器 ASN 与各节点 Fabric ASN 必须不同(例:节点 65001/65002/65003,EVPN 控制器 65000)[6]。
  • 若把 EVPN 控制器的 BGP Mode 设为 external,VTEP 会话走 eBGP,此时各节点 Fabric ASN 同时作为 VTEP peer-group 的本地 ASN;EVPN 控制器 ASN 仍用于派生 RT [6]。
  • 用 BGP Fabric 作 EVPN Underlay 时,每节点必须有 IPv4 地址(EVPN 用它作 VTEP 地址)[6]。
  • 9.2 起 EVPN 控制器支持 IPv6 peer 地址,Underlay 可完全走 IPv6 [8][16]。

6.3 模式 C:跨站点 / 跨集群(DCI)

两种组合方式:

方式 做法 适用
共享同一 EVPN 域 站点间 Underlay 打通(推荐 WireGuard Fabric 加密),把对端节点加入同一 EVPN 控制器的 Peers;或让对端成为路由反射器 [6] 两站点同一租户平面、要 L2 延伸
独立 EVPN 域 + RT 互通 两个集群各自建 Zone,在 Zone 上配置 Route-target Import 导入对端 RT [6] 站点独立管理、只按需泄漏部分网段

要点:

  • VNI 与 RT 必须全站点统一规划(同一网段 = 同一 VNI)。
  • 跨站点 MTU 按 1.4 节再减一次 WireGuard 开销。
  • 若通过公网互联,VXLAN 必须叠加 WireGuard/IPsec [6]。
  • 站点间若要 eBGP,注意 ebgp-multihop 与 bgp-multipath-as-path-relax(对端 ASN 不同仍想 ECMP 时)[6]。

6.4 模式 D:只做南北向 NAT/端口映射(最保守)

不引入 BGP、也不在上游加路由:Subnet 勾 SNAT 让内部出网;需要外部主动访问的服务,再在上游或出口节点上做 DNAT/端口转发到 anycast 网关可达的虚机 IP。适用于边缘/实验环境,生产多租户不推荐(丢源 IP、无 ECMP、排查困难)。

6.5 外部互联的选型速查

场景 推荐模式 关键配置
上游是普通 L3 交换机/防火墙,能加静态路由 A Exit Nodes + Primary Exit Node + 上游回程路由 + rp_filter=0
上游不能加路由 A + SNAT Subnet SNAT + Primary Exit Node
上游支持 EVPN,要 ECMP/自动收敛 B-1 第二个 EVPN 控制器(external + 自定义 peer group)+ 上游 RT import
上游只懂 IPv4 BGP B-2 BGP 控制器 / BGP Fabric + redistribute + Route Map
跨机房、公网链路 C WireGuard Fabric + 统一 VNI/RT + MTU 重算
临时/实验 D SNAT + 端口映射

7. 生产环境加固清单

7.1 配置与变更

  • /etc/pve/sdn/ 纳入备份与 Git 版本管理;记录每次 Apply 前后的 .version [6]。
  • 所有变更走「先 staging 集群 → 再生产 Apply」,利用 SDN 的 pending + 一次性 Apply 做原子回滚 [6]。
  • 节点本地文件单独管理:/etc/frr/frr.conf.local、/etc/sysctl.d/99-rp-filter.conf、/etc/network/interfaces 均不随 pmxcfs 同步,用 Ansible 统一分发。
  • 变更前导出 FRR 运行配置留档:vtysh -c "show running-config" > /root/frr-$(date +%F).conf。

7.2 高可用与容量

  • 关键虚机配置 HA(配合 9.2 的 HA Disarm/Arm 维护流程做计划内维护)。
  • 出口节点至少两个,但只让一个通告默认路由(Primary Exit Node)以避免回环与 ECMP 不对称 [6][6]。
  • 若坚持多出口负载分担,上游必须支持 ECMP,且三节点全部关闭严格 rp_filter [6][15]。
  • 跨 VNet 通信尽量在 EVPN 内部完成(Zone 的 VRF),不要把东西向流量绕到外部路由器。

7.3 观测

  • 采集 BGP 会话状态:show bgp l2vpn evpn summary(Established 数、Up/Down 时长)[6]。
  • 采集 VNI/邻居数:show evpn vni、show evpn next-hops vni <VNI>。
  • 采集节点侧:ip -s link show type vxlan(丢包/错误计数)、bridge fdb 条目数。
  • 用 9.2 的 SDN/EVPN 监控视图做日常巡检入口 [8]。
  • 上游设备侧监控回程路由是否还在(静态路由最容易被人误删)。

7.4 安全

  • VXLAN 端口 4789/udp 只允许集群节点与已知出口互通,禁止从办公网/互联网直入。
  • 跨站点一律加密(WireGuard Fabric 或 VXLAN over IPsec)[6]。
  • 用 PVE 防火墙 + SDN 自动生成的 IPSet(vnet-all、vnet-gateway、vnet-no-gateway)实现 VNet 级最小放行 [6]。
  • 只在必要时开 Disable ARP ND Suppression(它会放大广播),并确认确有浮动 IP 需求 [6]。

7.5 版本与升级

  • PVE 9.2 基于 Debian 13.5、内核 7.0、QEMU 11.0、LXC 7.0、ZFS 2.4 [16];升级前用 pve8to9(跨大版本时)与测试集群演练。
  • FRR 升级需谨慎(历史上小版本升级也出现过 ARP/MAC 老化相关回归)[4];建议固定版本、先在测试集群跑数天。

8. 故障排查速查表

症状 优先检查 处理
VM 之间完全不通 vtysh -c "show bgp l2vpn evpn summary" 是否 Established;节点间 4789/udp 是否被防火墙拦 放行 UDP 4789;核对 Peers 列表与 ASN 是否一致 [7]
BGP 会话起不来 各节点 ASN 是否相同(iBGP 必须同 ASN);Underlay 是否可达 统一 ASN;用 loopback 时加 ebgp-multihop [6]
VXLAN 接口起来了但学不到远端 MAC VTEP 源 IP 是否为预期(自动派生可能取错) 显式提供 loopback 或让 peer 列表含本机 IP [6]
Apply 报错/不生效 是否忘了在 SDN 主面板 Apply;/etc/pve/sdn/ 配置是否合法 重新 Apply,检查 pending 面板 [6]
ping 通但 TCP/UDP 不通 MTU/PMTU 黑洞、rp_filter VM 网卡 MTU 设为 Zone MTU;多出口关闭严格 rp_filter [6][15]
内部能出去、外部回不来 上游缺回程路由 加上游静态回程路由或改走 BGP [6][13]
出网时通时不通 / TTL 超时 多个出口节点都在通告默认路由造成回环 设置 Primary Exit Node;关闭严格 rp_filter [6][15]
从出口节点本身 ping 不通虚机 出口节点默认不做本机到 EVPN 的转发 打开 Exit Nodes Local Routing [6]
有静默/多 IP 虚机不可达 网关看不到它的流量 打开 Advertise Subnets 通告整段 [6]
浮动 IP 漂移后不通 ARP/ND 抑制干扰 打开 Disable ARP ND Suppression [6]
跨站点通了但大包失败 WireGuard/IPsec 叠加后的 MTU 按 1.4 节重算(WG 场景约 1390)[6][8]
上游路由器看不到 EVPN 路由 RT 不匹配;附加控制器未加到 Zone 从 show bgp l2vpn evpn route detail 读实际 RT 再 import;检查 Additional Controllers [6]

9. 落地顺序总览(按此顺序做,每步都有验收)

  1. 基线:三节点装齐 frr frr-pythontools、ifupdown2、确认 source /etc/network/interfaces.d/*,放行 4789/udp 与 179/tcp。
  2. Underlay:方案 A(物理 L3)/ B(OpenFabric·OSPF Fabric)/ C(WireGuard Fabric)三选一,验收 = 三节点两两可达且 MTU 达标。
  3. 控制器:建 evpnctl(ASN 65000 + Peers),验收 = GUI/vtysh 中三节点 BGP 全 Established。
  4. Zone:evpn-zone(VRF VXLAN 10000,MTU 1450,Exit Nodes 先留空)。
  5. VNet/Subnet:vnet-prod 11000 / vnet-dmz 12000 + 网关,Apply。
  6. Overlay 验收:跨节点同 VNet 通、跨 VNet 通、热迁移后仍通。
  7. 南向出网:填 Exit Nodes + Primary Exit Node,Apply;验收 = 虚机能 ping 通 1.1.1.1,traceroute 第二跳是出口节点。
  8. 北向入网:上游加回程路由(模式 A)或建 evpnctl-ext 做 BGP(模式 B);验收 = 从外部网络 ping 通虚机。
  9. 加固:rp_filter drop-in、配置管理纳管节点本地文件、监控告警、备份与回滚演练。

10. 附:与本文配套的关键官方事实索引

  • SDN 支持状态:核心 SDN 完全支持;IPAM(含 DHCP)与复杂路由/控制器集成为 tech preview [6]。
  • Zone 类型:Simple / VLAN / QinQ / VXLAN / EVPN(BGP EVPN,VXLAN + BGP 做三层路由)[6]。
  • EVPN Zone 可用选项:VRF VXLAN ID、Primary/Additional Controller、VNet MAC、Exit Nodes、Primary Exit Node、Exit Nodes Local Routing、Advertise Subnets、Disable ARP ND Suppression、Route-target Import、MTU(默认 1450)[6]。
  • 控制器:EVPN / BGP / ISIS;EVPN 控制器含 ASN、SDN Fabric、Peers、Nodes、Peer Group Name、BGP Mode、ebgp-multihop,以及 9.2 的入/出 Route Map [6][16]。
  • Fabric 类型:OpenFabric、OSPF(9.0 起)、WireGuard、BGP(9.2 起,eBGP unnumbered);支持前缀列表与路由映射、OSPF 重分发、EVPN over IPv6 [6][16]。
  • 出口节点会向 EVPN 网络通告默认路由;外部网络需为 EVPN 网段加回程路由(静态或 BGP)[6][13]。
  • 多出口节点需关闭严格 rp_filter(drop-in 于 /etc/sysctl.d/99-rp-filter.conf)[6][15]。
  • PVE 9.2 平台基线:Debian 13.5 “Trixie”、内核 7.0、QEMU 11.0、LXC 7.0、ZFS 2.4 [16]。

运维技术交流群

发送邮件到 ➡️ [email protected]

或者关注WX公众号:网工格物

微信扫码

博客(最先更新)

https://songxwn.com/