引言: 为什么需要VxLAN?
在传统数据中心网络中,通常使用VLAN技术实现二层网络隔离。但VLAN存在一个根本性限制:12位的VLAN ID字段最多只能支持4096个隔离网络(实际可用4094个)。这个数字在早期的企业网络中或许足够,但在如今云数据中心动辄成千上万个租户的环境下,这个限制已成为扩展性的瓶颈。VxLAN使用24位的VNI替代了VLAN ID,可支持约1600万个隔离网络,从而彻底解决了规模问题。
| 特性 |
传统VLAN |
VxLAN |
| 标识符长度 |
12位 |
24位 |
| 最大网络数 |
4094 |
16777214 |
| 封装方式 |
802.1Q标签 |
UDP over IP |
| 跨三层能力 |
有限(需协议) |
原生支持 |
| MTU要求 |
标准1500字节 |
需额外50字节开销 |
| 典型应用场景 |
企业园区网 |
云数据中心,SDN |
一、VxLAN基础架构与核心概念
1.1 VxLAN封装格式
VxLAN的封装方式可以形象地理解为寄送一个已包装的包裹:
- 原始以太网帧:你要寄送的实际物品(应用数据)
- VxLAN头部:新包裹内的运输清单(VNI等信息)
- 外层UDP头部:新包裹的快递单(端口信息)
- 外层IP头部:新包裹的收发货地址(隧道端点地址)
- 外层以太网头部:新包裹的物流卡车(物理网络传输)
完整的VxLAN封装结构如下:
┌─────────────────────────────────────────────────────────────────────┐
│ 原始以太网帧 (Payload) │
│ ┌────────────┬────────────┬────────────┬─────────────────────────┐ │
│ │ 目标MAC(6) │ 源MAC(6) │ EtherType │ Payload │ │
│ │ │ │ (2) │ (46-1500) │ │
│ └────────────┴────────────┴────────────┴─────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│
▼ 添加VxLAN封装
┌─────────────────────────────────────────────────────────────────────┐
│ VxLAN封装后的数据包 │
├────────────────────┬────────────────────┬───────────────────────────┤
| 外层以太网头部 | 外层IP头部 | 外层UDP头部 |
│ ┌──────┬──────┐ │ ┌────┬─────┬───┐ │ ┌──────┬──────┬─────────┐ │
│ │目标MAC│源MAC │ │ │版本│服务类型│...│ │源端口│目标端口│长度和校验│ │
│ │ (6B) │ (6B) │ │ │ (4)│ (1B) │ │ │ (2B) │ (2B) │ 和(4B) │ │
│ └──────┴──────┘ │ └────┴─────┴───┘ │ └──────┴──────┴─────────┘ │
├────────────────────┴────────────────────┴───────────────────────────┤
│ VxLAN头部 (8字节) │
│ ┌────────────┬──────────────────┐ │
│ │ 标志(8bit) │ 保留(24bit) │ │
│ ├────────────┼──────────────────┤ │
│ │ VNI (24bit) │ │
│ │ │ 保留(8bit) │ │
│ └────────────┴──────────────────┘ │
├─────────────────────────────────────────────────────────────────────┤
│ 原始以太网帧 (完整封装) │
│ ┌────────────┬────────────┬────────────┬─────────────────────────┐ │
│ │ 目标MAC(6) │ 源MAC(6) │ EtherType │ Payload │ │
│ │ │ │ (2) │ (46-1500) │ │
│ └────────────┴────────────┴────────────┴─────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
1.2 VxLAN核心组件详解
1.2.1 VTEP (VxLAN Tunnel Endpoint)
VTEP是VxLAN网络的边缘设备,负责执行VxLAN的封装和解封装。可以将其想象成国际邮件转运中心:
- 出口VTEP:当本地虚拟机要发送数据到远程网络时,VTEP将原始以太网帧封装进UDP/IP数据包。
- 入口VTEP:收到VxLAN数据包后,VTEP解封装,提取原始以太网帧并传递给目标虚拟机。
每个VTEP有两个重要接口:
- 本地连接接口:连接本地虚拟机/容器的桥接或路由接口。
- 隧道接口:用于VxLAN封装的虚拟接口,绑定到物理网络接口。
1.2.2 VNI (Virtual Network Identifier)
VNI是24位的标识符,类似于公寓大楼的单元号:
- 同一VNI内的设备处于同一个二层广播域。
- 不同VNI之间默认隔离,除非通过三层网关连接。
- VNI与VLAN ID可以映射,但不是必须的。
1.2.3 多播组 (Multicast Group)
在初始的VxLAN实现中,多播用于VTEP发现和BUM流量传输。可以把多播组想象成会议电话系统:
- 每个VNI映射到一个多播组。
- 当VTEP需要发送广播或未知单播时,它发送到对应的多播组。
- 同一多播组的所有VTEP都能收到数据。
然而,在实际的大规模部署中,多播存在扩展性问题,因此现代实现更常用头端复制或控制平面学习(如EVPN)。
二、VxLAN工作原理: 封装、传输与解封装
2.1 完整的数据传输流程
场景:虚拟机VM1 (MAC: 00:11:22:33:44:55, IP: 10.1.1.10) 想要与虚拟机VM2 (MAC: aa:bb:cc:dd:ee:ff, IP: 10.1.1.20) 通信,它们位于不同物理服务器但相同VNI (100) 中。

