目录
- 前言
- GRE 隧道技术
- VXLAN
- GRE/VXLAN接入云平台
前言
之前提到,为云平台中的租户实现隔离时,常用的策略是基于 VLAN。然而,VLAN 只有 12 位,共支持 4096 个 ID,这在最初设计时看似足够,但随着云计算的快速发展,这一限制已无法满足需求。那么该如何应对呢?
为什么不能直接修改 VLAN 协议?
一种可能的想法是直接修改现有的 VLAN 协议,让其支持更多的 ID。然而,这种方法在实践中几乎不可行,因为:
- VLAN 协议已经成为行业标准,广泛应用于各种网络设备和程序中。
- 如果修改协议,就需要更新所有相关的设备和软件,这是一个巨大的工程,几乎无法完成。
因此,直接修改协议并不现实。
扩展的思路:新增包头
另一种更为实际的方式是扩展协议,在现有的数据包格式上新增一个扩展包头,包含足够区分租户的 ID。外层包的格式仍保持与传统网络兼容,而需要区分用户时,由特定的软件或硬件处理这些带有扩展包头的特殊数据包。
这种方法与我们在第 22 讲中提到的“隧道理论”非常相似。还记得自驾游时通过摆渡轮到海南岛的例子吗?当时,隧道理论中的扩展包头主要用于加密,而这里的扩展包头则用于区分租户。
Underlay 与 Overlay 网络
为了解决云平台中的隔离问题,同时兼容传统网络,我们引入了 Underlay 和 Overlay 网络的概念:
- Underlay 网络:底层的物理网络,由真实的物理交换机、路由器等设备组成,承载所有基础的网络通信。
- Overlay 网络:虚拟化的网络,由一系列基于 Underlay 网络的技术实现,用于为虚拟机和租户提供隔离、互通以及灵活的网络配置。
Overlay 网络通过在物理网络之上创建虚拟化的二层或三层网络,为每个租户提供独立的逻辑网络。扩展包头的设计正是 Overlay 网络的关键所在。
典型的 Overlay 网络技术
本章将重点讲解两种常用的 Overlay 网络技术,分别是 VXLAN(虚拟扩展局域网) 和 GRE 隧道技术。它们通过新增包头的方式,突破了 VLAN 的局限,同时保持了对传统网络的兼容性。
这种扩展和隧道化的方式,不仅解决了隔离问题,还使得云平台的网络更灵活、更适应大规模、多租户的需求。
GRE 隧道技术
第一个 Overlay 网络技术是 GRE(Generic Routing Encapsulation),即通用路由封装。它是一种 IP-over-IP 的隧道技术,可以将 IP 数据包封装在 GRE 包中,外面再加上一层 IP 头。隧道的一端负责封装数据包,在传输过程中通过隧道传递,另一端则负责解封装。可以将 GRE 隧道理解为一种虚拟的点对点连接。
GRE 包头结构
在 GRE 包头中:
- 前 32 位 是固定存在的,主要用于隧道的基础功能。
- 后续字段 是可选的,是否包含这些字段由包头中的标志位决定。
- Key 字段 是一个非常重要的部分,它是一个 32 位字段,常用于区分不同的用户或隧道连接。在云平台中,这个字段存储的是 Tunnel ID,而 32 位的大小已经足以满足大规模云平台的需求。
在专用于网络虚拟化的 GRE 包头格式中,有一种叫做 NVGRE(Network Virtualization GRE) 的扩展版本,它提供了一个 24 位的网络 ID 字段。这个网络 ID 号足够表示 16,777,216 个虚拟网络,完全能够满足云平台的需求。
GRE 隧道的实现
GRE 隧道的封装和解封装需要由支持路由功能的设备来完成,这些设备可以是专用路由器,也可以是启用了路由功能的 Linux 服务器。GRE 隧道建立后,会在路由设备上生成虚拟的 Tunnel 端口,专门用于封包和解封包操作。
GRE 隧道的通信过程
GRE 隧道的传输过程如下:
- 在两个网络设备之间建立隧道,隧道的起点和终点由设备上的 Tunnel 端口表示。
- 数据包从源网段发出后,通过隧道的入口端口进行封包,添加 GRE 包头和外层 IP 头。
- 数据包在物理网络中传输,GRE 包头中的 Key 字段 用于标识数据包所属的隧道。
- 数据包到达隧道出口后,解封 GRE 包头和外层 IP 头,并将原始 IP 包转发到目标网段。
主机 A 想要访问主机 B,发送一个网络包:
- 源 IP 地址:192.168.1.102
- 目标 IP 地址:192.168.2.115
由于主机 B 在不同的网段,主机 A 会根据默认路由规则将数据包发送给默认网关(左侧路由器的地址 192.168.1.1)。
-
左侧路由器封装数据包
左侧路由器接收到主机 A 发来的数据包后,根据路由表发现目标网段(192.168.2.0/24)需要通过 GRE 隧道来访问。此时,路由器执行以下操作:- 封装数据包:
- 在原始 IP 头(源地址 192.168.1.102,目标地址 192.168.2.115)之外,加上一个 GRE 头。
- 对于 NVGRE,这一步会在 MAC 头之后添加 GRE 头,并包括一个租户隔离的网络 ID。
- 添加外部 IP 头:
- 外部 IP 头用于在公网中传输数据包。
- 源 IP 地址:左侧路由器的外网地址(172.17.10.10)。
- 目标 IP 地址:右侧路由器的外网地址(172.16.11.10)。
最终,封装后的数据包从左侧路由器的物理网卡(E1)发送到公共网络中。
- 封装数据包:
-
公共网络传输
数据包进入公共网络后,沿着公网路由器一跳一跳地转发。此时,所有的路由操作都基于外部的 IP 地址(172.17.10.10 和 172.16.11.10),GRE 头和内部 IP 头都不会被解读。 -
右侧路由器解封装
数据包到达右侧路由器后,右侧路由器会检测到这是一个 GRE 包,并执行以下步骤:- 解封装数据包:
- 去掉外层的 IP 头和 GRE 头,恢复原始数据包。
- 原始数据包的源 IP 地址为 192.168.1.102,目标 IP 地址为 192.168.2.115。
- 转发到目标主机:
- 根据路由表,路由器将解封装后的数据包从接口 E3 发送到右侧的网络,最终到达主机 B。
- 解封装数据包:
-
主机 B 接收数据包
主机 B 接收到数据包后,发现目标地址是自己的 IP 地址(192.168.2.115),于是正常处理数据包并做出响应。 -
GRE 隧道通信的关键步骤总结
- 封装:在发送端路由器,将数据包封装为 GRE 包,并添加外层的 IP 头,用于公网传输。
- 传输:在公共网络中,所有路由操作基于外层的 IP 地址完成。
- 解封装:在接收端路由器,将 GRE 包解封,恢复原始数据包。
- 转发:根据目标 IP 地址和路由表,将数据包转发到目标主机。
这种基于 GRE 隧道的传输方式使得两个不同网段的主机能够通过公共网络安全、透明地通信,同时借助 GRE 的 Key 字段 或 NVGRE 的 网络 ID,可以实现用户流量的隔离。
优势与局限
-
优势:
- 支持广泛的协议封装:不仅限于 IPv4 和 IPv6,还可以封装多种其他协议,具有良好的兼容性。
- 灵活的租户隔离:通过 GRE 包头中的 Key 字段和 NVGRE 的网络 ID,可以轻松实现大规模云平台的租户隔离需求。
- 易于部署:基于现有物理网络即可实现 Overlay 网络,不需要对底层网络做大规模改造。
-
局限:
- 缺乏内置安全性:GRE 隧道本身不具备加密功能,数据安全需要额外借助协议(如 IPSec)来保障。
- 增加网络开销:封包和解包会消耗计算资源,尤其在高负载场景下可能影响性能。
- 隧道数量限制:GRE 是一种点对点隧道,如果有多个网络需要互联,隧道数量会呈指数增长。例如,3 个网络需要建立 3 条隧道,5 个网络需要 10 条隧道,随着网络规模增加,管理复杂性也会大幅提升。
- 不支持组播:当一个网络中的虚拟机发送广播帧时,GRE 会将该广播包复制并发送到所有与其相连的节点,增加了不必要的流量开销,影响效率。
- 兼容性问题:部分防火墙和三层网络设备无法正确解析 GRE 数据包,因此无法对其进行有效过滤或负载均衡。
VXLAN
第二种 Overlay 网络技术是 VXLAN(Virtual Extensible LAN)。与 GRE 在三层头部之外增加封装不同,VXLAN 在二层头部外直接封装了一个 VXLAN 包头。VXLAN 包头包含一个 24 位的 VXLAN ID,支持多达 16,777,216 个逻辑网络,远远超越了传统 VLAN 的 4096 个 ID 限制。在 VXLAN 包头外,还封装了 UDP、IP 和外层 MAC 头。
VXLAN 的核心组件:VTEP
为了实现 VXLAN 的封装和解封装,需要一种称为 VTEP(VXLAN Tunnel Endpoint) 的组件来处理 VXLAN 数据包。VTEP 类似于虚拟机网络的“管家”,负责管理虚拟机的网络连接。以下是 VTEP 的主要功能:
- 虚拟机注册:每台物理机上都可以有一个 VTEP,虚拟机启动时会向 VTEP 注册,VTEP 记录管理的所有虚拟机信息。
- 包的封装和解封装:当虚拟机需要跨 VTEP 通信时,由 VTEP 完成 VXLAN 包头的封装与解封装。
- 通信代理:通过 VTEP 代理机制,实现跨物理机的虚拟机通信。
与 GRE 的区别
- 拓扑模型:GRE 是点对点的隧道,需要为每对通信的网络建立一个隧道,随着网络规模增加,隧道数量呈指数增长;而 VXLAN 支持基于组播的通信,无需每对节点单独建立隧道。
- 动态发现:VXLAN 使用组播技术动态发现目标节点,而 GRE 通信需要明确的隧道端点。
- 扩展性:VXLAN 的 24 位网络 ID 远超 GRE 和 VLAN 的限制,适合大规模云平台。
组播在 VXLAN 中的作用
VXLAN 利用 IGMP(Internet Group Management Protocol) 组播协议进行动态目标定位。VTEP 的组播机制类似于加入一个邮件列表或微信群:
- 当 VTEP 启动时,它会通过 IGMP 协议加入一个组播组,表示自己愿意接收组播流量。
- 当虚拟机上线并向 VTEP 注册后,VTEP 知道自己负责管理哪些虚拟机。
- 如果某台虚拟机发送数据包,VTEP 会将数据封装为 VXLAN 包,并根据组播组转发给目标 VTEP。所有加入该组播组的节点都会收到此消息,从而实现动态定位。
VXLAN 的优点
- 扩展性强:24 位的 VXLAN ID 能够支持大量虚拟网络,非常适合大规模、多租户的云平台。
- 动态发现目标节点:通过组播机制,无需预先配置隧道,通信更加灵活。
- 简化网络配置:支持二层扩展和动态地址发现,无需大规模改造物理网络。
VXLAN 的实现逻辑
当物理机上的虚拟机启动后,VTEP 立即感知到其上线,并完成以下操作:
- 注册虚拟机:虚拟机将自身的信息(如 IP 和 MAC 地址)注册到所在物理机的 VTEP。
- 加入组播组:VTEP 通过 IGMP 协议加入指定的组播组,准备接收来自其他 VTEP 的通信。
- 动态通信:当虚拟机发送数据包时,VTEP 封装 VXLAN 包头并利用组播将其发送到目标节点的 VTEP。
- 解封装与转发:目标 VTEP 解封 VXLAN 包后,将原始数据包转发到目标虚拟机。
VXLAN 的组播机制和动态发现能力使其在云平台中比 GRE 更加灵活高效,特别是在大规模、多租户环境下,能够显著降低网络管理的复杂性。
如图,虚拟机 1、2、3 属于云中同一个用户的虚拟机,因而需要分配相同的 VXLAN ID=101。在云的界面上,就可以知道它们的 IP 地址,于是可以在虚拟机 1 上 ping 虚拟机 2。
虚拟机 1 发现,它不知道虚拟机 2 的 MAC 地址,因而包没办法发出去,于是要发送 ARP 广播。
ARP 请求到达 VTEP1 的时候,VTEP1 知道,我这里有一台虚拟机,要访问一台不归我管的虚拟机,需要知道 MAC 地址,可是我不知道啊,这该咋办呢?
VTEP1 想,我不是加入了一个微信群么?可以在里面 @all 一下,问问虚拟机 2 归谁管。于是 VTEP1 将 ARP 请求封装在 VXLAN 里面,组播出去。
当然在群里面,VTEP2 和 VTEP3 都收到了消息,因而都会解开 VXLAN 包看,里面是一个 ARP。
VTEP3 在本地广播了半天,没人回,都说虚拟机 2 不归自己管。
VTEP2 在本地广播,虚拟机 2 回了,说虚拟机 2 归我管,MAC 地址是这个。通过这次通信,VTEP2 也学到了,虚拟机 1 归 VTEP1 管,以后要找虚拟机 1,去找 VTEP1 就可以了。
VTEP2 将 ARP 的回复封装在 VXLAN 里面,这次不用组播了,直接发回给 VTEP1。
VTEP1 解开 VXLAN 的包,发现是 ARP 的回复,于是发给虚拟机 1。通过这次通信,VTEP1 也学到了,虚拟机 2 归 VTEP2 管,以后找虚拟机 2,去找 VTEP2 就可以了。
虚拟机 1 的 ARP 得到了回复,知道了虚拟机 2 的 MAC 地址,于是就可以发送包了。
虚拟机 1 发给虚拟机 2 的包到达 VTEP1,它当然记得刚才学的东西,要找虚拟机 2,就去 VTEP2,于是将包封装在 VXLAN 里面,外层加上 VTEP1 和 VTEP2 的 IP 地址,发送出去。
网络包到达 VTEP2 之后,VTEP2 解开 VXLAN 封装,将包转发给虚拟机 2。
虚拟机 2 回复的包,到达 VTEP2 的时候,它当然也记得刚才学的东西,要找虚拟机 1,就去 VTEP1,于是将包封装在 VXLAN 里面,外层加上 VTEP1 和 VTEP2 的 IP 地址,也发送出去。
网络包到达 VTEP1 之后,VTEP1 解开 VXLAN 封装,将包转发给虚拟机 1。
GRE/VXLAN接入云平台
假设有多个物理机上的虚拟机,它们通过虚拟交换机(如 br0)进行互联,路由器和 DHCP 服务器则负责提供网络连接和地址分配。在这种网络架构中,虚拟机要访问互联网时,必须通过虚拟交换机连接到路由器,路由器再将请求通过 NAT 转发到公网。
当多个物理机上的虚拟机需要共享相同的虚拟交换机时,问题便出现了:由于物理机分布在不同的物理位置,它们的 br0 交换机可能会被切割成多个独立的段。为了解决这个问题,我们可以通过在物理机之间建立隧道,将各个虚拟交换机连接起来,使得虚拟机和路由器看起来仍然在同一个网络中。
在这个过程中,引入了 br1 这一虚拟交换机。br1 将虚拟机之间的互联和物理机之间的互联分开设计,使得网络架构更加清晰和灵活。隧道可以使用多种技术来实现,如 GRE 或 VXLAN。
当使用 OpenvSwitch 时,br0 可以借助 OpenvSwitch 提供的 Tunnel 和 Flow 功能来实现隧道通信。OpenvSwitch 支持三种类型的隧道:GRE、VXLAN 和 IPsec_GRE。利用这些技术,虚拟交换机可以成为 GRE 和 VXLAN 封装的终端,帮助有效管理和转发流量。
三台物理机,每台上都有两台虚拟机,分别属于两个不同的用户,因而 VLAN tag 都得打地不一样,这样才不能相互通信。但是不同物理机上的相同用户,是可以通过隧道相互通信的,因而通过 GRE 隧道可以连接到一起。
接下来,所有的 Flow Table 规则都设置在 br1 上,每个 br1 都有三个网卡,其中网卡 1 是对内的,网卡 2 和 3 是对外的。
下面我们具体来看 Flow Table 的设计。
1.Table 0 是所有流量的入口,所有进入 br1 的流量,分为两种流量,一个是进入物理机的流量,一个是从物理机发出的流量。
从 port 1 进来的,都是发出去的流量,全部由 Table 1 处理。
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 in_port=1 actions=resubmit(,1)"
从 port 2、3 进来的,都是进入物理机的流量,全部由 Table 3 处理。
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 in_port=2 actions=resubmit(,3)"
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 in_port=3 actions=resubmit(,3)"
如果都没匹配上,就默认丢弃。
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=0 actions=drop"
2.Table 1 用于处理所有出去的网络包,分为两种情况,一种是单播,一种是多播。
对于单播,由 Table 20 处理。
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=1 dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20)"
对于多播,由 Table 21 处理。
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=1 dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,21)"
3.Table 2 是紧接着 Table1 的,如果既不是单播,也不是多播,就默认丢弃。
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=0 table=2 actions=drop"
4.Table 3 用于处理所有进来的网络包,需要将隧道 Tunnel ID 转换为 VLAN ID。
如果匹配不上 Tunnel ID,就默认丢弃。
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=0 table=3 actions=drop"
如果匹配上了 Tunnel ID,就转换为相应的 VLAN ID,然后跳到 Table 10。
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=3 tun_id=0x1 actions=mod_vlan_vid:1,resubmit(,10)"
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=3 tun_id=0x2 actions=mod_vlan_vid:2,resubmit(,10)"
- 对于进来的包,Table 10 会进行 MAC 地址学习。这是一个二层交换机应该做的事情,学习完了之后,再从 port 1 发出去。
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=10 actions=learn(table=20,priority=1,hard_timeout=300,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:0->NXM_OF_VLAN_TCI[],load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],output:NXM_OF_IN_PORT[]),output:1"
Table 10 是用来学习 MAC 地址的,学习的结果放在 Table 20 里面。Table20 被称为 MAC learning table。
NXM_OF_VLAN_TCI 是 VLAN tag。在 MAC learning table 中,每一个 entry 都仅仅是针对某一个 VLAN 来说的,不同 VLAN 的 learning table 是分开的。在学习结果的 entry 中,会标出这个 entry 是针对哪个 VLAN 的。
NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[] 表示,当前包里面的 MAC Source Address 会被放在学习结果的 entry 里的 dl_dst 里。这是因为每个交换机都是通过进入的网络包来学习的。某个 MAC 从某个 port 进来,交换机就应该记住,以后发往这个 MAC 的包都要从这个 port 出去,因而源 MAC 地址就被放在了目标 MAC 地址里面,因为这是为了发送才这么做的。
load:0->NXM_OF_VLAN_TCI[] 是说,在 Table20 中,将包从物理机发送出去的时候,VLAN tag 设为 0,所以学习完了之后,Table 20 中会有 actions=strip_vlan。
load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[] 的意思是,在 Table 20 中,将包从物理机发出去的时候,设置 Tunnel ID,进来的时候是多少,发送的时候就是多少,所以学习完了之后,Table 20 中会有 set_tunnel。
output:NXM_OF_IN_PORT[] 是发送给哪个 port。例如是从 port 2 进来的,那学习完了之后,Table 20 中会有 output:2。
所以如图所示,通过左边的 MAC 地址学习规则,学习到的结果就像右边的一样,这个结果会被放在 Table 20 里面。
6.Table 20 是 MAC Address Learning Table。如果不为空,就按照规则处理;如果为空,就说明没有进行过 MAC 地址学习,只好进行广播了,因而要交给 Table 21 处理。
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=0 table=20 actions=resubmit(,21)"
7.Table 21 用于处理多播的包。
如果匹配不上 VLAN ID,就默认丢弃。
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=0 table=21 actions=drop"
如果匹配上了 VLAN ID,就将 VLAN ID 转换为 Tunnel ID,从两个网卡 port 2 和 port 3 都发出去,进行多播。
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1table=21dl_vlan=1 actions=strip_vlan,set_tunnel:0x1,output:2,output:3"
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1table=21dl_vlan=2 actions=strip_vlan,set_tunnel:0x2,output:2,output:3"
总结:
- GRE 是一种点对点的隧道模式,而 VXLAN 支持组播隧道模式。它们都需要在 Tunnel Endpoint
进行封装和解封装,以实现跨物理机的互联。 - OpenvSwitch 可以作为 Tunnel Endpoint,通过配置流表规则,将虚拟机网络与物理机网络进行隔离和转换,从而实现高效的跨机通信。