VXLAN-EVPN 多租户私有网络测试文档
by cluaude code + glm5.1
1. 测试概述
1.1 目标
使用3台Ubuntu 24.04云主机 基于 VLAN + VXLAN/EVPN 技术构建多租户私有网络,验证:
- 同子网跨 TOR 东西向流量(L2 跨节点转发)
- EVPN 控制面 MAC/IP 自动学习与同步
- BGP Route Reflector 路由反射架构
- VXLAN 隧道封装正确性
1.2 测试拓扑
scss
┌──────────────────┐
│ RR (172.20.2.6)│
│ 仅 BGP EVPN RR │
│ 无 VTEP/无数据面 │
└────────┬─────────┘
│ iBGP EVPN
┌────────┴───────────────────────┐
│ │
┌───────┴──────┐ ┌───────┴──────┐
│ node1 │ │ node2 │
│ 172.20.2.9 │ │ 172.20.2.10 │
│ VTEP + 计算 │ │ VTEP + 计算 │
│ │ │ │
│ vm1-sub100 │◄──── VXLAN ────►│ vm2-sub100 │
│ 10.1.1.11 │ (VNI 10001) │ 10.1.1.12 │
│ │ │
│ vm1-sub200 │◄──── VXLAN ────►│ vm2-sub200 │
│ 10.1.2.11 │ (VNI 10002) │ 10.1.2.12 │
└──────────────┘ └──────────────┘
Underlay: 172.20.2.0/24 (内网互通)
Overlay: VNI 10001 → 10.1.1.0/24 (子网1)
VNI 10002 → 10.1.2.0/24 (子网2)
1.3 节点信息
| 节点 | 角色 | 内网 IP | 外网 IP | 网卡名 |
|---|---|---|---|---|
| RR | Route Reflector | 172.20.2.6 | 112.51.122.186 | enp0s16 |
| node1 | 计算节点 | 172.20.2.9 | 112.51.122.182 | enp0s16 |
| node2 | 计算节点 | 172.20.2.10 | 112.51.122.180 | enp0s16 |
1.4 Overlay 地址规划
| VNI | VLAN | 子网 | 用途 | node1 VM | node2 VM |
|---|---|---|---|---|---|
| 10001 | - | 10.1.1.0/24 | 租户子网1 | 10.1.1.11 | 10.1.1.12 |
| 10002 | - | 10.1.2.0/24 | 租户子网2 | 10.1.2.11 | 10.1.2.12 |
2. 环境准备
2.1 云主机要求
- 3 台 VM 位于同一内网子网(Underlay 互通)
- 安全组放行以下端口:
| 协议 | 端口 | 用途 |
|---|---|---|
| TCP | 179 | BGP 邻居建立 |
| UDP | 4789 | VXLAN 隧道数据 |
| UDP | 3784 | BFD 快速故障检测 |
| ICMP | - | 调试连通性 |
2.2 基础软件安装(三台均执行)
bash
# 安装 FRR
apt update && apt install -y frr iproute2 bridge-utils tcpdump
# 开启内核转发
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv4.conf.all.rp_filter=0
sysctl -w net.ipv4.conf.default.rp_filter=0
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
echo "net.ipv4.conf.all.rp_filter=0" >> /etc/sysctl.conf
echo "net.ipv4.conf.default.rp_filter=0" >> /etc/sysctl.conf
2.3 启用 FRR 守护进程(三台均执行)
bash
cat > /etc/frr/daemons <<'EOF'
bgpd=yes
ospfd=no
ospf6d=no
ripd=no
ripngd=no
isisd=no
bfdd=yes
pimd=no
ldpd=no
nhrpd=no
eigrpd=no
babeld=no
sharpd=no
pbrd=no
EOF
systemctl enable frr
systemctl restart frr
3. RR 节点配置
3.1 设计说明
RR 仅运行 BGP EVPN 控制面,不做 VXLAN 数据转发,不接入任何 VM。
3.2 FRR 配置
bash
cat > /etc/frr/frr.conf <<'EOF'
frr version 8.4.4
frr defaults traditional
no ipv6 forwarding
service integrated-vtysh-config
!
router bgp 65000
bgp router-id 172.20.2.6
!
neighbor 172.20.2.9 remote-as 65000
neighbor 172.20.2.9 description node1
neighbor 172.20.2.9 update-source enp0s16
neighbor 172.20.2.9 bfd
!
neighbor 172.20.2.10 remote-as 65000
neighbor 172.20.2.10 description node2
neighbor 172.20.2.10 update-source enp0s16
neighbor 172.20.2.10 bfd
!
address-family l2vpn evpn
neighbor 172.20.2.9 activate
neighbor 172.20.2.10 activate
neighbor 172.20.2.9 route-reflector-client
neighbor 172.20.2.10 route-reflector-client
retain route-target all
exit-address-family
!
bgp bestpath as-path multipath-relax
!
EOF
systemctl restart frr
3.3 关键配置说明
| 配置项 | 作用 |
|---|---|
update-source enp0s16 |
指定 BGP TCP 连接使用的源接口 |
route-reflector-client |
标记对端为 RR 客户端,反射其路由 |
retain route-target all |
RR 保留所有 RT 路由,不做本地 RT 过滤 |
bgp bestpath as-path multipath-relax |
允许 AS-Path 长度不同的路由做 ECMP |
4. node1 配置(计算节点)
4.1 数据面脚本
bash
cat > /root/setup-vxlan.sh <<'SCRIPT'
#!/bin/bash
set -e
LOCAL_IP=172.20.2.9
# 清理旧配置
ip link del br-10001 2>/dev/null || true
ip link del br-10002 2>/dev/null || true
ip link del vni10001 2>/dev/null || true
ip link del vni10002 2>/dev/null || true
ip netns del vm1-sub100 2>/dev/null || true
ip netns del vm1-sub200 2>/dev/null || true
ip link del veth-vm1 2>/dev/null || true
ip link del veth-vm2 2>/dev/null || true
# VNI 10001
ip link add vni10001 type vxlan id 10001 \
local ${LOCAL_IP} dstport 4789 nolearning
ip link set vni10001 up
# VNI 10002
ip link add vni10002 type vxlan id 10002 \
local ${LOCAL_IP} dstport 4789 nolearning
ip link set vni10002 up
# Bridge
ip link add br-10001 type bridge
ip link set vni10001 master br-10001
ip link set br-10001 up
ip link add br-10002 type bridge
ip link set vni10002 master br-10002
ip link set br-10002 up
# VM: vm1-sub100 (10.1.1.11)
ip netns add vm1-sub100
ip link add veth-vm1 type veth peer name eth0 netns vm1-sub100
ip link set veth-vm1 master br-10001
ip link set veth-vm1 up
ip netns exec vm1-sub100 ip link set eth0 up
ip netns exec vm1-sub100 ip addr add 10.1.1.11/24 dev eth0
ip netns exec vm1-sub100 ip route add default via 10.1.1.1
# VM: vm1-sub200 (10.1.2.11)
ip netns add vm1-sub200
ip link add veth-vm2 type veth peer name eth0 netns vm1-sub200
ip link set veth-vm2 master br-10002
ip link set veth-vm2 up
ip netns exec vm1-sub200 ip link set eth0 up
ip netns exec vm1-sub200 ip addr add 10.1.2.11/24 dev eth0
ip netns exec vm1-sub200 ip route add default via 10.1.2.1
echo "=== node1 数据面配置完成 ==="
ip -br addr | grep -E 'br-|vni|veth'
SCRIPT
chmod +x /root/setup-vxlan.sh
bash /root/setup-vxlan.sh
4.2 FRR 配置
bash
cat > /etc/frr/frr.conf <<'EOF'
frr version 8.4.4
frr defaults traditional
no ipv6 forwarding
service integrated-vtysh-config
!
router bgp 65000
bgp router-id 172.20.2.9
!
neighbor 172.20.2.6 remote-as 65000
neighbor 172.20.2.6 description RR
neighbor 172.20.2.6 update-source enp0s16
neighbor 172.20.2.6 bfd
!
address-family l2vpn evpn
neighbor 172.20.2.6 activate
advertise-all-vni
vni 10001
rd 65000:10001
route-target import 65000:10001
route-target export 65000:10001
exit-vni
vni 10002
rd 65000:10002
route-target import 65000:10002
route-target export 65000:10002
exit-vni
exit-address-family
!
EOF
systemctl restart frr
5. node2 配置(计算节点)
5.1 数据面脚本
bash
cat > /root/setup-vxlan.sh <<'SCRIPT'
#!/bin/bash
set -e
LOCAL_IP=172.20.2.10
# 清理旧配置
ip link del br-10001 2>/dev/null || true
ip link del br-10002 2>/dev/null || true
ip link del vni10001 2>/dev/null || true
ip link del vni10002 2>/dev/null || true
ip netns del vm2-sub100 2>/dev/null || true
ip netns del vm2-sub200 2>/dev/null || true
ip link del veth-vm3 2>/dev/null || true
ip link del veth-vm4 2>/dev/null || true
# VNI 10001
ip link add vni10001 type vxlan id 10001 \
local ${LOCAL_IP} dstport 4789 nolearning
ip link set vni10001 up
# VNI 10002
ip link add vni10002 type vxlan id 10002 \
local ${LOCAL_IP} dstport 4789 nolearning
ip link set vni10002 up
# Bridge
ip link add br-10001 type bridge
ip link set vni10001 master br-10001
ip link set br-10001 up
ip link add br-10002 type bridge
ip link set vni10002 master br-10002
ip link set br-10002 up
# VM: vm2-sub100 (10.1.1.12)
ip netns add vm2-sub100
ip link add veth-vm3 type veth peer name eth0 netns vm2-sub100
ip link set veth-vm3 master br-10001
ip link set veth-vm3 up
ip netns exec vm2-sub100 ip link set eth0 up
ip netns exec vm2-sub100 ip addr add 10.1.1.12/24 dev eth0
ip netns exec vm2-sub100 ip route add default via 10.1.1.1
# VM: vm2-sub200 (10.1.2.12)
ip netns add vm2-sub200
ip link add veth-vm4 type veth peer name eth0 netns vm2-sub200
ip link set veth-vm4 master br-10002
ip link set veth-vm4 up
ip netns exec vm2-sub200 ip link set eth0 up
ip netns exec vm2-sub200 ip addr add 10.1.2.12/24 dev eth0
ip netns exec vm2-sub200 ip route add default via 10.1.2.1
echo "=== node2 数据面配置完成 ==="
ip -br addr | grep -E 'br-|vni|veth'
SCRIPT
chmod +x /root/setup-vxlan.sh
bash /root/setup-vxlan.sh
5.2 FRR 配置
bash
cat > /etc/frr/frr.conf <<'EOF'
frr version 8.4.4
frr defaults traditional
no ipv6 forwarding
service integrated-vtysh-config
!
router bgp 65000
bgp router-id 172.20.2.10
!
neighbor 172.20.2.6 remote-as 65000
neighbor 172.20.2.6 description RR
neighbor 172.20.2.6 update-source enp0s16
neighbor 172.20.2.6 bfd
!
address-family l2vpn evpn
neighbor 172.20.2.6 activate
advertise-all-vni
vni 10001
rd 65000:10001
route-target import 65000:10001
route-target export 65000:10001
exit-vni
vni 10002
rd 65000:10002
route-target import 65000:10002
route-target export 65000:10002
exit-vni
exit-address-family
!
EOF
systemctl restart frr
6. 部署操作顺序
yaml
步骤 1: 三台均安装 FRR + 开启内核转发 + 配置 daemons
步骤 2: 配置 RR 的 frr.conf → 重启 frr
步骤 3: node1 执行 setup-vxlan.sh(数据面)
步骤 4: node1 配置 frr.conf → 重启 frr
步骤 5: node2 执行 setup-vxlan.sh(数据面)
步骤 6: node2 配置 frr.conf → 重启 frr
步骤 7: 等待 10 秒 BGP 收敛
步骤 8: 执行验证(第 7 章)
7. 验证与测试
7.1 BGP 邻居验证
bash
# 在 RR 上执行
vtysh -c "show bgp l2vpn evpn summary"
期望输出:
vbnet
Neighbor V AS MsgRcvd MsgSent Up/Down State/PfxRcd
172.20.2.9 4 65000 xxx xxx xx:xx:xx 4 ← node1
172.20.2.10 4 65000 xxx xxx xx:xx:xx 4 ← node2
7.2 EVPN 路由验证
bash
# 在 RR 上查看收到的所有 EVPN 路由
vtysh -c "show bgp l2vpn evpn route"
# 在计算节点上查看 VNI 状态
vtysh -c "show evpn vni"
# 查看 MAC 表
vtysh -c "show evpn mac vni 10001"
vtysh -c "show evpn mac vni 10002"
期望输出(node1 上):
csharp
VNI Type VxLAN IF # MACs # ARPs # Remote VTEPs Tenant VRF
10001 L2 vni10001 2 0 1 default
10002 L2 vni10002 2 0 1 default
7.3 FDB 转发表验证
bash
bridge fdb show | grep extern_learn
期望输出:
lua
<远端VM-MAC> dev vni10001 dst 172.20.2.10 self extern_learn
<远端VM-MAC> dev vni10002 dst 172.20.2.10 self extern_learn
7.4 同子网跨 TOR 连通性测试
bash
# 测试 1: VNI 10001 - node1 → node2
ip netns exec vm1-sub100 ping -c 3 10.1.1.12
# 测试 2: VNI 10002 - node1 → node2
ip netns exec vm1-sub200 ping -c 3 10.1.2.12
# 测试 3: 反向 - node2 → node1
ip netns exec vm2-sub100 ping -c 3 10.1.1.11
# 测试 4: 反向 - node2 → node1
ip netns exec vm2-sub200 ping -c 3 10.1.2.11
期望结果:全部 0% 丢包,延迟 < 2ms
7.5 VXLAN 封装验证
bash
# 在 node1 上抓包
tcpdump -i enp0s16 udp port 4789 -nn -c 5 &
ip netns exec vm1-sub100 ping -c 2 10.1.1.12
期望看到:
yaml
IP 172.20.2.9.xxxxx > 172.20.2.10.4789: VXLAN, vni 10001
IP 10.1.1.11 > 10.1.1.12: ICMP echo request
IP 172.20.2.10.xxxxx > 172.20.2.9.4789: VXLAN, vni 10001
IP 10.1.1.12 > 10.1.1.11: ICMP echo reply
8. 踩坑记录与注意事项
8.1 网卡名称
云环境网卡名通常为 enp0s16 等。update-source 必须指定实际网卡名。
验证方法:
bash
ip -br addr
8.2 FRR 命令差异
FRR 8.x 的正确命令是 advertise-all-vni(无 s),而非 advertise-all-vnis。
8.3 VNI 类型误识别
如果配置文件中存在残留的 vni <ID> 块(不在 address-family l2vpn evpn 下),FRR 会将其识别为 L3 VNI。
修复:
bash
vtysh -c "configure terminal" -c "no vni <ID>"
8.4 RD 格式
VNI 下的 RD 格式为 ASN:NN(如 65000:10001),不支持 auto。
8.5 RR 的 retain route-target all
RR 节点必须 配置 retain route-target all,否则 RR 会按本地 RT 过滤路由。
9. 清理脚本
如需重置环境,在 node1 和 node2 上执行:
bash
# 清理数据面
ip link del br-10001 2>/dev/null || true
ip link del br-10002 2>/dev/null || true
ip link del vni10001 2>/dev/null || true
ip link del vni10002 2>/dev/null || true
ip netns del vm1-sub100 2>/dev/null || true
ip netns del vm1-sub200 2>/dev/null || true
ip netns del vm2-sub100 2>/dev/null || true
ip netns del vm2-sub200 2>/dev/null || true
ip link del veth-vm1 2>/dev/null || true
ip link del veth-vm2 2>/dev/null || true
ip link del veth-vm3 2>/dev/null || true
ip link del veth-vm4 2>/dev/null || true
10. 附录:完整配置文件
10.1 RR - /etc/frr/frr.conf
ini
frr version 8.4.4
frr defaults traditional
no ipv6 forwarding
service integrated-vtysh-config
!
router bgp 65000
bgp router-id 172.20.2.6
neighbor 172.20.2.9 remote-as 65000
neighbor 172.20.2.9 description node1
neighbor 172.20.2.9 update-source enp0s16
neighbor 172.20.2.9 bfd
neighbor 172.20.2.10 remote-as 65000
neighbor 172.20.2.10 description node2
neighbor 172.20.2.10 update-source enp0s16
neighbor 172.20.2.10 bfd
!
address-family l2vpn evpn
neighbor 172.20.2.9 activate
neighbor 172.20.2.10 activate
neighbor 172.20.2.9 route-reflector-client
neighbor 172.20.2.10 route-reflector-client
retain route-target all
exit-address-family
!
bgp bestpath as-path multipath-relax
!
10.2 node1 - /etc/frr/frr.conf
ini
frr version 8.4.4
frr defaults traditional
no ipv6 forwarding
service integrated-vtysh-config
!
router bgp 65000
bgp router-id 172.20.2.9
neighbor 172.20.2.6 remote-as 65000
neighbor 172.20.2.6 description RR
neighbor 172.20.2.6 update-source enp0s16
neighbor 172.20.2.6 bfd
!
address-family l2vpn evpn
neighbor 172.20.2.6 activate
advertise-all-vni
vni 10001
rd 65000:10001
route-target import 65000:10001
route-target export 65000:10001
exit-vni
vni 10002
rd 65000:10002
route-target import 65000:10002
route-target export 65000:10002
exit-vni
exit-address-family
!
10.3 node2 - /etc/frr/frr.conf
ini
frr version 8.4.4
frr defaults traditional
no ipv6 forwarding
service integrated-vtysh-config
!
router bgp 65000
bgp router-id 172.20.2.10
neighbor 172.20.2.6 remote-as 65000
neighbor 172.20.2.6 description RR
neighbor 172.20.2.6 update-source enp0s16
neighbor 172.20.2.6 bfd
!
address-family l2vpn evpn
neighbor 172.20.2.6 activate
advertise-all-vni
vni 10001
rd 65000:10001
route-target import 65000:10001
route-target export 65000:10001
exit-vni
vni 10002
rd 65000:10002
route-target import 65000:10002
route-target export 65000:10002
exit-vni
exit-address-family
!
11. 部署验证结果
实际测试结果
| 测试项 | 结果 |
|---|---|
| BGP 邻居 (RR ↔ node1) | ✅ Established,收到 4 条路由 |
| BGP 邻居 (RR ↔ node2) | ✅ Established,收到 4 条路由 |
| EVPN Type 2 路由 | ✅ 4 条 MAC 路由正常同步 |
| EVPN Type 3 路由 | ✅ 4 条 Inclusive Multicast 路由 |
| VNI 10001 连通性 | ✅ 0% 丢包,平均延迟 0.77ms |
| VNI 10002 连通性 | ✅ 0% 丢包,平均延迟 0.64ms |