主题
实验 13:隧道原理
实验 9 结尾提到一个数字:VLAN ID 只有 12 位,最多 4094 个。
这一章从这个限制出发,讲清楚 Overlay 网络为什么存在、隧道到底做了什么。下一章动手把它建起来。
VLAN 撑不住的三件事
一、4094 个不够
一个公有云上有几万个租户,每个租户至少要一个隔离的网络。4094 个 VLAN 一个月就分完了。
二、VLAN 是二层的,跨不过路由器
VLAN 标签在以太网帧里。路由器转发时会重新构造以太网头,标签直接没了。
所以同一个 VLAN 必须在同一个二层域内。数据中心里这意味着:要让两台机器上的虚拟机在同一个 VLAN 里,这两台机器之间必须是二层可达的。 于是整个数据中心得是一个大二层 —— 广播域巨大、生成树收敛缓慢、故障域没边界。
三、物理交换机也要配
每加一个 VLAN,路径上所有物理交换机的 trunk 口都得放行它。虚拟机迁移到另一个机架,可能整条链路的配置都要动。虚拟网络的变更被绑死在物理网络的配置上。
Overlay 的思路:套一层
text
想要的效果
┌──────────────────────────────────────────────┐
│ h1 和 h2 觉得自己接在同一台交换机上 │
│ h1 ──────── 虚拟的二层 ──────── h2 │
└──────────────────────────────────────────────┘
实际的物理情况
┌──────────────────────────────────────────────┐
│ h1 ── 宿主机A ══ 三层网络(路由器若干)══ 宿主机B ── h2 │
└──────────────────────────────────────────────┘
做法:把 h1 发出的整个以太网帧塞进一个 UDP 包,
通过三层网络送到宿主机B,再拆出来交给 h2。1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
这就是隧道:把一个协议的数据包整个当成载荷,塞进另一个协议的包里传输。
于是:
- 租户数量由隧道标识决定,不再受 12 位限制
- 不要求二层可达,只要三层能通就行(IP 路由已经解决了这个问题)
- 物理网络不用感知虚拟网络,它只看到普通的 UDP 流量
underlay 和 overlay
- underlay(承载网):真实的物理网络,用 IP 路由。上面跑的是隧道包
- overlay(叠加网):虚拟机看到的那个网络。它"跑在" underlay 之上
两套网络的地址空间完全独立。overlay 里用 192.168.10.0/24 和 underlay 用什么地址毫无关系,重叠也没问题。
VXLAN 的封装格式
text
原始帧(h1 发出来的,也叫内层帧)
┌──────────┬──────────┬─────────────────────────┐
│ 内层目MAC │ 内层源MAC │ 内层 IP 包(h1→h2) │
└──────────┴──────────┴─────────────────────────┘
│
│ ovs1 加上四层封装
▼
┌──────────┬─────────┬─────────┬────────┬──────────────────┐
│ 外层以太头 │ 外层 IP │ 外层 UDP │ VXLAN │ 原始帧(整个) │
│ 14 字节 │ 20 字节 │ 8 字节 │ 8 字节 │ │
└──────────┴─────────┴─────────┴───┬────┴──────────────────┘
↑ ↑ │
underlay 地址 目的端口 4789 │
10.0.0.1 源端口是哈希值 │
→ 10.0.0.2 │
┌───────────────┴────────────────┐
│ flags │ 保留 │ VNI │ 保留 │
│ 1字节 │ 3字节│ 3字节 │ 1字节 │
│ │ │ 24 位 │ │
└────────────────────────────────┘
总开销 = 14 + 20 + 8 + 8 = 50 字节
VNI 24 位 → 1677 万个隧道标识1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
VNI 是 24 位,一千六百多万个。这是 VXLAN 取代 VLAN 的直接理由。
外层 UDP 源端口是个哈希值
这个设计很巧妙。外层 UDP 的目的端口固定 4789(标识"这是 VXLAN"),但源端口是根据内层报文算出来的哈希。
看实验里抓到的真实包:
text
10.0.0.1.32922 > 10.0.0.2.4789: VXLAN, vni 100 ← 源端口 32922
10.0.0.1.48601 > 10.0.0.2.4789: VXLAN, vni 100 ← 源端口 486011
2
2
两个不同的内层流,外层源端口不同。目的是让 underlay 的路由器能做 ECMP —— 路由器按五元组哈希选路,源端口变化就意味着不同的内层流会走不同的物理路径,多条链路的带宽才用得上。
如果源端口固定,所有隧道流量都会挤在同一条物理路径上。
四种隧道类型
OVS 支持的隧道类型(Open_vSwitch.iface_types 里能看到全部):
| 类型 | 封装 | 标识位数 | 标准端口 | 说明 |
|---|---|---|---|---|
vxlan | UDP | 24 位 VNI | 4789 | 最通用,硬件支持最广 |
geneve | UDP | 24 位 VNI | 6081 | 支持可变长度的元数据选项,OVN 的默认选择 |
gre | IP 协议 47 | 32 位 key | —— | 不走 UDP,做不了 ECMP |
stt | 伪装成 TCP | 64 位 | —— | 能利用网卡的 TCP 分段卸载,性能好但非标准 |
在 OVS 里切换类型只需要改一个字段:
bash
ovs-vsctl set Interface vxlan0 type=geneve1
实验里试过,改完立刻就通,datapath 里换成了 genev_sys_6081。
怎么选
默认用 VXLAN。 它是事实标准,物理交换机和网卡的硬件卸载支持最好。
用 Geneve 的理由:需要在隧道头里携带自定义元数据。OVN 就靠这个传递逻辑端口 ID 等信息,这是 VXLAN 的固定头做不到的。
避免 GRE:它不走 UDP,underlay 的路由器无法用端口号做 ECMP,多路径带宽用不上。
三个必须注意的坑
一、MTU
封装要吃掉 50 字节。underlay MTU 是 1500 的话,overlay 的可用 MTU 只有 1450。
text
underlay MTU 1500
├── 外层封装 50 字节 ──┼────── overlay 可用 1450 ──────┤1
2
2
虚拟机还按 1500 发包的话,封装后变成 1550,超过 underlay MTU:
- 如果外层 IP 设了 DF 位(OVS 默认设),包被直接丢弃
- 没设 DF 就会分片,性能大幅下降
症状很有特点:ping 通,小包正常,大包或者 TCP 传大文件就卡死。 这是隧道环境最经典的故障。
三种解法:
- underlay 用巨帧(推荐)。物理网络 MTU 设成 9000,overlay 保持 1500
- 调小 overlay MTU。虚拟机网卡设成 1450
- 靠 TCP MSS clamping。只能救 TCP,UDP 救不了
二、underlay 必须先通
隧道建立在三层可达的基础上。配隧道之前先确认 underlay 能 ping 通:
bash
ping <对端的 underlay 地址>1
这个顺序不能反。underlay 不通,隧道端口会显示成 up,但一个包都过不去。
三、两端 VNI 必须一致
VNI 不匹配时,包能到对面,但会被丢弃(对面找不到对应 VNI 的隧道端口)。现象是"抓包能看到,但业务不通" —— 排查时很容易忽略。
隧道端口在 OVS 里的样子
隧道端口就是一个 type=vxlan 的 Interface:
bash
ovs-vsctl add-port br0 vxlan0 \
-- set Interface vxlan0 type=vxlan \
options:remote_ip=10.0.0.2 options:key=1001
2
3
2
3
常用的 options:
| 选项 | 含义 |
|---|---|
remote_ip | 对端的 underlay 地址 |
local_ip | 本端 underlay 地址(多网卡时指定用哪个) |
key | VNI。写 flow 表示由流表动态决定 |
dst_port | 改默认端口 |
df_default | 是否设 DF 位,默认 true |
tos / ttl | 外层 IP 的字段,写 inherit 表示继承内层 |
key=flow 是多租户的关键
options:key=100 是固定 VNI。写成 options:key=flow 则由流表的 set_field:...->tun_id 动作决定 —— 一个隧道端口就能承载所有租户。
实验 15 会用到。
建好之后,它在网桥里就是个普通端口。 MAC 学习、VLAN、流表全都照常工作,转发逻辑一行都不用改 —— 这是 OVS 隧道设计最优雅的地方。
小结
- VLAN 的三个限制:只有 4094 个、跨不过路由器、物理网络要跟着配
- Overlay 的做法是把整个以太网帧塞进 UDP 包,通过三层网络传输
- underlay 和 overlay 的地址空间完全独立
- VXLAN 封装开销 50 字节,VNI 24 位(1677 万)
- 外层 UDP 源端口是内层报文的哈希,为了让 underlay 能做 ECMP
- 默认选 VXLAN;需要携带元数据用 Geneve;避免 GRE(做不了 ECMP)
- 三个坑:MTU(小包通大包不通)、underlay 必须先通、两端 VNI 必须一致
- 隧道端口就是
type=vxlan的 Interface,建好后和普通端口一样用
下一章:实验 14:打通 VXLAN,动手建一条隧道并抓包验证封装。