1
2
3
4
5
6
7
作者:李晓辉

联系方式:

1. 微信:Lxh_Chat

2. 邮箱:939958092@qq.com

ML2 介绍

在 OpenStack 里,ML2 是一个网络插件,全名叫“Modular Layer 2”。你可以把它想象成一个“网络搭桥工”,它的主要任务就是帮虚拟机和外部网络之间“搭桥铺路”,让虚拟机能够顺利地和其他设备通信。

为啥要有 ML2?

在云计算的世界里,虚拟机都跑在一个个服务器上,这些服务器就像是一个个“小岛”。虚拟机要想和其他“小岛”上的设备(比如别的虚拟机、存储设备等)聊天,就需要通过网络来连接。但网络这事儿挺复杂的,不同的环境可能用不同的网络技术,比如有的用 VLAN,有的用 VXLAN,还有的用 OVS(Open vSwitch)之类的。如果没有一个统一的“搭桥工”,虚拟机就很难找到合适的路,或者得为每种网络技术都写一套代码,那太麻烦了!

ML2 就是来解决这个问题的。它就像是一个“中间人”,不管你的网络环境用啥技术,它都能帮你搞定,让虚拟机顺利地和其他设备通信。

ML2 的工作原理

ML2 是 OpenStack 网络(Neutron)的一个插件框架,它的核心功能是让 OpenStack 能够同时使用多种不同的网络技术。就好比你在不同的地方修路,有的地方可能用高速公路(VXLAN),有的地方可能用普通公路(VLAN),ML2 就是那个能同时搞定这些不同路的“修路工”。

类型驱动程序(Type Driver)

类型驱动程序就像是“规划师”,它决定了这条路的“类型”。具体来说,它定义了网络的“结构”和“规则”。在 OpenStack 中,最常见的类型驱动程序包括:

  • VLAN 类型驱动程序:它负责管理 VLAN 网络。VLAN 是一种传统的网络隔离技术,通过给每个虚拟网络分配一个唯一的 VLAN 标签来实现隔离。类型驱动程序会告诉系统:“嘿,这个网络要用 VLAN,每个虚拟机的流量都要打上这个标签。”

  • VXLAN 类型驱动程序:它负责管理 VXLAN 网络。VXLAN 是一种更先进的网络技术,可以在不同的物理网络之间创建虚拟网络。类型驱动程序会告诉系统:“这个网络要用 VXLAN,我们需要在底层网络上封装这些流量。”

举个例子:

假设你有一个虚拟机网络,你想用 VLAN 来隔离这些虚拟机。你就会启用 VLAN 类型驱动程序。这个驱动程序会告诉 OpenStack:“这个网络要用 VLAN,每个虚拟机的流量都要打上 VLAN 标签。”这样,当虚拟机发送数据时,OpenStack 就知道该用 VLAN 的方式来处理这些流量。

机制驱动程序(Mechanism Driver)

机制驱动程序就像是“施工队”,它负责把类型驱动程序的设计变成现实。具体来说,它定义了如何在物理网络上实现这些网络规则。在 OpenStack 中,最常见的机制驱动程序包括:

  • Open vSwitch 机制驱动程序:Open vSwitch 是一个开源的虚拟交换机,它运行在虚拟机的宿主机上。这个机制驱动程序会告诉 Open vSwitch:“嘿,这个虚拟机的流量要用 VLAN 标签,或者这个虚拟机的流量要用 VXLAN 封装。”然后 Open vSwitch 会按照这些规则来处理流量。

  • Linux Bridge 机制驱动程序:Linux Bridge 是一个基于 Linux 内核的虚拟交换机。这个机制驱动程序会告诉 Linux Bridge 如何处理虚拟机的流量,比如如何打上 VLAN 标签或者如何封装 VXLAN 流量。

举个例子:

假设你已经决定用 VLAN 来隔离虚拟机网络(类型驱动程序已经定义好了),现在你需要让这些规则在物理网络上生效。如果你的环境中使用了 Open vSwitch,那么 Open vSwitch 机制驱动程序就会告诉 Open vSwitch:“这个虚拟机的流量要用 VLAN 标签 100。”然后 Open vSwitch 会按照这个规则来处理流量,确保虚拟机的流量正确地打上 VLAN 标签并发送到物理网络。

总结一下

  • 类型驱动程序:决定网络的“类型”(比如 VLAN 或 VXLAN),定义网络的“规则”。

  • 机制驱动程序:根据类型驱动程序的规则,在物理网络上实现这些规则。

为什么需要这两种驱动程序?

因为网络环境很复杂,不同的环境可能用不同的技术。ML2 通过这两种驱动程序,可以灵活地支持多种网络技术。比如,你可以同时用 VLAN 和 VXLAN,或者在不同的主机上用不同的虚拟交换机(Open vSwitch 或 Linux Bridge)。这样,不管你的网络环境怎么变,ML2 都能搞定。