2.2 关键过程详解
2.2.1 MAC地址学习过程
VxLAN中的MAC学习有两种主要方式:
- 数据平面学习(传统方式)
- 通过监听数据包的源MAC地址和源VTEP IP。
- 类似于传统交换机的MAC地址表学习。
- 简单但可能产生大量BUM流量。
- 控制平面学习(现代方式,如EVPN)
- 使用BGP EVPN传递MAC/IP信息。
- 提前建立转发表,避免泛洪。
- 支持更复杂的策略和优化。
2.2.2 隧道建立机制
VxLAN隧道是动态建立的,没有明确的隧道建立协议。隧道存在与否取决于:
- VTEP是否配置了相同的VNI。
- 底层IP网络是否可达。
- 是否有转发该VNI流量的需要。
这就像一个按需拨号连接——只有需要通信时,隧道逻辑才被激活。
三、Linux内核中的VxLAN实现机制
Linux内核为Linux网络虚拟化提供了完整的VxLAN支持,其实现涉及多个关键数据结构。
3.1 核心数据结构分析
/* 核心数据结构: vxlan_dev - 表示一个VxLAN网络设备 */
struct vxlan_dev {
struct hlist_node hlist; // 哈希链表节点
struct list_head next; // 设备链表
struct vxlan_rdst *default_dst; // 默认远程目的地
struct net_device *dev; // 关联的网络设备
struct vxlan_net *vn; // 指向vxlan_net
/* 配置参数 */
__be16 dst_port; // VxLAN目标端口 (默认4789)
__be16 dst_port_min; // 端口范围最小值
__be16 dst_port_max; // 端口范围最大值
u32 flags; // 设备标志位
/* 转发表相关 */
struct hlist_head fdb_head[FDB_HASH_SIZE]; // FDB哈希表
struct work_struct fdb_work; // FDB维护工作队列
unsigned long age_timer_value; // 老化计时器值
/* 多播相关 */
union vxlan_addr mcast_grp; // 多播组地址
struct socket __rcu *sock4; // IPv4套接字
#if IS_ENABLED(CONFIG_IPV6)
struct socket __rcu *sock6; // IPv6套接字
#endif
/* 统计信息 */
struct vxlan_stats stats; // 统计计数器
};
/* 远程目的地结构: 表示一个远程VTEP */
struct vxlan_rdst {
union vxlan_addr remote_ip; // 远程VTEP IP地址
__be16 remote_port; // 远程端口
u8 offloaded:1; // 是否卸载到硬件
struct list_head list; // 链表
struct rcu_head rcu; // RCU回调头
};
/* FDB条目: 转发表中的MAC地址条目 */
struct vxlan_fdb {
struct hlist_node hlist; // 哈希链表节点
struct rcu_head rcu_head; // RCU回调头
struct list_head remotes; // 远程目的地列表
unsigned long used; // 最后使用时间
unsigned long updated; // 最后更新时间
u8 eth_addr[ETH_ALEN]; // MAC地址
__be32 vni; // VNI
u16 state; // 状态标志
/* 标志位 */
u8 flags; // FDB标志
u8 nh_flags; // 下一跳标志
};

