Openvswitch Agent 的分布式 DHCP

RFE: https://bugs.launchpad.net/neutron/+bug/1900934

Neutron DHCP 代理和计划的网络实例功能相对简单。但配置复杂,并且依赖于外部进程(dnsmasq)和命名空间。当用户的需求仅仅是唯一性时,例如,他们只需要在虚拟机启动过程中响应 DHCP 请求,那么现有的 DHCP 代理及其网络和端口配置过程会使事情变得复杂。

本文档描述了如何为 Neutron openvswitch 代理实现一个 DHCP 扩展,通过利用 openvswitch 的 openflow 来实现一个简单高效的虚拟机 DHCP 功能。

问题描述

响应 DHCP 请求是 DHCP 代理计划网络实例的主要功能。除此之外,它还有其他功能,例如隔离的元数据和 DNS 查找。但这些扩展功能有替代方案,例如 config drive 用于元数据,Designate 用于 DNS。

因此,DHCP 代理及其计划实例的使用频率相对较低。如果未进行 DNS 查找,它仅在 VM 启动期间使用。如果您使用 config drive,则计划的 DHCP 实例也无用。

对于大型集群,我们还有更多问题

  • DHCP 端口的计划网络实例增加了 L2 代理的容量和性能消耗。

  • DHCP 配置阻塞有时会导致虚拟机启动失败。

  • 由于未知原因的全量同步导致消息队列、neutron-server 和 DB 负载过高。

  • 为计划的 DHCP 端口创建 DVR 本地路由器是默认行为,这隐式地增加了 L2 和 L3 代理的资源负载 [1]

  • DHCP 节点宕机会导致长时间恢复,因为它具有大量的计划网络实例。

很难找到 应该部署多少 DHCP 代理单个代理可以处理多少 资源 之间的平衡。DHCP 代理太少最终会导致每个代理拥有大量的资源。DHCP 代理太多会增加运营商的维护压力,并使集中式组件过载。

有一种方法是将一个网络调度到所有计算节点上的所有 DHCP 代理。首先,这对于资源极少的微型部署可能有效。对于大规模部署,这基本上是不可能的。因为 Neutron 中会有数万个网络,这将直接导致每个节点上的资源压力激增,消耗用户网络中的过多 IP,结果基本上是无法运行,虚拟机启动失败以及无法获取 IP 等。

提议的变更

将添加一个新的 Neutron openvswitch 代理扩展来实现 分布式 DHCP

注意

此扩展仅适用于 openvswitch 代理,将不会考虑其他机制驱动程序,因为此新扩展将依赖于 openflow 协议和原理。对于 OVN,它已经支持了类似的 DHCP 本地响应机制。

提出的解决方案

如我们所知,Neutron openvswitch 代理拥有连接到 ovs bridge 的端口的全部信息(如果端口信息未由 ovs-agent 同步,则有一个简单的缓存拉取机制将填充信息)。Neutron 具有支持本机分布式 DHCP 的所有条件

  • ovs-agent 基于 python SDN 控制器 ryu/os-ken

  • ovs-agent 是完全分布式的

  • ovs-agent 拥有全部资源信息

因此,我们可以假设 Neutron openvswitch 代理是一个本地 SDN 控制器,它将尝试响应 VM 的 DHCP 请求。基本数据管道可以描述如下

                        +---------+                +---------------------+
+-------+ DHCP Request  |         |    packet-in   |  +----------------+ |
|  VM   +--------------->  Flows  +---------------->  |   os-ken app   | |
|       <---------------+         <----------------+  |                | |
+-------+ DHCP Response |         |    packet-out  |  | DHCP Responder | |
                        |         |                |  +----------------+ |
                        | br-int  |                |      OVS-agent      |
                        +---------+                +---------------------+

之后我们将拥有

  • 比具有其计划 dnsmasq 的 DHCP 代理更高的可用性,DHCP 请求直接在计算节点中处理,它是完全分布式的。

  • 不再需要 DHCP 代理及其调度机制

  • 不再需要额外的 DHCP 外部进程

  • (Neutron openvswith)代理停机时间将不再影响其他节点上的地址获取和虚拟机启动。

  • 虚拟机启动将不再受端口的 DHCP 配置影响,从而降低了 VM 生成失败的可能性。

  • VM 的 DHCP 请求和响应将实现很高的成功率。