ML2 的好处

  1. 灵活:不管你的网络环境用啥技术,ML2 都能搞定,就像一个“万能适配器”。

  2. 扩展性强:如果以后你的网络环境要换新技术,ML2 只需要加载一个新的驱动,不需要重新写一大堆代码。

  3. 简单易用:对于管理员来说,ML2 提供了一套统一的接口,不管用啥网络技术,操作起来都差不多,很方便。

ML2 的小缺点

虽然 ML2 很厉害,但它也有个小缺点:因为它是通过各种驱动来适配不同技术的,所以如果驱动有问题,或者网络环境特别复杂,可能会出现一些小故障。不过,这些问题一般都能通过更新驱动或者调整配置来解决。

总之,ML2 就像是 OpenStack 里的“网络搭桥工”,帮虚拟机和其他设备之间搭桥铺路,让它们能够顺利通信。有了它,不管你的网络环境怎么变,虚拟机都能找到合适的路,不用担心“迷路”了。

常见⽹络类型

OpenStack 网络服务就像是一个“网络魔术师”,它可以在虚拟环境中提供各种网络功能,就像是把网络变成了一种“即插即用”的服务。它不仅能做传统的网络事情,比如划分子网、搭桥、用 VLAN 隔离流量,还能用一些更厉害的技术,比如开放虚拟网络(OVN)。OVN 是红帽 OpenStack 平台的默认 SDN 技术,它能让网络变得更灵活、更智能。

扁平网络

如果你的虚拟机需要直接连到外面的大网络,就用扁平网络。这种网络就像是“直通线”,虚拟机可以直接和外部网络对话,不需要经过复杂的中间环节。

VLAN

VLAN 就像是给网络流量贴上“标签”,让不同的流量分道扬镳。想象一下,你在一个大办公室里,有很多不同的部门,每个部门的文件都有自己的标签,这样就不会搞混了。VLAN 也是这样,它通过在数据包里加上一个特殊的标签(这个标签是按照 IEEE 802.1Q 标准定义的,值是 0x8100),来区分不同的流量。

这个标签里有一个“VLAN 标识符”字段,它告诉网络设备这个数据包属于哪个虚拟网络。因为这个字段有 12 位,所以理论上可以有 4094 个不同的 VLAN(去掉两个保留值)。这意味着在一个物理网络里,你可以划分出 4094 个不同的虚拟网络,每个网络里的流量都不会互相干扰。

查询课程中网络VLAN范围定义

这里可以看到外部网络名称以及存储ID范围等信息,我们可以用101-104的VLAN ID来创建flat

1
2
3
4
[root@controller0 ml2]# pwd
/var/lib/config-data/puppet-generated/neutron/etc/neutron/plugins/ml2
[root@controller0 ml2]# grep ^network ml2_conf.ini
network_vlan_ranges=datacentre:1:1000,vlanprovider1:101:104,vlanprovider2:101:104,storage:30:30

GENEVE

GENEVE概述

想象一下,你有一个很大的办公室,里面有成千上万的员工(虚拟机),他们都需要互相通信,但又不能互相干扰。VLAN 就像是给每个部门的文件贴上标签,但它的标签数量有限,最多只能有 4094 个,这在大规模环境中显然是不够的。

于是,VXLAN 出现了。VXLAN 通过一个 24 位的标签(VNI,VXLAN Network Identifier)解决了这个问题,它可以支持多达 1600 万个不同的网络,这比 VLAN 的 4000 多个标签要多得多。但是,VXLAN 有一个小问题:它和其他一些技术(比如 STT 和 NVGRE)不太兼容,这就像是不同部门之间用不同的语言交流,很容易出问题。

为了解决这个问题,GENEVE 出现了。GENEVE 是一个“超级翻译器”,它支持 VXLAN、NVGRE 和 STT 的所有功能,让这些不同的技术能够互相兼容。GENEVE 的工作方式有点像一个“通用数据封装器”,它只封装数据的格式,但不包含控制平面的任何规范。这就像是一个通用的“快递包装”,不管里面是什么东西(数据),它都能安全地传输。

每个 GENEVE 隧道都有一个唯一的 VNI(VXLAN Network Identifier),这就像每个快递包裹都有一个唯一的追踪号。GENEVE 的接口可以在 OpenStack 的 overcloud 节点上找到,这就像是在办公室的每个楼层都设置了快递收发点,方便管理和查找。

举个例子

假设你有一个虚拟机网络,里面有 10000 个虚拟机,它们需要分成不同的组进行通信。如果用 VLAN,你可能会遇到标签不够用的问题。但如果用 GENEVE,你可以轻松地为每个组分配一个唯一的 VNI,这样每个组的虚拟机都能安全地通信,而不会互相干扰。