3.2 关键函数流程分析
3.2.1 数据包接收流程 (vxlan_rcv)
当内核收到VxLAN数据包时的简化处理流程:
static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, __be32 vni)
{
struct vxlan_dev *vxlan;
struct vxlan_fdb *fdb;
struct ethhdr *eth;
// 1. 查找对应的VxLAN设备
vxlan = vxlan_vni_find(vs, vni);
if (!vxlan) {
kfree_skb(skb);
return;
}
// 2. 移除外层封装
skb = vxlan_udp_decap(skb);
if (!skb)
return;
// 3. 获取内部以太网头
eth = eth_hdr(skb);
// 4. 查找FDB表
fdb = vxlan_find_mac(vxlan, eth->h_source, vni);
// 5. 更新或创建FDB条目
if (fdb) {
// 更新现有条目
vxlan_fdb_update(vxlan, eth->h_source,
&remote_ip, NUD_REACHABLE,
flags, skb->dev->ifindex);
} else {
// 创建新条目
vxlan_fdb_create(vxlan, eth->h_source,
&remote_ip, NUD_NOARP,
flags, skb->dev->ifindex);
}
// 6. 转发到上层网络栈
netif_rx(skb);
}
3.2.2 数据包发送流程 (vxlan_xmit)
当从VxLAN接口发送数据包时的简化处理:
static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
struct vxlan_fdb *fdb;
struct vxlan_rdst *rdst;
// 1. 获取目标MAC地址
struct ethhdr *eth = eth_hdr(skb);
u8 *dest_mac = eth->h_dest;
// 2. 查找FDB表
fdb = vxlan_find_mac(vxlan, dest_mac, vxlan->cfg.vni);
// 3. 处理不同类型的流量
if (is_multicast_ether_addr(dest_mac)) {
// 组播处理
return vxlan_xmit_mcast(skb, dev);
} else if (fdb && !list_empty(&fdb->remotes)) {
// 已知单播
rdst = first_remote_rcu(fdb);
return vxlan_xmit_one(skb, dev, vni, rdst, false);
} else {
// 未知单播或广播
return vxlan_xmit_novel(skb, dev);
}
}