DHCP(v4/v6) 协议选项

我们不会详细重复 DHCPv4 [2] 和 DHCPv6 [3]。但对于本文档,我们将确保相关协议的以下功能

  • DHCPv4 所有消息类型

  • DHCPv4 主机配置

  • DHCPv6 类型 Solicit、Advertise、Confirm、Renew、Rebind、Release 和 Reply

  • DHCPv6 选项

对于 Neutron,我们有一些端口属性,例如 dns_domain、dns_name 和 extra_dhcp_opts,以及子网 dns_nameservers、host_routes 和 gateway_ip 等,所有这些选项都将添加到最终的 DHCP 响应中,就像 dnsmasq 一样。

服务器端变更

基于新添加的配置选项,一些 DHCP 相关的 DB 选项、API、通知和 RPC 将更改为无操作或被跳过。配置选项仅控制 Neutron 本身,DHCP 协议将不会影响。最终目标是支持定义的 DHCP 协议的全部功能。更改如下

  • 永久禁用 DHCP 调度机制及其故障转移

  • 禁用 DHCP 配置阻塞

  • 禁用 DHCP 相关的 RPC 和通知

OpenvSwitch Agent 侧的更改

对于 Neutron openvswitch 代理,我们将添加一个新的代理扩展,它将处理每个端口进一步 DHCP 请求的基本流安装。

将有两个基本流将 DHCPv4 和 DHCPv6 指导到独立的表。table 77 用于 DHCPv4,table 78 用于 DHCPv6。这些流是

table=60, priority=101,udp,nw_dst=255.255.255.255,tp_src=68,tp_dst=67 actions=resubmit(,77)
table=60, priority=101,udp6,ipv6_dst=ff02::1:2,tp_src=546,tp_dst=547 actions=resubmit(,78)

对于表 77,每个 DHCP 请求都将检查以验证源 MAC 和 in_port,以避免 DHCP 欺骗。如果 DHCP 请求匹配,则将其提交给控制器,即 Neutron openvswitch 代理。任何不匹配的数据包将被丢弃。一个 VM 端口的示例是

table=77, priority=100,udp,in_port="tapcc4f2da4-c5",dl_src=fa:16:3e:46:58:fe,tp_src=68,tp_dst=67 actions=CONTROLLER:0
table=77, priority=0 actions=drop

对于表 78,DHCPv6 匹配和丢弃流的结构基本上与 DHCPv4 相同

table=78, priority=100,udp6,in_port="tapcc4f2da4-c5",dl_src=fa:16:3e:46:58:fe,tp_src=546,tp_dst=547 actions=CONTROLLER:0
table=78, priority=0 actions=drop

对于 openvswitch 代理的新扩展,它将添加一个本地 packet_in_handler,它将执行以下工作

  • 监听 EventOFPPacketIn 事件

  • 验证每个数据包是 DHCPv4 还是 DHCPv6

  • 根据 openflow inport 号检索端口的信息

  • 组装 DHCP(v4/v6) 响应和 packet_outin_port

响应 DHCP 数据包的结构将是

+------------------------------------------+
|           *Source Mac Address            |
|The gateway Port's MAC or A fake fixed MAC|
+------------------------------------------+
|       *Destination Mac Address           |
|        Neutron Port Mac Address          |
+------------------------------------------+
|           *Source IP Address             |
|      Gateway IP address from Subnet      |
+------------------------------------------+
|         *Destination IP address          |
|             Neutron Port IP              |
+------------------------------------------+
  • Mac 地址 将是内部子网网关端口的 Mac 地址。但实际上,这对于 DHCP 协议来说不是必需的,我们可以使用假的固定 MAC 地址来避免一些 DB/RPC 查询。

  • 目标 Mac 地址 将是端口的 MAC。

  • IP 地址 将是内部子网的网关 IP。

  • 目标 IP 地址 将是端口的第一个 IP(v4/v6) 地址,将忽略辅助 IP。

