MTU 选择和广播¶
https://blueprints.launchpad.net/neutron/+spec/mtu-selection-and-advertisement
本文档提出了一系列修复 Openstack MTU 问题的方案,以确保虚拟机在 Openstack 的虚拟和物理网络上以正确的 MTU 运行。
问题描述¶
简而言之:您的 Neutron 网络的任何 L3 封装的 MTU 很可能不是 1500 字节。这会导致各种各样的潜在问题,详见下文,虽然存在现有的解决方法,但它们在各种部署类型中都无法正常工作,可能包括您当前正在使用的部署类型。如果您愿意接受这一点,请跳到下一节。
Neutron 网络具有不可预测的 MTU,这会导致大量的边缘情况行为。
在所有接口上 MTU 均为 1500 字节(典型默认值)的机器上运行的租户网络的 MTU 可能是,在其他值中
1500 字节,如果使用的封装机制是 VLAN,或者网络是扁平网络。请注意,无论您首选的封装类型如何,这两种情况之一都适用于您所有的外部连接网络
1492 字节,如果使用的封装机制是 GRE 隧道。请注意,这意味着路由器一侧的租户网络与另一侧的外部网络 MTU 不同
更小,如果封装是其他 L3 类型,例如 VXLAN
更大,如果云已部署在使用的巨型帧基础设施上
如果超过了最大传输单元大小,数据包将被丢弃,要么在网络上(如果网络无法传递发送方期望发送的那么大的流量),要么在目的地(如果目的地的配置 MTU 小于发送方或网络的 MTU)。实际上,这意味着发送方和接收方——无论是虚拟机、服务还是路由器——必须就 MTU 大小达成一致,并且网络段必须能够传递约定的尺寸的数据包。
此外,请注意,L3 机制用于路径 MTU 发现仅发生在通过 L3 元素(例如路由器)的数据包上。它们不发生在传输 L2 段的流量上,这意味着大型数据包在发送方不知情的情况下被丢弃。这导致不同传输类型之间行为不一致:通常,数据的大批量传输不起作用,但某些连接(例如小的 HTTP 请求)可以工作。
除了段将传递的绝对最大传输单元的大小之外,通常还有一个首选的传输单元大小。某些隧道协议允许在封装后对数据包进行分片,这意味着如果超过了某个传输单元大小,封装的数据包将进行分片,虽然数据包到达了,但网络性能会急剧下降。
最后,MTU 在段的不同端点之间经常不一致。在同一主机上的两个虚拟机之间,通常能够使用比不同主机上的两个虚拟机更大的传输单元进行通信。该段的 MTU 应该是任何主机对之间有效工作的最小值,但事实并非总是如此。
一种推荐且广泛部署的解决方法是向所有虚拟机通过 DHCP 广播一个功能性的小于 1500 的 MTU,只要
DHCP MTU 广播被尊重
没有正在运行的提供商网络(因为它们的 MTU 大小通常为 1500 并且可能完全不同,而且无论如何虚拟机将无法与外部系统通信)
外部网络配置为在下一跳处使用小的 MTU
所有服务 MTU 也都已适当地配置。
这对于仅 IPv6 的虚拟机也不起作用——它们响应 RA 属性,而不是 DHCPv4,并且 RA 属性通常只能减少网络 MTU——或者对于根本不使用 IP 的偶尔出现的虚拟机。
有时,租户对他们想要的 MTU 也有自己的看法——要么它大于默认的 1500,或者,对于已经部署成可以使大 MTU 大小起作用的部署,他们仍然希望拥有 1500 MTU。
提议的变更¶
本文档提出将 MTU 操作统一起来,以便(按可取性顺序)
自动确定最佳 MTU
插件可以确保广播机制(例如 DHCP、RA、config drive)可以访问网络的正确 MTU,并在启用此功能时用于将其传播到客户机
插件可以确保连接到网络的网络服务使用正确的 MTU 运行(例如,路由器端口配置了适当的接口 MTU),以便即使在不同网络上的 MTU 大小不同时,正常的 L3 行为也能适应这种差异而不会破坏租户通信。
租户可以发现网络上的 MTU,以便——如果租户必须编写配置文件到 config drive 以指示虚拟机配置 MTU——它可以知道使用哪个 MTU 值。请注意,某些虚拟机不会请求 DHCPv4 MTU,RFC 的严格解读禁止虚拟机接受通过 IPv6 RA 的大型 MTU,并且目前没有 config drive 机制来广播 MTU,因此必须考虑到这种可能性
租户可以请求网络上的特定 MTU——这是为了,如果租户拥有预配置 MTU 的虚拟机(例如,那些不尊重任何可用的 MTU 广播形式的虚拟机,他们可以为具有这些虚拟机的网络请求特定的——通常为 1500——MTU)
插件可以确认它可以传递网络上的特定 MTU,如果已明确提出请求
对于给定的网络,Neutron 将在内部计算两个值。这些是
将有效工作的最大 MTU。这可能是未确定的(例如,如果封装进行分片)。
要使用的最佳 MTU。这可能是最大 MTU,也可能更小。大于此最佳 MTU 的数据包可能会看到降级的吞吐量,但如果它们小于最大 MTU,它们将被传递。
租户可以选择性地(在 Phase III 中;见下文)通过在 net-create 上设置“mtu”标志来为网络提出 MTU。所使用的插件有两个选项
它可以创建网络,将该网络的 MTU 设置为给定的尺寸(这意味着 L2 段将传递至少该尺寸的数据包;启动在该网络上的服务将具有与网络相同的 MTU;并且如果启用了广播,则广播的 MTU 是所选的 MTU)。网络上的“mtu”属性,存储在 DB 中并在网络对象上返回,将包含请求的 MTU。
如果 MTU 大于最大 MTU,它可以拒绝创建网络,因为无法满足 MTU 请求。或者,如果插件不支持 MTU 控制,Neutron 将拒绝该请求。这使我们能够使“mtu”接口核心,同时支持不识别它的插件。
如果未提供 MTU,则支持的插件将使用首选值。不支持的插件将使其不确定。
如果网络也标记为 VLAN 透明(如 VLAN 透明度规范中所述,尚未实现,在 [1] 处),则网络必须传递带有 MTU 尺寸或更小内容的 VLAN 标记数据包(这意味着 VLAN 标记之前的数据包内容必须小于 Neutron 网络上的 MTU 8 个字节)。这种区别在隧道协议(例如 GRE)中很重要——传统上,VLAN 标记不计入 MTU,但额外的标头字段计入 GRE 隧道有效负载,因此如果标记数据包可能通过隧道,则需要留出额外的空间。
Neutron 的一个配置项“advertise_mtu”,如果不存在则默认为 false(为了向后兼容),启用 MTU 广播。如果设置为 true,将启用各种 MTU 广播机制并配置为使用 MTU。广播列表包括
DHCPv4 将在客户机请求时使用“MTU”选项广播 MTU
由 Neutron 发送的 IPv6 RA 将包含 MTU(尽管,通常,客户机只有在特别配置的情况下才会尊重大于 1500 的 MTU 大小)
当有第三方支持时,将添加以下广播方法
cloud-init 文件将包含每个接口的接口 MTU。
如果关闭了广播,则确保其虚拟机具有适当 MTU 配置是 Openstack 应用程序的责任。
无论广播设置如何,Neutron 网络设备(例如路由器和高级服务设备)都将配置其接口为所选 MTU(如果 MTU 已知)。这意味着服务的插件机制理解并正确实施 MTU 设置。
对于广播到网络的任何给定的 MTU,插件必须确定,即使在底层网络拓扑发生变化(例如,故障转移到备份路径,或使用不同的封装类型,或在附加到网络的新的实例时从单主机设置切换到多主机设置),从任何端点传输的指定尺寸的数据包始终保证到达所有目的地。它的任务是确保 MTU 足够小,可以在所选基础设施上工作,包括主机间和主机内。
Openstack 网络通常具有用于(a)外部连接和(b)提供商网络使用的物理网络。这些网络可能具有与彼此相同的 MTU 大小,并且很可能具有与虚拟租户网络不同的 MTU 大小。物理网络的链路 MTU 由配置指定,并将用作这些段上提供商和外部网络的最大和首选 MTU 大小。
备选方案¶
解决此问题的常见解决方法是
使用 config,向 DHCP 添加一个选项以传播“安全”MTU 到所有虚拟机,并在各种(有些驱动程序特定的)config 参数中设置 MTU 以确保 L2 和 L3 网络元素正常工作。这对于 v4 有效,但对于 v6 无效,因为等效选项通常未设置;它不是完全可用的,因为路由器不知道其 MTU 不正确;并且它仅适用于实际支持 DHCP 的虚拟机。如果租户和提供商网络具有不同的 MTU,或者内部网络和外部网络,它也无法工作。
指导用户在文档中设置所有虚拟机中的“安全”MTU(以及相同的 config 选项调整)。这与上述相同,即虚拟机可能相互同意,但不同意路由器,这可能导致意外行为。它不适用于提供商网络或其他 Neutron 网络具有不同 MTU 的配置。
可以使用大型 MTU 接口并在网络组件(例如内核交换机和桥接器)上配置 MTU,但路由器并不总是正确配置的,并且提供商网络 MTU 通常不正确。
有一些 MTU 相关的配置变量,但它们是解决由于软件网络结构引起的 MTU 问题的解决方法。如果网络 MTU 是明确已知的,则不需要此配置,因为相关组件可以显式配置为虚拟网络的 MTU。
当驱动程序设置网络的 MTU 或租户提供它时,network_device_mtu 和 veth_mtu 的值将为该网络动态派生,并且任何配置值都将被忽略。
数据模型影响¶
将“mtu”(正整数)属性添加到网络的数据库模型中。这存储了确定的首选“mtu”值,除非用户覆盖。如果未确定,则将其存储为 NULL。如果为 NULL,广播机制将不会发送 MTU。
在 Phase I 中,mtu 存储在数据库中,但未通过 API 公开。它在 net-create 时设置为插件提供的首选 MTU(如果有),并读取以通过 DHCP 和 RA 提供广播。
在 Phase II 中,该项目对所有用户可见,作为只读属性。NULL 被视为未设置。
在 Phase III 中,该项目可以通过 API 写入,前提条件是管理员已在 policy.json 中显式启用它。它只能在 net-create 调用中设置,并传递给插件;ML2 将根据插件提供的 max-MTU 值对其进行验证,并拒绝任何过大的值。
REST API 影响¶
Phase II 仅
任何用户都可以从网络对象读取“mtu”属性。该值在网络的整个生命周期内是恒定的。
Phase III 仅
对于 net-create,“mtu”属性可以提供。它将根据插件内的最大计算 MTU 进行验证,并且如果太大可能会被拒绝。它的值在 net-create 之后是不可变的,因此 net-update 不应接受它。
安全影响¶
现在用户可以检测最大和首选 MTU 值,这可能存在一些可见性,但这本身并不是安全风险。应考虑这是否会削弱任何其他安全假设。
通知影响¶
无。
IPv6 影响¶
当启用广播时,RA 将携带 MTU。大于 1500 的 MTU 不会被符合 RFC 的虚拟机中的 IPv6 堆栈接受。Linux 虚拟机通常会在收到 RA 时接受它,如果它们的 MTU 大于 1500。应记录此信息。
其他最终用户影响¶
虚拟机现在可以通过 DHCPv4 和 IPv6 RA 接收 MTU 广播。
性能影响¶
MTU 的当前问题偶尔会导致当大型租户数据包通过隧道传输时网络性能非常低,其中隧道数据包大小超过隧道的 PMTU。正确的 MTU 行为应纠正此问题,特别是如果网络插件更喜欢创建不会导致数据包分片的 MTU 的网络。
不应使性能变差。
其他部署者影响¶
部署者可以提供三个新的配置变量
advertise_mtu - 默认值为 false,如果为 false,则与向后兼容;不会通过网络方法向虚拟机广播 MTU。如果为 true,当网络的首选 MTU 已知时,虚拟机将接收 DHCP 和 RA MTU 选项。
path_mtu - 对于 L3 机制驱动程序,确定从和到发送封装的 Neutron 流量的地址,可允许的最大未分片数据包大小。驱动程序应根据此值计算最大的可行 MTU,用于验证租户请求(通常为 path_mtu - 最大封装报头大小)。如果未提供,则 path MTU 是不确定的,并且不会进行任何计算(即,将拒绝所有需要它的驱动程序的 MTU 请求)。(请注意,path MTU 是指定的,而不是探测的,因为以编程方式确定两个端点之间最坏可能路径上的最小 MTU 是不可能的,只能确定当前正在使用的路径 MTU。)
segment_mtu - 对于 L2 机制驱动程序(例如 VLAN),确定 segment MTU。如果未提供,则 segment MTU 是不确定的,并且不会进行任何计算(即,将拒绝所有需要它的驱动程序的 MTU 请求)。(请注意,segment MTU 是从配置中确定的,而不是通过探测接口,因为多个接口可能参与一个网络段。)
此外,将在 ML2 配置中添加一个名为 physnet_mtus 的新属性,以适应可选的每个物理网络 MTU 设置。任何没有相应 physnet_mtus 设置的物理网络都将导致在为该物理网络进行 MTU 计算时使用全局 segment_mtu 值(如果 segment_mtu 未设置,则不进行任何计算)。
- 示例
physnet_mtus = physnet1:1550, physnet2:1500
- 或者,要为 physnet2 设置 MTU,并使 physnet1 保持默认值
physnet_mtus = physnet2:1550
这可用于声明物理网络的 MTU,包括外部网络和用于提供商网络的网络。
上述值意味着可以根据用于构建它的驱动程序或驱动程序计算特定网络可以传输的最大 MTU。
veth_mtu 属性先前用于配置用于构建 OVS 驱动程序网络元素的 veth 接口的 MTU。当设置网络 MTU 时,不再需要它。在这些情况下,它将被忽略,但如果无法计算网络 mtu(例如,如果需要且未设置路径或段 MTU),则将应用它。
network_device_mtu 之前用于配置连接到 Neutron 网络的命名空间中的接口的 MTU。在此更改之后,如果驱动程序(或租户)已设置网络的 MTU,现在将直接使用它。如果是不确定的,仍将使用 network_device_mtu。
开发人员影响¶
插件应添加对建议的 MTU 接口的支持。此蓝图不强制执行时间表,但为他们提供支持的设施。我们将更改至少 ML2 插件作为示例,以允许进行测试,但不保证为所有插件添加支持。
驱动程序应添加对建议的 MTU 接口的支持。我们将更改 OVS、LB、VLAN、VXLAN 和 GRE 驱动程序以添加支持。
社区影响¶
无。
实现¶
负责人¶
- 主要负责人
ijw-ubuntu
工作项¶
这项工作将分三个不同的阶段进行。
第一阶段将涉及创建机制,以允许在 ML2 插件以及 OVS、Linuxbridge、VLAN、GRE 和 VXLAN 驱动程序中计算合适的 MTU;将这些 MTU 广播给 VM;以及在服务的命名空间实现中使用这些 MTU(Neutron 路由器、DHCP、Metadata)。请注意,根据问题陈述,这确实需要每个网络的 MTU 值。 此时,将实施向后兼容机制,以便不支持 MTU 计算的驱动程序回退到其当前行为。
第二阶段将涉及启用网络对象上的只读“mtu”标志,以便在理解广播机制方面存在问题的 VM 可以配置为使用正确的 MTU。
第三阶段将涉及允许用户指定他们自己的 MTU 选择,根据驱动程序的允许值验证该 MTU,并适当地广播 MTU。这将首先作为实验代码完成,其中“mtu”广播将在 net-create 命令上获取一个值,但默认 policy.json 中禁用该值的实际写入。这允许感兴趣的各方使用该功能,而不会为大多数用户启用它。
对于 Kilo,必须完成第一阶段,第二阶段非常可取。第三阶段优先级较低。
第一阶段的任务如下
更改数据库中的数据模型,在网络上添加“mtu”标志,添加升级和降级脚本
更改配置文件读取器,以便可以理解 bridge-mappings 项目的新格式。
将 path_mtu、segment_mtu 和 advertise_mtu 属性添加到配置文件读取器
更改 OVS、LB、VLAN、GRE 和 VXLAN 驱动程序,以根据需要使用 bridge-mappings、path_mtu 和 segment_mtu,正确计算其最大和首选 MTU 值。
更改 ML2 插件,以根据网络中使用的驱动程序的功能,正确确定网络的最大和首选 MTU 值,并将该值存储在数据库中的网络对象上。
更正网络控制和插拔代码,以正确设置尊重它的所有软件网络元素的 MTU
将代码添加到 neutron 命名空间,以正确设置 MTU
如果网络上设置了 MTU,则从 DHCP 自动广播,并在启用 DHCP 时。
如果网络上设置了 MTU,则从 RA 自动广播,并在启用 RA 时。
第二阶段的任务如下
公开网络上 MTU 的只读标志
第三阶段的任务如下
在 net-create 上公开 MTU 的写入标志
根据驱动程序能够处理的最大 MTU 验证传递的值
更改核心 Neutron 代码,以拒绝在提供“mtu”并且插件不知道其最大 MTU 时创建网络。
依赖项¶
无。
测试¶
API 测试¶
第一阶段
无
第二阶段
测试新“mtu”属性的存在和值;确认只读;确认预期值
第三阶段
测试写入“mtu”属性;测试是否受到尊重;测试是否针对最大和首选 MTU 进行了正确验证
验证基于段 mtu 的 VLAN 的最大 MTU 是否针对租户网络正确计算,并且基于外部网络物理 MTU 的提供商网络正确计算。
验证基于外部桥接物理 MTU 的外部网络的最大 MTU 是否正确计算和使用。
验证物理 MTU 默认为 1500。
验证网络元素是否根据新的配置参数正确配置,并且旧的配置参数不再影响行为。
验证驱动程序和插件拒绝使用无法传输的过大 MTU 创建网络
功能测试¶
第一阶段
确认 VLAN、VXLAN、GRE、OVS 和 Linuxbridge 驱动程序正在从输入(配置参数 path_mtu、segment_mtu 和 physnet_mtus)正确计算其 MTU
确认使用上述驱动程序,ML2 正确计算用于各种网络类型(包括虚拟、提供商和外部网络)的 MTU
确认通过检查在启用 advertise_mtu 时在网络上使用的 dnsmasq 和 RADVD 配置,MTU 正在正确广播;确认在未设置 advertise_mtu 时未广播它
第二阶段
确认根据所选网络配置,网络上公开的“mtu”值是正确的,用于各种配置
第三阶段
确保在 MTU 已指定和未指定的网络一起使用时,正确应用 MTU 到所有元素。
Tempest 测试¶
Tempest 场景测试以确保
第一阶段
当启用广播时,可以跨网络传输和接收大小为该大小的数据包,网络中的 VM 识别广播类型
第二阶段
当 VM 在启动时手动配置为使用网络上看到的“mtu”值,并且禁用“advertise_mtu”时,可以跨网络传输和接收大小为该大小的数据包
第三阶段
可接受的 MTU 是可传输的
文档影响¶
用户文档¶
应记录新的“mtu”属性。应记录 DHCP 和 RA 的更改行为。
应记录新的“path_mtu”、“segment_mtu”和“advertise-mtu”选项。应弃用它们所取代的选项。
开发人员文档¶
插件和驱动程序设计文档应注意管理 MTU 的新功能。
参考资料¶
[1] https://blueprints.launchpad.net/neutron/+spec/nfv-vlan-trunks