ML2: 分层端口绑定¶
Launchpad蓝图
https://blueprints.launchpad.net/neutron/+spec/ml2-hierarchical-port-binding
此蓝图扩展了 ML2 端口绑定,以支持分层网络拓扑。
致审阅者:一个类似的蓝图已被接受用于 Juno 版本并成功实施,但审阅在周期结束前完成得不够早,导致代码无法合并。 此规范已得到重大更新,以反映实施期间和响应审阅意见所做的决定,并以提高可理解性为目标。 它描述了 Juno 期间审阅的代码的最终状态。 除了重新定位代码外,先前审阅的代码无需进行重大更改。
问题描述¶
ML2 插件不能充分支持分层网络拓扑。 分层虚拟网络在不同级别使用不同的网络段,这些网络段可能具有不同的类型(VLAN、VXLAN、GRE、专有织网等)。 它可能由一个或多个顶级静态网络段以及较低级别的动态分配网络段组成。 例如,ToR 和核心交换机之间的虚拟网络流量可以使用 VXLAN 段进行封装,而相同虚拟网络在 ToR 交换机和计算节点之间的流量可以使用动态分配的 VLAN 段。
+-------------+
| |
| Core Switch |
| |
+---+-----+---+
VXLAN | | VXLAN
+-----------+ +------------+
| |
+------+-----+ +------+-----+
| | | |
| ToR Switch | | ToR Switch |
| | | |
+---+---+----+ +---+----+---+
VLAN | | VLAN VLAN | | VLAN
+-------+ +----+ +----+ +------+
| | | |
+----+----+ +----+----+ +----+----+ +----+----+
| | | | | | | |
| Compute | | Compute | | Compute | | Compute |
| Node | | Node | | Node | | Node |
| | | | | | | |
+---------+ +---------+ +---------+ +---------+
在分层结构的较低级别动态分配段对于允许 Neutron 部署扩展到每个物理网络 4K VLAN 的限制之外至关重要。 VLAN 分配可以在分层的较低级别进行管理,从而允许存在更多的 4K 虚拟网络,并且可以作为 VLAN 供计算节点访问,只要从 ToR 交换机到计算节点的每个链路同时不需要超过 4K 个 VLAN。
在 Juno 期间,支持分配动态段已合并到 ML2 中。 但是,目前没有办法让一个支持 ToR 交换机的机制驱动程序分配这些动态段,并由支持计算节点上的 L2 代理的另一个机制驱动程序使用。 所需的是初始机制驱动程序能够部分绑定到端口虚拟网络的静态段,并提供可以由下一级别的不同机制驱动程序绑定的动态段,直到绑定完成为止。
请注意,上面的图显示了连接 ToR 和核心交换机的静态 VXLAN 段,但这很可能不是当前“vxlan”network_type,其中隧道端点通过 Neutron 服务器和 L2 代理之间的 RPC 进行管理。 相反,它将是特定于封装格式和交换机之间管理隧道端点方式的 network_type。 每个 network_type 值都应标识明确定义的标准或专有协议,从而在需要时实现互操作性,并在异构部署中实现共存。
提议的变更¶
ML2 将通过在分层结构的每个级别将端口绑定到机制驱动程序和网络段来支持分层网络拓扑。 例如,一个机制驱动程序可以绑定到网络的静态 VXLAN 段,导致 ToR 交换机将该网络桥接到连接到该交换机的计算节点上的动态分配 VLAN,而第二个机制驱动程序(例如现有的 OVS 或 HyperV 驱动程序)将计算节点绑定到该动态 VLAN。
支持分层网络拓扑会影响 ML2 驱动程序 API 和 ML2 的端口绑定数据模型,但不会以任何方式更改 Neutron 的 REST API。
将向驱动程序 API 中的 PortContext 类添加一个新函数和属性,以启用分层端口绑定。
class PortContext(object):
# ...
@abc.abstractmethod
def continue_binding(self, segment_id, next_segments_to_bind):
pass
@abc.abstractproperty
def segments_to_bind(self):
pass
新的 continue_binding() 方法可以从机制驱动程序的 bind_port() 方法中调用,作为替代现有的 set_binding() 方法。 与目前的情况一样,如果机制驱动程序可以完成绑定,它会调用 PortContext.set_binding(segment_id, vif_type, vif_details, status)。 如果机制驱动程序只能部分建立绑定,它将改为调用 continue_binding(segment_id, next_segments_to_bind)。 如果机制驱动程序根本无法绑定,它将直接返回,而不调用这两个方法中的任何一个。
与 set_binding() 一样,传递给 continue_binding() 的 segment_id 指示该驱动程序正在绑定到的段。 new_segments 参数指定下一阶段绑定端口可以使用的网络段集合。 它通常包含下一个驱动程序将用于继续或完成绑定的动态分配段。
当前,机制驱动程序尝试使用 PortContext.network.network_segments 属性中的段进行绑定。 这些是网络的静态段。 现在所有驱动程序都应使用新的 PortContext.segments_to_bind 属性。 对于绑定的初始阶段,它将包含与 PortContext.network.network_segments 相同的段。 但对于后续阶段,它将包含作为 next_segments_to_bind 传递给 PortContext.continue_binding() 的段。
ML2 插件当前尝试使用以机制_驱动程序配置变量中指定的顺序注册的所有机制驱动程序进行绑定。 为了支持分层绑定,只需要进行一个小小的更改,以避免在配置错误或行为不端的部署中出现任何绑定循环。 在绑定的每个阶段,任何已经使用当前级别的一组绑定段在较高级别绑定的驱动程序都会被排除在外。 这种方法允许相同的驱动程序在分层网络的多个级别使用不同的段进行部分绑定,但不能使用相同的段。 此外,如果超过了绑定级别的总数限制,则绑定将失败并记录错误。
最后,为了使机制驱动程序能够查看分层(以及正常)绑定的详细信息,PortContext 的 bound_segment、original_bound_segment、bound_driver 和 original_bound_driver 属性将被一组新的属性替换
class PortContext(object):
# ...
@abc.abstractproperty
def binding_levels(self):
@abc.abstractproperty
def original_binding_levels(self):
@abc.abstractproperty
def top_bound_segment(self):
@abc.abstractproperty
def original_top_bound_segment(self):
@abc.abstractproperty
def bottom_bound_segment(self):
@abc.abstractproperty
def original_bottom_bound_segment(self):
binding_levels 和 original_binding_levels 属性返回一个字典列表,描述每个绑定级别(如果端口已完全或部分绑定)。 定义了 BOUND_DRIVER 和 BOUND_SEGMENT 键,并且如果需要,可以在未来版本中添加其他键。 第一条目描述了顶级绑定,该绑定始终涉及端口网络的静态段之一。 完全绑定时,最后一条目描述了提供端口的 binding:vif_type 和 binding:vif_details 属性值的底层绑定。
在存在分层绑定时,一些使用旧的 bound_segment、original_bound_segment、bound_driver 和/或 original_bound_driver 属性的机制驱动程序需要访问顶级绑定,而其他驱动程序需要访问底层绑定。 因此,旧属性将被一组新的属性替换,这些属性提供对每个属性的访问权限。
数据模型影响¶
为了存储多个绑定级别的信息供机制驱动程序访问,需要对 ML2 数据库模式进行更改。 driver 和 segment 列将从现有的 ml2_port_bindings 和 ml2_dvr_port_bindings 表移动到新的 ml2_port_binding_levels 表。 该表将具有 port_id、host 和 level 列作为主键。 不需要单独的 DVR 特定表。
将提供一个 DB 迁移,该迁移将在升级时将现有的绑定数据移动到新表。 降级将保留现有的单层绑定数据,但无法合理地保留现有的多层绑定数据进行降级。
REST API 影响¶
此规范中没有提出任何 REST API 更改。
使用现有的 providernet 和 multiprovidernet API 扩展,只能访问网络的顶级静态段。 目前不需要通过 REST API 公开动态段。 如果需要,可以将 portbindings 扩展修改为将来公开有关多层绑定的更多信息。
随着特定网络织网技术的机制驱动程序开发,可能会定义新的 network_type 值,这些值将通过 providernet 和 multiprovidernet 扩展可见。 但此 BP 中没有引入新的 network_type 值。
安全影响¶
无。
通知影响¶
无。
其他最终用户影响¶
分层网络拓扑应使 OpenStack 部署扩展到更多的网络。
性能影响¶
分层网络拓扑可以通过利用低开销的封装技术(例如在计算节点级别使用 VLAN),同时专业网络交换机处理扩展到非常多的网络所需的更高级的封装来提高租户网络吞吐量。
IPv6 影响¶
没有影响,因为此蓝图位于第二层。
其他部署者影响¶
在部署非分层网络拓扑时无需更改。 在部署分层网络拓扑时,需要配置额外的机制驱动程序。 此外,当 VLAN 用于底层绑定时,L2 代理配置会受到影响,如下面几段所述。
机制驱动程序通过查看 network_type 和任何其他相关信息来确定它们是否可以绑定到网络段。 例如,如果 network_type 是“flat”或“vlan”,则 L2 代理机制驱动程序会查看 physical_network,并使用 agents_db 信息,确保该主机上的 L2 代理具有该段的 physical_network 的映射。 这是现有机制驱动程序的工作方式,并且此 BP 不会更改它。
使用分层端口绑定时,ToR 交换机使用动态 VLAN 段,而连接到它的主机使用标准 L2 代理,主机上的 L2 代理将配置为 physical_network 名称的映射,该名称对应于交换机分配动态 VLAN 的范围。
如果动态 VLAN 段在交换机范围内分配,则每个 ToR 交换机应具有唯一的相应 physical_network 名称。 交换机的机制驱动程序将在其创建的动态段中将此 physical_network 名称用于部分绑定。 连接到该交换机的主机上的 L2 代理必须具有相同 physical_network 名称的映射(桥接或接口),从而允许任何正常的 L2 代理机制驱动程序完成绑定。
如果动态 VLAN 段改为在交换机端口范围内分配,则每个交换机端口将具有相应的唯一 physical_network 名称,并且只有连接到该端口的主机才应具有该 physical_network 的映射。
由于多层网络部署通常涉及特定供应商的专有交换机,因此该供应商应提供文档和部署工具来帮助管理员。
开发人员影响¶
支持分层绑定的机制驱动程序将使用额外的驱动程序 API 调用。 其他驱动程序只需要进行一个小小的更新,即可使用 PortContext.segments_to_bind 代替 PortContext.network.network_segments,以及用于访问顶级或底层绑定段或驱动程序的新属性。
社区影响¶
此更改为 ML2 机制驱动程序提供了支持分层网络拓扑的新功能。 这支持社区对允许 Neutron 扩展到更大的部署的兴趣。 它已经在 ML2 子团队会议以及 Juno 和 Kilo 会议上进行了讨论。
备选方案¶
另一种选择是让需要支持分层网络拓扑的供应商通过单体插件而不是 ML2 来实现,或者通过需要定制 L2 代理的 ML2 机制驱动程序来实现。
实现¶
负责人¶
- 主要负责人
rkukura
- 其他贡献者
asomya
工作项¶
与 Juno 期间所做的一样,实施将由一系列三个补丁组成
驱动程序 API 的更改
DB 模式的更改
绑定逻辑的更改
依赖项¶
使用此功能需要 Juno 期间合并的动态段功能。
测试¶
单元测试将验证所有新的驱动程序 API 方法和属性,以及使用测试机制驱动程序可以建立分层端口绑定。 使用所需的交换机硬件在相应的第三方 CI 中将测试使用分层绑定的实际机制驱动程序。
Tempest 测试¶
由于没有应用程序级别的行为变化,因此不需要新的 tempest 测试。 使用现有的 tempest 测试的第三方 CI 测试将充分行使分层端口绑定功能。
功能测试¶
由于没有系统级别的交互无法在单元测试中进行测试,因此不需要新的功能测试。
API 测试¶
没有要测试的 REST API 更改。
文档影响¶
部署程序文档是提供建立分层绑定的机制驱动程序的第三方责任。
用户文档¶
不需要用户文档更改。
开发人员文档¶
主要的开发人员文档来自驱动程序 API 源代码文件中的文档字符串,这些字符串详细描述了 API 及其行为。 如果将来编写 ML2 驱动程序指南,则需要涵盖分层端口绑定。
参考资料¶
无。