6. Tunnel 在哪里终止:VTEP 的落点
封包解包这件事,在哪里做?由谁做?
VTEP 可以放在宿主机的操作系统内核里,用软件完成封包解包。可以放在机架顶部的物理交换机上,用专用 ASIC 芯片完成。也可以放在服务器的网卡上,一种叫 SmartNIC 或 DPU 的专用硬件。每种选择都有自己的代价,每种代价都指向不同的架构方向。
6.1 软件 VTEP:在内核里做封包解包
最直接的思路是让宿主机自己来做。
宿主机的操作系统内核本来就管着整个网络协议栈,TCP/IP 的收发、路由表的查找、网卡驱动的调度。在内核里加一个 VxLAN 模块,让它负责封包解包,逻辑上是最简单的。不需要额外的硬件,不需要改动物理网络,只需要在每台宿主机上部署一段软件。
Linux 内核从 3.7 版本(2012 年)开始原生支持 VxLAN。管理员可以直接创建一个 VxLAN 类型的网络接口,指定 VNI 和远端 VTEP 的 IP 地址,内核就会自动完成封装和解封装。VM 发出的帧到达宿主机的虚拟交换机后,被内核的 VxLAN 模块拦截,套上外层头部,变成一个普通的 UDP/IP 包,从物理网卡发出去。对端宿主机收到这个 UDP 包后,内核的 VxLAN 模块识别出目的端口是 4789,剥掉外层头部,把原始帧交给对应的 VM。
在实际的云环境中,软件 VTEP 通常不是直接用 Linux 内核的原生 VxLAN 模块,而是通过 OVS 来实现。OVS 提供了更丰富的流量控制能力,它可以根据流表规则决定哪些包需要 VxLAN 封装、封装到哪个远端 VTEP、使用哪个 VNI。这种灵活性是原生内核模块做不到的。
OVS 是什么?
OVS(Open vSwitch)是一个运行在宿主机上的软件虚拟交换机。它在内核态完成数据包的快速转发,在用户态提供管理接口。OVS 支持 VxLAN 封装,同时提供流表匹配、QoS 限速、端口镜像等高级功能。在云计算环境中,OVS 通常替代 Linux 原生的 bridge,作为 VM 流量的第一跳转发节点。SDN 控制器通过 OpenFlow 协议向 OVS 下发流表规则,控制每个包的转发行为。
软件 VTEP 的优势很明显。部署灵活,不依赖特定的硬件型号,任何一台装了 Linux 的服务器都能跑。升级方便,改软件比换硬件容易得多,一个内核模块的升级可以在几分钟内完成,而更换一台物理交换机可能需要几个小时的停机窗口。功能迭代快,新的封装协议、新的转发策略、新的安全功能,都可以通过软件更新来支持,不需要等硬件厂商发布新固件。
代价也很明显:CPU。
每个包的封装和解封装都消耗 CPU 周期。封装时,CPU 需要查转发表(MAC → 远端 VTEP IP 的映射)、构造 50 字节的外层头部(以太网头 + IP 头 + UDP 头 + VxLAN 头)、计算 UDP 源端口的哈希值、计算外层 IP 头的校验和。解封装时,CPU 需要解析外层头部、校验 VNI、剥掉外层头部、把原始帧交给正确的虚拟网卡。每个包都要走一遍这个流程。
当一台宿主机上只跑几台 VM,网络流量不大时,这个开销微不足道。但云计算的密度在持续增长。2010 年前后,一台宿主机上可能跑 5-10 台 VM,每秒处理几十万个包,VxLAN 封包解包占用的 CPU 不到 5%。到了 2015 年,单台宿主机上的 VM 数量增长到 20-30 台,每秒处理的包数量达到百万级,封包解包的 CPU 开销上升到 10%-15%。再往后,容器化让单台宿主机上的工作负载数量进一步爆炸,一台机器上可能跑几十个 Pod,高峰时每秒需要处理 200 万甚至更多的包,VxLAN 的 CPU 开销可能占到 15%-20%。
如果你是 2014 年某家云厂商的网络架构师,面对这条增长曲线,你会怎么选?继续用软件扛,还是把封包解包从 CPU 上移走,交给专用硬件?这个问题的答案,推动了整个行业从软件到硬件的功能下移。
这些 CPU 本来可以卖给租户跑业务,现在被网络虚拟化吃掉了。对云厂商来说,这是真金白银的损失。一台 128 核的服务器,如果 20% 的 CPU 被网络虚拟化占用,就相当于 25 个核心无法出售。乘以数据中心里几万台服务器,这是一个巨大的数字。
软件 VTEP 不是一个"错误的方案"。在云计算的早期阶段,2008 到 2015 年左右,它是完全合理的选择。那时候单台宿主机的 VM 密度不高,CPU 开销在可控范围内,而软件方案的灵活性和快速迭代能力对于还在快速演进的云网络架构来说至关重要。但随着服务器密度的提升和网络流量的增长,软件 VTEP 的 CPU 开销从"可以接受"变成了"不可忽视",最终变成了"必须解决"。
规模变了,权衡的条件就变了。
6.2 硬件卸载:从 ToR 交换机到 SmartNIC
既然软件做封包解包太消耗 CPU,一个自然的想法是:把这件事交给专用硬件来做。通用 CPU 擅长处理复杂的、多变的逻辑,但对于"每个包都执行相同的固定操作"这种任务,专用硬件的效率要高几个数量级。
硬件卸载有两条路径。
第一条路径:把 VTEP 下推到 ToR 交换机。
ToR(Top of Rack)交换机是机架顶部的物理交换机,所有服务器的网线都插在它上面。如果让 ToR 交换机承担 VxLAN 的封包解包,宿主机就完全不需要做任何 Overlay 处理,VM 发出的原始帧直接到达 ToR,由 ToR 的 ASIC 芯片完成封装,然后通过物理网络发送到远端 ToR,远端 ToR 解封装后把原始帧交给目标宿主机。
图 6.1:ToR 交换机作为 VTEP 的数据路径
sequenceDiagram
participant VM as VM-A
participant Host as Host (No Overlay)
participant ToR as ToR Switch (VTEP)
participant Net as Physical Network
participant ToR2 as Remote ToR (VTEP)
participant VM2 as VM-B
VM->>Host: Original Frame
Host->>ToR: Original Frame (no encap)
Note over ToR: ASIC encapsulates:<br/>VxLAN + UDP + IP headers
ToR->>Net: VxLAN Packet
Net->>ToR2: VxLAN Packet
Note over ToR2: ASIC decapsulates
ToR2->>VM2: Original Frame
这条路径的优势是宿主机 CPU 完全解放。网络处理在 ToR 的专用 ASIC 芯片上完成,ASIC 的包处理速度可以达到每秒数十亿个包,比通用 CPU 快两到三个数量级。宿主机的所有 CPU 核心都可以卖给租户,没有任何浪费。
但代价是灵活性。ToR 交换机的 ASIC 芯片是固定功能的,它能做什么、不能做什么,在芯片设计阶段就决定了。每次网络策略变更,比如新增一个 VNI、修改转发规则、支持一种新的封装协议,都需要更新 ToR 的固件或配置。物理交换机的固件升级周期远长于软件:一次固件升级可能需要几周的测试和验证,还可能需要短暂的停机窗口。在云计算这种需要快速迭代的环境里,这个节奏太慢了。
更深层的问题是耦合。当 VTEP 在 ToR 上时,网络虚拟化的逻辑和物理网络的硬件绑定在了一起。云厂商的网络团队想要调整 Overlay 策略,必须和物理交换机的厂商协调,"你的 ASIC 支不支持这个新功能?什么时候能出新固件?"这种依赖关系在云计算的早期就被证明是不可接受的:云厂商需要对自己的网络架构有完全的控制权,不能被硬件厂商的开发节奏卡住。
第二条路径:SmartNIC / DPU。
SmartNIC(智能网卡)和 DPU(Data Processing Unit,数据处理单元)的思路是在服务器的网卡上集成专用的处理芯片。这块芯片不是通用 CPU,而是专门为网络处理设计的,它可以在硬件层面完成 VxLAN 的封包解包、流表匹配、QoS 限速等操作,速度接近 ASIC,但比 ASIC 更灵活。
SmartNIC / DPU 是什么?
SmartNIC(智能网卡)和 DPU(Data Processing Unit,数据处理单元)是在传统网卡基础上集成了可编程处理芯片的网络硬件。传统网卡只负责收发数据帧,所有网络处理(封包解包、流表匹配、安全过滤)都由宿主机 CPU 完成。SmartNIC/DPU 把这些工作卸载到网卡上的专用芯片,释放宿主机 CPU 给租户使用。两者的区别主要在定位上:SmartNIC 侧重网络功能卸载,DPU 的野心更大,试图接管整个基础设施层(网络、存储、安全)的虚拟化工作。AWS 的 Nitro、阿里云的神龙 MOC 卡、Azure 的 Catapult FPGA 都属于这一类。
图 6.2:三种 VTEP 位置的架构对比(图中 NIC 即网卡,Network Interface Card)
graph TB
subgraph optA["Option A: Software VTEP"]
direction LR
A_VM["VM"] --> A_OVS["OVS / Kernel<br/>(VTEP)"]
A_OVS --> A_NIC["NIC"]
A_NIC --> A_NET["Physical Network"]
end
subgraph optB["Option B: ToR as VTEP"]
direction LR
B_VM["VM"] --> B_NIC["NIC"]
B_NIC --> B_TOR["ToR Switch<br/>ASIC (VTEP)"]
B_TOR --> B_NET["Physical Network"]
end
subgraph optC["Option C: SmartNIC / DPU"]
direction LR
C_VM["VM"] --> C_DPU["SmartNIC / DPU<br/>(VTEP on chip)"]
C_DPU --> C_NET["Physical Network"]
end
style A_OVS fill:#fce4ec,stroke:#c62828
style B_TOR fill:#fff3e0,stroke:#f57c00
style C_DPU fill:#e8f5e9,stroke:#388e3c
style optA fill:#fafafa,stroke:#999
style optB fill:#fafafa,stroke:#999
style optC fill:#fafafa,stroke:#999
红色 = 消耗宿主机 CPU(软件封装)。橙色 = ToR 硬件处理(灵活性低)。绿色 = SmartNIC 硬件处理(CPU 零开销 + 灵活性中等,但成本高)。
SmartNIC 的优势在于它同时解决了软件 VTEP 和 ToR VTEP 的核心痛点。和软件 VTEP 相比,它解放了宿主机 CPU,封包解包在网卡芯片上完成,宿主机的 CPU 不需要参与。和 ToR VTEP 相比,它保留了灵活性,SmartNIC 的固件可以独立于物理交换机升级,云厂商可以自主控制网络虚拟化的迭代节奏。而且 SmartNIC 是插在服务器上的,每台服务器独立升级,不需要像 ToR 那样影响整个机架。
但需要付出更多的经济成本。一块支持 VxLAN 卸载的 SmartNIC,价格从几百到几千元不等。一个数据中心有几万台服务器,每台都配一块 SmartNIC,硬件采购成本是一笔巨大的投入。而且 SmartNIC 的生态还在成熟过程中,编程模型、调试工具、驱动兼容性,都不如通用 CPU 上的软件栈那么完善。当 SmartNIC 上的网络处理出了 bug,排查的难度比软件 VTEP 高得多,你不能像调试内核模块那样打断点、加日志,硬件上的问题往往需要抓包分析和固件级别的排查。
三种方案,三个维度的权衡:
| 维度 | 软件 VTEP | ToR VTEP | SmartNIC/DPU |
|---|---|---|---|
| CPU 开销 | 高 | 无 | 无 |
| 灵活性 | 高 | 低 | 中 |
| 硬件成本 | 无 | 无(已有设备) | 高 |
| 升级周期 | 分钟级 | 周级 | 天级 |
| 排障难度 | 低 | 中 | 高 |
没有一种方案在所有维度上都是最优的。选择取决于你更不愿意接受哪个代价。
但如果把时间轴拉长,会发现一个有趣的经济学规律:规模效应决定了最终赢家。
2012-2015 年,云厂商的服务器规模在几万到几十万台,软件 VTEP 的 CPU 开销虽然存在,但每台服务器的 CPU 本来就有富余(早期虚拟化密度低),"免费"的 CPU 比"昂贵"的 SmartNIC 更经济。2016-2019 年,单台服务器的虚拟化密度急剧上升(容器化),CPU 变得稀缺,每 1% 的 CPU 开销都意味着少卖一份算力给租户。此时 SmartNIC 的采购成本虽然高(每块几百到几千元),但释放出的 CPU 可以卖给租户产生收入——当"CPU 的机会成本"超过"SmartNIC 的采购成本"时,硬件卸载就变得经济上合理了。
这就是为什么 AWS 在 2013 年就开始研发 Nitro(当时它的规模已经大到 CPU 开销不可忽视),而中小云厂商直到 2018-2019 年才跟进 SmartNIC 方案。不是技术判断不同,而是经济拐点到来的时间不同。规模越大,CPU 的机会成本越高,硬件卸载的经济合理性越早到来。
6.3 分布式网关:VTEP 兼任路由器
到目前为止,VTEP 做的事情是二层转发,VM-A 发一个帧给 VM-B,VTEP 查 MAC 表,找到远端 VTEP 的 IP,封装,发送。但如果 VM-A 和 VM-B 不在同一个子网呢?VM-A 在 10.0.1.0/24,VM-B 在 10.0.2.0/24,这是一个跨子网的通信,需要三层路由。
传统的做法是设置一个集中式网关。所有跨子网的流量都发到这个网关,网关查路由表,决定把包转发到哪个子网,然后再封装发送。这个网关可能是一台专用的路由设备,也可能是一组高性能的服务器。
图 6.3:集中式网关 vs 分布式网关
graph TB
subgraph "Centralized Gateway"
VM_A1[VM-A<br/>10.0.1.10] -->|"Cross-subnet"| GW[Central Gateway]
GW -->|"Route + Encap"| VM_B1[VM-B<br/>10.0.2.20]
end
graph TB
subgraph "Distributed Gateway"
VM_A2[VM-A<br/>10.0.1.10] -->|"Cross-subnet"| VTEP_A[VTEP-A<br/>Route + Encap]
VTEP_A -->|"Direct to remote VTEP"| VM_B2[VM-B<br/>10.0.2.20]
end
集中式网关的问题很直观:它是一个瓶颈。所有跨子网的流量,在云环境中,这可能占总流量的 30% 到 50%,都要经过同一个网关节点。网关的带宽和处理能力是有限的,当流量超过网关的承载能力时,要么丢包,要么排队等待,延迟急剧上升。而且网关是一个单点,如果网关故障,所有跨子网的通信都会中断。虽然可以通过主备或集群来提高可用性,但集中式架构的扩展性天花板始终存在。
分布式网关的思路是把路由能力下放到每台宿主机的 VTEP 上。每个 VTEP 不仅知道"MAC-B 在哪个远端 VTEP 后面"(二层转发表),还知道"10.0.2.0/24 这个子网的网关 MAC 是什么"(三层路由表)。当 VM-A 要给 VM-B 发跨子网的包时,VM-A 把包发给自己的默认网关,这个网关不是一台远处的集中设备,而是本地 VTEP 上的一个虚拟接口。本地 VTEP 收到包后,查路由表,发现目标子网 10.0.2.0/24 对应的远端 VTEP 是 VTEP-B,直接在本地完成路由决策和 VxLAN 封装,把包发给 VTEP-B。
整个过程中,跨子网的包不需要绕到任何集中节点,它在源端 VTEP 上就完成了路由和封装,直接走最短路径到达目标。路由能力被分散到了每台宿主机上,没有单点瓶颈,没有集中式网关的带宽限制。
但分布式网关有一个前提:每台 VTEP 都需要知道完整的路由信息。"10.0.2.0/24 在 VTEP-B 后面"、"10.0.3.0/24 在 VTEP-C 后面",这些路由条目需要被控制面实时下发到每一台 VTEP。当 VPC 内有几十个子网、几千台 VM 时,路由表的规模和更新频率都不小。每次 VM 创建、销毁或迁移,都可能触发路由表的更新,控制面需要在秒级内把变更推送到所有相关的 VTEP。
这个架构选择和 VTEP 的位置选择是耦合的。如果 VTEP 在宿主机内核里(软件 VTEP),分布式网关也在内核里做,OVS 的流表同时处理二层转发和三层路由。如果 VTEP 在 SmartNIC 上,分布式网关的路由逻辑也要卸载到 SmartNIC 的芯片上,这对 SmartNIC 的功能要求更高,不仅要做封包解包,还要做路由查找和 ARP 处理。
VTEP 的角色正在从"隧道端点"扩展为"虚拟网络的全功能节点",它既是二层的转发者,又是三层的路由者。这个演进方向在后续章节会进一步展开。
6.4 各大云厂商的选择
同一个问题,不同的云厂商给出了不同的答案。这些差异不是因为谁对谁错,而是因为每家的起点不同、约束不同、优先级不同。
AWS 的路径最具代表性。早期,AWS 使用 Xen 虚拟化,VTEP 在 Xen 的 Dom0(特权域)内核中以软件方式实现。随着 EC2 实例密度的增长,软件 VTEP 的 CPU 开销变得不可接受。2013 年前后,AWS 开始自研专用硬件,最终的产物是 Nitro 系统。Nitro 的核心是一块定制的芯片(本质上是一种 DPU),它接管了网络虚拟化、存储虚拟化和安全管理的所有工作。宿主机的 CPU 被完全解放,100% 的算力都可以卖给客户。Nitro 的意义不仅仅是性能,它让 AWS 实现了"裸金属级别的虚拟化",虚拟机的网络性能和物理机几乎没有差异。
阿里云 走了类似的路径。自研的 神龙架构 通过 MOC 卡(一种类似 SmartNIC 的定制硬件)把网络和存储的虚拟化开销从宿主机 CPU 上卸载下来。MOC 卡不仅处理 VxLAN 封包解包,还承担了虚拟交换机的流表匹配、安全组规则的执行、以及存储 IO 的虚拟化。和 AWS 的 Nitro 一样,目标是让宿主机的 CPU 完全服务于租户的业务负载。
Azure 选择了一条不同的技术路线:FPGA。Azure 的 SmartNIC(代号 Catapult)使用可编程的 FPGA 芯片来实现网络功能卸载。FPGA 的优势在于可编程性,它的逻辑可以在部署后通过重新烧录来更新,不需要像 ASIC 那样等下一代芯片。这让 Azure 能够在不更换硬件的前提下,持续迭代网络虚拟化的功能。代价是 FPGA 的单位性能不如 ASIC,而且 FPGA 的编程门槛很高,需要硬件描述语言(HDL)的专业人才,开发周期比软件长得多。
Google Cloud 的 Andromeda 虚拟网络在早期以软件为主,利用 Google 在软件工程上的深厚积累来优化软件 VTEP 的性能。Google 的思路是通过极致的软件优化(比如内核旁路、批量处理、零拷贝)来尽可能压低 CPU 开销,同时逐步引入硬件卸载。这条路径的优势是不需要在早期就投入巨大的硬件研发成本,但随着规模的增长,Google 也在向硬件卸载的方向演进。
这些选择背后有一个共同的方向:从"软件做一切"向"关键路径硬件卸载"演进。没有一家云厂商还停留在纯软件 VTEP 的阶段,规模不允许。但演进的节奏和路径各不相同:AWS 和阿里云选择了自研 ASIC/定制芯片,追求极致的性能和成本控制;Azure 选择了 FPGA,追求可编程性和灵活性;Google 选择了软件优先、逐步卸载的渐进路线。
每家的选择都取决于自身的条件。AWS 有足够的规模来摊薄自研芯片的研发成本,当你有几百万台服务器时,每台服务器省下的 CPU 乘以总量,足以覆盖芯片研发的投入。Azure 有微软在 FPGA 领域的长期积累,Catapult 项目最初是为 Bing 搜索加速设计的,后来被复用到网络虚拟化。Google 有全球顶尖的软件工程能力,在别人需要硬件才能达到的性能,Google 有时候用软件优化就能逼近。
这些路径之间没有对错,只有约束不同下的合理性。但它们都指向同一个结论:在规模足够大之后,你不得不为网络虚拟化专门造芯片。 区别只在于造什么样的芯片、什么时候开始造、以及用什么技术路线来造。
6.5 VTEP 确定了,控制面在哪里
无论 VTEP 放在宿主机内核里、ToR 交换机上还是 SmartNIC 里,它都面临同一个问题:谁来告诉它当前的转发规则是什么?
VTEP 需要知道的信息很多。
- "VNI 1000 对应哪些 VM?",这决定了哪些帧需要被封装。
- "MAC-B 在哪个远端 VTEP 后面?",这决定了封装后的包发给谁。
- "10.0.2.0/24 这个子网的下一跳是什么?",如果 VTEP 兼任分布式网关,它还需要路由信息。
这些信息不是 VTEP 自己能发现的,它不像传统交换机那样可以通过泛洪和学习来建立 MAC 表。在云计算的规模下,泛洪的开销不可接受,VTEP 必须被"告知"转发规则。
告知 VTEP 的那个角色,就是控制面。
控制面的职责是维护全局的网络拓扑信息,哪个 VM 在哪台宿主机上、属于哪个 VNI、MAC 地址是什么、IP 地址是什么,然后把这些信息翻译成 VTEP 能理解的转发规则(流表),实时下发到每台 VTEP。当一台新的 VM 被创建时,控制面需要在几秒内把这台 VM 的信息推送到所有相关的 VTEP,让它们知道"有一台新的 VM 上线了,它的 MAC 是 XX,在 VTEP-Y 后面"。当一台 VM 被迁移到另一台宿主机时,控制面需要更新所有 VTEP 的转发表,"MAC-B 不再在 VTEP-A 后面了,它现在在 VTEP-C 后面"。
这个过程的规模是惊人的。一个大型数据中心可能有几万台宿主机,每台宿主机上运行一个 VTEP。一个 VPC 可能有几千台 VM,分布在几千台宿主机上。每次 VM 的创建、销毁、迁移,都会触发一次或多次转发表的更新,这些更新需要被推送到所有相关的 VTEP。控制面必须能够处理每秒数千次的状态变更,并在毫秒级内完成下发。
当用户在云控制台上点击"创建一个 VPC"、"添加一个子网"、"启动一台 VM"时,这些操作最终都会被翻译成控制面的指令,分配一个 VNI、更新路由表、下发流表到相关的 VTEP。用户看到的是"VPC"这个产品概念,一个逻辑上隔离的私有网络空间;底层是控制面在管理成千上万个 VTEP 的转发规则,让这个"逻辑上隔离"的承诺变成物理上的现实。
VTEP 是数据面,它负责搬运每一个包。控制面负责告诉数据面"怎么搬"。数据面的位置(软件、ToR、SmartNIC)决定了搬运的效率;控制面的设计决定了搬运规则的正确性和时效性。两者缺一不可。
到这里,数据面和控制面的技术骨架已经搭好了。但用户不会直接和 VTEP 打交道,也不会手动给控制面下指令。用户在云控制台上看到的是"VPC"、"子网"、"路由表"这些产品概念,这些概念和底层的 VNI、VTEP、流表,到底是怎么对应起来的?