四、实际部署与配置示例
4.1 使用iproute2创建VxLAN接口
创建一个点对点VxLAN隧道的示例:
# 1. 创建VxLAN接口
# 语法: ip link add <name> type vxlan id <vni> dev <物理设备> dstport <端口>
sudo ip link add vxlan100 type vxlan \
id 100 \
dev eth0 \
dstport 4789 \
local 192.168.1.10 \
remote 192.168.1.20
# 2. 启动VxLAN接口
sudo ip link set vxlan100 up
# 3. 分配IP地址
sudo ip addr add 10.1.1.1/24 dev vxlan100
# 4. 查看VxLAN接口详细信息
sudo ip -d link show vxlan100
# 5. 查看FDB表(MAC转发表)
sudo bridge fdb show dev vxlan100
# 6. 添加静态FDB条目
sudo bridge fdb append 00:11:22:33:44:55 dev vxlan100 dst 192.168.1.30
4.2 完整的两节点VxLAN配置示例
节点A配置 (192.168.1.10):
#!/bin/bash
# 节点A配置脚本
# 创建VxLAN接口
ip link add vxlan100 type vxlan \
id 100 \
dev eth0 \
dstport 4789 \
local 192.168.1.10 \
remote 192.168.1.20
# 创建网桥并将VxLAN接口加入
ip link add name br-vxlan type bridge
ip link set br-vxlan up
ip link set vxlan100 master br-vxlan
# 配置IP地址
ip addr add 10.1.1.10/24 dev br-vxlan
# 启动所有接口
ip link set vxlan100 up
节点B配置 (192.168.1.20):
#!/bin/bash
# 节点B配置脚本
# 创建VxLAN接口
ip link add vxlan100 type vxlan \
id 100 \
dev eth0 \
dstport 4789 \
local 192.168.1.20 \
remote 192.168.1.10
# 创建网桥
ip link add name br-vxlan type bridge
ip link set br-vxlan up
ip link set vxlan100 master br-vxlan
# 配置IP地址
ip addr add 10.1.1.20/24 dev br-vxlan
# 启动接口
ip link set vxlan100 up
4.3 使用systemd-networkd的配置方法
对于使用systemd的现代Linux发行版,可以使用networkd配置VxLAN:
/etc/systemd/network/10-vxlan100.netdev:
[NetDev]
Name=vxlan100
Kind=vxlan
[VXLAN]
Id=100
Local=192.168.1.10
Remote=192.168.1.20
Port=4789
/etc/systemd/network/20-br-vxlan.netdev:
[NetDev]
Name=br-vxlan
Kind=bridge
/etc/systemd/network/30-br-vxlan.network:
[Match]
Name=br-vxlan
[Network]
Address=10.1.1.10/24
五、高级特性与优化
5.1 多播与头端复制模式对比
| 特性 |
多播模式 |
头端复制模式 |
| BUM流量处理 |
发送到多播组 |
复制到所有已知单播VTEP |
| 控制平面复杂度 |
简单 |
需要维护VTEP列表 |
| 底层网络要求 |
需要多播支持 |
只需单播可达 |
| 扩展性 |
受多播范围限制 |
受VTEP数量限制 |
| 资源消耗 |
网络资源优化 |
源VTEP CPU消耗较高 |
5.2 VxLAN与硬件卸载
现代网卡(特别是SmartNIC)支持VxLAN的硬件卸载,可以显著提升性能:
# 检查VxLAN卸载能力
ethtool -k eth0 | grep vxlan
# 启用VxLAN卸载
ethtool -K eth0 tx-udp_tnl-segmentation on
ethtool -K eth0 rx-udp_tnl-segmentation on
# 检查卸载状态
ethtool -k eth0 | grep tnl
5.3 EVPN-VxLAN控制平面
EVPN为VxLAN提供了控制平面,解决了传统数据平面学习的限制,是实现大规模云原生网络的关键技术之一。
┌─────────────────────────────────────────────────────┐
│ EVPN-VxLAN架构 │
├──────────────┬──────────────┬───────────────┤
│ 数据平面 │ 控制平面 │ 管理平面 │
├──────────────┼──────────────┼───────────────┤
│ VxLAN封装 │ BGP EVPN │ 配置与管理 │
│ 与转发 │ 路由分发 │ 系统 │
├──────────────┼──────────────┼───────────────┤
│ • 基于UDP的 │ • 传播MAC/IP │ • 集中式控制器│
│ 封装 │ 可达性信息 │ • 自动化配置 │
│ • 硬件卸载 │ • 水平分割 │ • 监控与故障 │
│ • 负载均衡 │ • 多归属支持 │ 排除 │
└──────────────┴──────────────┴───────────────┘
六、调试与故障排除
6.1 常用诊断命令
# 1. 查看网络接口详细信息
ip -d link show vxlan100
# 2. 查看路由表
ip route show
ip -6 route show
# 3. 查看FDB表(MAC地址表)
bridge fdb show dev vxlan100
# 4. 查看ARP/NDP表
ip neigh show dev vxlan100
# 5. 抓包分析(指定VxLAN UDP端口4789)
sudo tcpdump -i eth0 udp port 4789 -vvv
# 6. 检查内核日志
dmesg | grep -i vxlan
journalctl -k | grep -i vxlan
# 7. 查看网络接口统计信息
ip -s link show vxlan100
# 8. 检查连接性(指定源接口)
ping -I br-vxlan 10.1.1.20
6.2 常见问题排查流程