GENEVE 数据帧结构

这个表格详细描述了 GENEVE 数据帧的结构。我们可以把它想象成一个“包裹”,每个部分都有特定的作用。

GENEVE 数据帧结构

1. 外层 L2(Outer L2)

  • 目的 MAC 地址(Destination MAC Address):这是数据帧的“收件人地址”,告诉网络设备这个数据帧应该送到哪里。

  • 源 MAC 地址(Source MAC Address):这是数据帧的“寄件人地址”,标识数据帧是从哪里发出的。

  • 以太网类型(EtherType):这是数据帧的“内容类型标签”,告诉网络设备这个帧里面装的是什么类型的数据。对于 GENEVE,它通常是 IPv4(0x0800)或 IPv6(0x86dd)。

2. 外层 L3(Outer L3)

  • 协议(Protocol):这是数据帧的“传输协议”,对于 GENEVE,它使用 UDP 协议(协议号 0x11)。

  • 源 IP 地址(Source IP Address):这是数据帧的“寄件人 IP 地址”,标识发送数据的设备。

  • 目的 IP 地址(Destination IP Address):这是数据帧的“收件人 IP 地址”,标识接收数据的设备。这些 IP 地址通常是 VTEP(VXLAN Tunnel End Point)的地址,也就是 OVS(Open vSwitch)隧道桥接(br-tun)的端点。

3. 外层 L4(Outer L4)

  • UDP 源端口(UDP Source Port):这是数据帧的“寄件人端口”,对于 GENEVE,它通常是 6801。这个端口是 VTEP 服务端口,用于标识发送方的隧道端点。

4. GENEVE 基础头部(GENEVE Base Header)

  • 版本(Version):标识 GENEVE 协议的版本。

  • 标志(Flags):用于控制数据帧的行为。

  • 保留位(Reserved bits):暂时不用的位,留作未来扩展。

  • 协议类型(Protocol Type):标识原始数据帧的类型。

  • 虚拟网络标识符(VNI):这是一个 24 位的字段,用于标识虚拟网络。它可以支持多达 1600 万个不同的隧道标识符。

5. GENEVE 选项(GENEVE Options)

  • 类别(Class):标识选项的类别。

  • 类型(Type):标识选项的具体类型。

  • 保留位(Reserved):暂时不用的位。

  • 长度(Length):标识选项的长度。

  • 可变长度选项(Variable length options):这些选项是可扩展的,以 TLV(Type-Length-Value)格式存在,可以根据需要添加额外的信息。

6. 原始帧(Original Frame)

  • L2、L3、L4 头部(L2, L3, L4 Headers):这是原始数据帧的头部,包括以太网、IP 和传输层的头部信息。在传输过程中,这些头部信息保持不变。

  • L5 应用数据(L5 Application Data):这是原始数据帧的负载部分,也就是实际要传输的数据。


用一个快递包裹来比喻

想象一下,你寄一个快递包裹:

  1. 外层 L2:就像是包裹的外包装,上面有收件人和寄件人的地址。

  2. 外层 L3:就像是包裹的运输方式,比如用飞机还是火车。

  3. 外层 L4:就像是包裹的运输服务提供商,比如顺丰、圆通。

  4. GENEVE 基础头部:就像是包裹的内部标签,上面有包裹的详细信息,比如包裹的编号(VNI)。

  5. GENEVE 选项:就像是包裹的附加信息,比如是否需要保价、是否需要加急等。

  6. 原始帧:就像是包裹里的东西,比如你寄的书、衣服等,这些在运输过程中不会改变。

GENEVE 头部格式

GENEVE 头部基于 UDP,它继续使用标准的 IP 作为底层传输协议,并支持多种封装协议。这意味着 GENEVE 可以在现有的网络基础设施上运行,同时还能灵活地支持未来可能出现的新协议。

可选字段的扩展性

GENEVE 的一个关键特性是它支持头部的可选字段。这些可选字段以 TLV(Type-Length-Value)格式存在,允许在头部中添加额外的元数据。这种设计使得 GENEVE 能够在未来轻松扩展,支持更多的功能和特性。例如,你可以添加新的字段来支持更复杂的网络策略、服务质量(QoS)控制,或者用于调试和监控的额外信息。

GENEVE 头部的关键字段

GENEVE 头部包含以下关键字段:

  • 24 位 Datapath ID:这是一个唯一的标识符,用于标识 GENEVE 隧道的路径。它可以用来区分不同的虚拟网络,确保数据包在正确的路径上传输。

  • 15 位 ingress port(入端口):这个字段标识数据包进入虚拟网络的端口。在 OpenStack 的 OVN(Open Virtual Network)中,这个字段非常重要,因为它允许 OVN 实现安全组规则。通过记录数据包的入口点,OVN 可以决定是否允许数据包进入虚拟网络。

  • 16 位 egress port(出端口):这个字段标识数据包离开虚拟网络的端口。同样,在 OVN 中,这个字段用于实现安全组规则。通过记录数据包的出口点,OVN 可以决定是否允许数据包离开虚拟网络。