潜在的配置

将为 neutron server 端添加配置选项 disable_traditional_dhcp,旨在控制

  • 禁用网络的 DHCP 调度

  • 禁用 DHCP 配置阻塞

  • 禁用 DHCP RPC/通知

  • 禁用网络、子网和端口的所有 DHCP 相关 API/属性。

将为 neutron openvswitch 代理添加一个新的扩展别名 dhcp

[agent]
extensions = ...,dhcp

将为 neutron openvswitch 代理添加配置部分 [dhcp] 并注册一些常见选项以确定 DHCP 协议相关参数,最终的 [dhcp] 部分对于 openvswitch 代理将是

dhcp_opts = [
  cfg.BoolOpt('enable_dhcp_ipv6', default=False,
              help=_("Whether enable DHCP for IPv6")),
  cfg.IntOpt('dhcp_renewal_time', default=0,
             help=_("DHCP renewal time T1 (in seconds). If set to 0, it "
                    "will default to half of the lease time.")),
  cfg.IntOpt('dhcp_rebinding_time', default=0,
             help=_("DHCP rebinding time T2 (in seconds). If set to 0, it "
                    "will default to 7/8 of the lease time.")),
]

Neutron 基本工作流程

  1. 用户在网络中创建 VM

  2. Nova 将 VM 的 NIC 端口连接到 ovs-bridge

  3. Ovs-agent 处理端口并安装 DHCP 相关流

  4. L2 配置阻塞释放(无 DHCP 配置阻塞)

  5. VM 启动并发送 DHCP 请求

  6. 匹配流并 packet_in 到 ovs-agent

  7. Ovs-agent 直接将 DHCP(v4/v6) 响应发送到 VM 的端口

  8. VM 启动成功

数据模型影响

REST API 影响

使用新的配置选项,将禁用以下 API [4]

  • add_network_to_dhcp_agent

  • remove_network_from_dhcp_agent

  • list_networks_on_dhcp_agent

  • list_dhcp_agents_hosting_network

对于 Subnet 的选项 enable_dhcp,此代理扩展将基于该选项设置流。如果为 False,则此子网下的端口将不会在表 77 和 78 中安装任何流。DHCP 请求将命中最终的 DROP 操作。

升级

对于本机 ml2/ovs 部署,这将很容易升级以强制执行。一种简单的方法是像以前一样运行所有代理。但禁用 DHCP 配置阻塞。启用 ovs-agent 的 dhcp 扩展后,DHCP 请求将比 dnsmasq 更早地由它处理。

如果您需要一个纯部署而没有 DHCP 代理,以下是关于如何迁移到使用此新功能的概述

  • 升级 Neutron 代码并重新启动 neutron-server 进程。

  • 使用 dhcp 扩展设置 ovs-agent。

  • 禁用所有 DHCP 代理以确保不再创建计划的网络。

openstack network agent set --disable <dhcp_agent_id>

注意

此操作将从管理状态 DOWN DHCP 代理中删除所有计划的网络实例。

  • 设置 disable_traditional_dhcp = True 选项用于 neutron-server 以禁用相关的 API/RPC。

  • (可选,以防万一) 删除所有 DHCP 代理中的计划网络,此步骤是为了清除所有 DHCP 命名空间和 DHCP 工作进程 dnsmasq

  • 在没有更多计划的网络后,停止所有 DHCP 代理并将其从 DB 中删除。

注意

此功能不支持 DNS 查找。如果您的运行部署正在使用 dnsmasq 的 DNS 查找功能,请考虑使用 designate 作为替代方案。

实现

负责人

工作项

  • 用于控制 DHCP 相关代码的 neutron server 的配置选项。

  • 创建代理扩展。

  • 测试。

  • 文档。

依赖项

测试

功能

我们将添加全栈测试用例来验证这个新的代理扩展

  • 在两个测试命名空间中创建两个假的完整栈 VM

  • 使用 DHCP(v4 和 v6) 配置假的 VM 端口

  • 从一个假 VM 到另一个 VM 乒 (-4/6)

参考资料