6.3 高级调试技巧
6.3.1 使用bpftrace进行内核跟踪
# 安装bpftrace
sudo apt-get install bpftrace
# 跟踪VxLAN数据包接收
sudo bpftrace -e 'kprobe:vxlan_rcv {
printf("VxLAN packet received: dev=%s len=%d\n",
str(arg1->name), arg2->len);
}
kretprobe:vxlan_rcv {
printf("VxLAN processing completed: ret=%d\n", retval);
}'
# 跟踪FDB更新事件
sudo bpftrace -e 'kprobe:vxlan_fdb_update {
$fdb = (struct vxlan_fdb *)arg1;
printf("FDB update: MAC=%02x:%02x:%02x:%02x:%02x:%02x\n",
$fdb->eth_addr[0], $fdb->eth_addr[1], $fdb->eth_addr[2],
$fdb->eth_addr[3], $fdb->eth_addr[4], $fdb->eth_addr[5]);
}'
6.3.2 使用dropwatch监控丢包
# 安装dropwatch
sudo apt-get install dropwatch
# 启动dropwatch(交互式模式)
sudo dropwatch -l kas
# 在交互提示符下输入 `start` 开始监控
七、VxLAN性能优化实践
7.1 MTU与巨帧配置
VxLAN封装增加了50字节开销,需要相应调整MTU以避免分片:
# 计算合适的MTU
# 底层网络MTU: 1500
# VxLAN开销: 50字节
# 推荐VxLAN接口MTU: 1450
# 设置MTU
ip link set vxlan100 mtu 1450
# 如果底层支持巨帧 (Jumbo Frame)
# 底层MTU: 9000
# VxLAN接口MTU: 8950
ip link set eth0 mtu 9000
ip link set vxlan100 mtu 8950
对于高性能场景,配置RSS可以充分利用多核CPU处理网络流量:
# 检查当前RSS配置
ethtool -n eth0 rx-flow-hash udp4
# 配置UDP端口4789使用四元组(源/目IP,源/目端口)进行RSS哈希
ethtool -N eth0 rx-flow-hash udp4 sdfn
# 查看及设置RSS队列数量
ethtool -l eth0
ethtool -L eth0 combined 8
7.3 中断亲和性优化
将网络中断绑定到特定CPU核心,可以减少缓存失效,提升处理效率:
# 查看中断分配
cat /proc/interrupts | grep eth0
# 设置中断亲和性(例如将中断123绑定到CPU0)
echo 1 > /proc/irq/123/smp_affinity
# 或者使用irqbalance服务自动优化
systemctl enable irqbalance
systemctl start irqbalance
八、VxLAN与其他技术的结合
8.1 VxLAN + Kubernetes(CNI插件)
现代Kubernetes网络插件大量使用VxLAN来实现Pod网络,例如Calico:
# Calico使用VxLAN的配置示例
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: default-ipv4-ippool
spec:
cidr: 10.244.0.0/16
vxlanMode: Always # 启用VxLAN模式
natOutgoing: true
---
apiVersion: projectcalico.org/v3
kind: FelixConfiguration
metadata:
name: default
spec:
vxlanEnabled: true
vxlanPort: 4789
vxlanVNI: 4096
8.2 VxLAN + SR-IOV(硬件加速)
结合SR-IOV实现高性能容器网络,为对网络性能有极致要求的应用提供解决方案:
┌─────────────────────────────────────────────┐
│ VxLAN + SR-IOV架构 │
├──────────────┬──────────────┬──────────────┤
│ 容器/Pod │ 主机网络 │ 物理网络 │
├──────────────┼──────────────┼──────────────┤
│ SR-IOV VF │ VxLAN隧道 │ 交换机/路由器 │
│ 直通给容器 │ 在PF上终结 │ │
├──────────────┼──────────────┼──────────────┤
│ • 接近线速 │ • 网络策略 │ • 物理隔离 │
│ 性能 │ 集中实施 │ • 服务质量 │
│ • 低延迟 │ • 可观测性 │ 保障 │
│ • 低CPU消耗 │ • 易于管理 │ │
└──────────────┴──────────────┴──────────────┘
九、总结
9.1 VxLAN的核心价值总结
- 极致扩展性:24位VNI支持千万级隔离网络,满足大规模云数据中心需求。
- 无缝三层扩展:在现有IP网络基础设施上透明地扩展二层网络,打破物理位置限制。
- 天然的多租户支持:为云环境提供逻辑隔离,是构建多租户网络的基础。
- 部署灵活性:支持多播、头端复制、EVPN等多种控制平面,适应不同场景。
- 广泛的生态支持:作为IETF标准(RFC 7348),得到了主流厂商、Linux内核及众多云原生网络方案(如Kubernetes CNI)的良好支持。
9.2 传统VLAN vs VxLAN全面对比
| 维度 |
传统VLAN (802.1Q) |
VxLAN (RFC 7348) |
| 扩展性 |
4094个网络 |
约1600万个网络 |
| 网络范围 |
通常限于单个数据中心 |
跨数据中心、跨云 |
| 封装开销 |
4字节 |
50字节 |
| 技术要求 |
二层网络知识 |
二层+三层网络知识 |
| 配置复杂度 |
相对简单 |
更复杂,但自动化工具多 |
| 硬件支持 |
普遍支持 |
现代硬件支持良好 |
| 适用场景 |
传统企业网络 |
云数据中心、SDN、虚拟化 |
| 演进方向 |
维持现状 |
持续演进,与SDN、云原生深度融合 |