为什么这些字段很重要?

在 VXLAN 和 GRE 这样的传统隧道协议中,没有专门的字段来标识数据包的入口和出口点。这使得在这些协议中实现 OpenStack 安全组规则变得非常困难。安全组规则需要知道数据包是从哪里进入网络的,以及它将从哪里离开网络,以便决定是否允许这些数据包通过。

而 GENEVE 通过引入 ingress port 和 egress port 字段,为 OVN 提供了实现安全组规则的能力。OVN 可以根据这些字段来检查数据包的来源和去向,从而决定是否允许数据包通过。这使得 GENEVE 在支持 OpenStack 安全组规则方面比 VXLAN 和 GRE 更强大。

用一个例子来说明

假设你有一个虚拟机网络,其中包含多个虚拟机。你希望某些虚拟机只能接收来自特定虚拟机的数据包,而其他虚拟机的数据包则被阻止。在 VXLAN 或 GRE 中,实现这样的规则会非常复杂,因为它们没有足够的信息来区分数据包的来源和去向。

但在 GENEVE 中,OVN 可以利用 ingress port 和 egress port 字段来实现这些规则。当一个数据包进入虚拟网络时,OVN 会检查 ingress port 字段,确定数据包是从哪里进入的。然后,当数据包准备离开虚拟网络时,OVN 会检查 egress port 字段,确定数据包将从哪里离开。通过这些信息,OVN 可以决定是否允许数据包通过,从而实现安全组规则。

查询GENEVE设置

在租户网络 VLAN20 中,我们可以看到 GENEVE 流量。每个 GENEVE 隧道都有一个唯一的 VNI(VXLAN Network Identifier)。在我们这个例子中,隧道的 ID 是 0x3。

具体来说:

  • 172.24.2.2.35614 这个地址对应的是 compute0(计算节点 0)。

  • 172.24.2.12.6081 这个地址对应的是 compute1(计算节点 1)。

这两个地址都是 GENEVE 隧道的端点地址。它们用来标识数据包在隧道中的传输路径。

另外,192.168.1.X 子网中的 IP 地址代表的是同一个 OpenStack 网络中的两个虚拟机实例。这些虚拟机实例通过 GENEVE 隧道进行通信,而 GENEVE 隧道的 VNI(0x3)确保了这些流量属于同一个虚拟网络 VLAN20。

1
2
3
8e:43:4c:8b:d8:cf > 76:3a:02:69:82:1e, ethertype IPv4 (0x0800), length 156: 172.24.2.2.35614 > 172.24.2.12.6081: Geneve, Flags [C],     vni 0x3, proto TEB (0x6558), options [8 bytes]: fa:16:3e:b5:fd:da > fa:16:3e:ec:5f:e0, ethertype IPv4 (0x0800), length 98: 192.168.1.11 > 192.168.1.12: ICMP echo request, id 1211, seq 1, length 64

76:3a:02:69:82:1e > 8e:43:4c:8b:d8:cf, ethertype IPv4 (0x0800), length 156: 172.24.2.12.23252 > 172.24.2.2.6081: Geneve, Flags [C], vni 0x3, proto TEB (0x6558), options [8 bytes]: fa:16:3e:ec:5f:e0 > fa:16:3e:b5:fd:da, ethertype IPv4 (0x0800), length 98: 192.168.1.12 > 192.168.1.11: ICMP echo reply, id 1211, seq 1, length 64

查询GENEVE 端⼝

在 controller 上,使⽤ ovs-vsctl 命令列出 br-int 的配置。注意不同的 ovn- 端⼝。IP 地址与课堂环境中的三个计算节点匹配。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[root@controller0 ~]# ovs-vsctl show
da52b817-899b-459f-b486-b529fcbd9275
Bridge br-prov2
fail_mode: standalone
Port eth4
Interface eth4
Port br-prov2
Interface br-prov2
type: internal
Bridge br-int
Port br-int
Interface br-int
type: internal
Port ovn-8e0b99-0
Interface ovn-8e0b99-0
type: geneve
options: {csum="true", key=flow, remote_ip="172.24.2.2"}
Port o-hm0
Interface o-hm0
type: internal
Port ovn-3f678a-0
Interface ovn-3f678a-0
type: geneve
options: {csum="true", key=flow, remote_ip="172.24.2.6"}
Port ovn-b8bd46-0
Interface ovn-b8bd46-0
type: geneve
options: {csum="true", key=flow, remote_ip="172.24.2.12"}