VXLAN-EVPN 多租户私有网络测试文档

20 阅读11分钟

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 测试拓扑

                    ┌──────────────────┐
                    │   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 1000110.1.1.0/24 (子网1)
             VNI 1000210.1.2.0/24 (子网2)

1.3 节点信息

节点角色内网 IP外网 IP网卡名
RRRoute Reflector172.20.2.6112.51.122.186enp0s16
node1计算节点172.20.2.9112.51.122.182enp0s16
node2计算节点172.20.2.10112.51.122.180enp0s16

1.4 Overlay 地址规划

VNIVLAN子网用途node1 VMnode2 VM
10001-10.1.1.0/24租户子网110.1.1.1110.1.1.12
10002-10.1.2.0/24租户子网210.1.2.1110.1.2.12

2. 环境准备

2.1 云主机要求

  • 3 台 VM 位于同一内网子网(Underlay 互通)
  • 安全组放行以下端口:
协议端口用途
TCP179BGP 邻居建立
UDP4789VXLAN 隧道数据
UDP3784BFD 快速故障检测
ICMP-调试连通性

2.2 基础软件安装(三台均执行)

# 安装 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 守护进程(三台均执行)

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 配置

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 allRR 保留所有 RT 路由,不做本地 RT 过滤
bgp bestpath as-path multipath-relax允许 AS-Path 长度不同的路由做 ECMP

4. node1 配置(计算节点)

4.1 数据面脚本

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 配置

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 数据面脚本

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 配置

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. 部署操作顺序

步骤 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 邻居验证

# 在 RR 上执行
vtysh -c "show bgp l2vpn evpn summary"

期望输出

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 路由验证

# 在 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 上):

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 转发表验证

bridge fdb show | grep extern_learn

期望输出

<远端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 连通性测试

# 测试 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 封装验证

# 在 node1 上抓包
tcpdump -i enp0s16 udp port 4789 -nn -c 5 &
ip netns exec vm1-sub100 ping -c 2 10.1.1.12

期望看到

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 必须指定实际网卡名。

验证方法

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。

修复

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 上执行:

# 清理数据面
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

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

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

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