修改 TripleO Ironic Inspector 以通过 DHCP 中继进行 PXE 启动

https://blueprints.launchpad.net/tripleo/+spec/tripleo-routed-networks-ironic-inspector

此蓝图是 tripleo-routed-networks-deployment 系列的一部分 [0]

此规范描述了向 Undercloud 添加功能,以支持 Ironic Inspector 为多个路由子网执行 PXE 启动服务(路由器上的 DHCP 中继转发请求)。支持此功能所需的更改将采用 undercloud.conf 的格式,以及编写 Ironic Inspector dnsmasq.conf 配置的 Puppet 脚本。

TripleO 使用 Ironic Inspector 对 overcloud 节点进行裸机检查,然后再进行部署。目前,Ironic Inspector 使用的 dnsmasq.conf 由在 Undercloud 配置时运行的 Puppet 脚本生成。单个子网和 IP 分配范围输入到 undercloud.conf 的参数 inspection_iprange 中。此规范将实现对一个配置网络中的多个子网的支持。

背景信息

有关所需拓扑和正在解决的问题的详细描述,请参考父蓝图 triplo-routed-networks-deployment [0]

问题描述

Ironic Inspector DHCP 尚未支持 DHCP 中继。这使得当主机不在与控制器相同的 L2 域中时,进行内省变得困难。dnsmasq 进程实际上可以在 DHCP 中继上运行,但必须手动编辑配置。

可能的解决方案、想法或方法

  1. 添加对 DHCP 范围和 DHCP 中继的支持。

  2. 使用远程 DHCP/PXE 启动,但提供返回到内省服务器的 L3 路由

  3. 使用 Neutron DHCP 代理来 PXE 启动节点进行内省(Neutron dhcp-agent 已经支持多个子网,并且可以修改以支持 DHCP 中继)。请注意,关于将 Ironic 内省迁移到 Neutron 的讨论在此处进行过 [3]。由于 Neutron 无法为未知的 MAC 地址分配 IP,因此目前不可行。相关的补丁已被放弃 [5]

解决方案实施

Ironic Inspector DHCP 服务器使用 dnsmasq,但仅配置一个子网。我们需要修改 Ironic Inspector DHCP 配置,以便可以为多个 Neutron 子网和分配池配置 DHCP。然后,我们应该可以使用 DHCP 中继将 DHCP 请求发送到 Ironic Inspector DHCP 服务器。从长远来看,我们可以利用 Neutron 中正在进行中的路由网络工作来表示将用于 DHCP 范围集以下的子网和分配池。此规范仅涵盖 TripleO 所需的最低限度,因此可以通过修改 Undercloud Puppet 脚本来实现工作。以下内容经过测试,并显示了跨两个子网的成功内省,一个本地子网,一个通过配置了 DHCP 中继的路由器。

Current dnsmasq.conf representing one network (172.20.0.0/24), which is
configured in the "inspection_iprange" in undercloud.conf:
  port=0
  interface=br-ctlplane
  bind-interfaces
  dhcp-range=172.21.0.100,172.21.0.120,29
  dhcp-sequential-ip
  dhcp-match=ipxe,175
  # Client is running iPXE; move to next stage of chainloading
  dhcp-boot=tag:ipxe,http://172.20.0.1:8088/inspector.ipxe
  dhcp-boot=undionly.kpxe,localhost.localdomain,172.20.0.1

Multiple-subnet dnsmasq.conf representing multiple subnets:
  port=0
  interface=br-ctlplane
  bind-interfaces
  # Ranges and options
  dhcp-range=172.21.0.100,172.21.0.120,29
  dhcp-range=set:leaf1,172.20.0.100,172.20.0.120,255.255.255.0,29
  dhcp-option=tag:leaf1,option:router,172.20.0.254
  dhcp-range=set:leaf2,172.19.0.100,172.19.0.120,255.255.255.0,29
  dhcp-option=tag:leaf2,option:router,172.19.0.254

  dhcp-sequential-ip
  dhcp-match=ipxe,175
  # Client is running iPXE; move to next stage of chainloading
  dhcp-boot=tag:ipxe,http://172.20.0.1:8088/inspector.ipxe
  dhcp-boot=undionly.kpxe,localhost.localdomain,172.20.0.1

在上述配置中,为所有子网提供了路由器,包括连接到 Undercloud 的子网。请注意,对于与检查器主机位于同一子网上的节点,路由器不是必需的,但如果它被自动生成,也不会有任何问题。

此文件由位于 [1] 的 Puppet 文件创建。更改必须在那里进行。

如上所述,使用远程 DHCP/PXE 服务器只有在我们在顶层交换机中具有支持的情况下,或者如果系统或 VM 正在远程子网上侦听以中继 DHCP 请求的情况下才可行。此 dnsmasq 配置将允许它向 DHCP 中继发送 DHCP 报价,DHCP 中继会将报价转发到请求主机。报价被接受后,主机可以直接与 Undercloud 通信,因为它已经接收到正确的网关地址,以便转发数据包。它将根据报价直接发送 DHCP 请求,并且 DHCP ACK 将直接从 Undercloud 发送到客户端。通过 TFTP 和 HTTP 下载 PXE 镜像,而不是通过 DHCP 中继。

另一个问题是 Ironic Inspector 会使用 iptables 规则阻止来自特定 MAC 地址的流量来阻止已经过内省的节点。由于通过 DHCP 中继中继的数据包将来自路由器的 MAC 地址(而不是发送数据包的原始 NIC),因此我们需要根据中继 DHCP 数据包的内容来阻止 MAC 地址。如果可能,这将使用 dnsmasq 完成,这将提供解码 DHCP Discover 数据包并对内容采取行动的能力。为了直接使用 dnsmasq 而不是使用 iptables 进行黑名单处理,我们需要能够影响 dnsmasq 配置文件。

提议的变更

以下讨论了拟议的更改。

概述

Puppet 模块需要重构,以便从 undercloud.conf 中的子网列表中输出多子网 dnsmasq.conf

需要更新黑名单功能。通过 MAC 地址过滤对于由路由器中继的 DHCP 请求不起作用。在这种情况下,源 MAC 地址将是发送中继请求的路由器接口。有几种方法可以在 dnsmasq 中阻止 MAC 地址,例如此配置

dhcp-mac=blacklist,<target MAC address>
dhcp-ignore=blacklist

或者此配置

# Never offer DHCP service to a machine whose Ethernet
# address is 11:22:33:44:55:66
dhcp-host=11:22:33:44:55:66,ignore

可以将配置放置在主 dnsmasq.conf 文件中,也可以放置在 /etc/dnsmasq.d/ 中的文件中。无论哪种方式,都需要重新启动 dnsmasq 才能重新读取配置文件。这是 dnsmasq 中的一项安全功能,可防止以 root 身份加载外部配置。由于 DHCP 具有内置的重试机制,因此重新启动 dnsmasq 的简短时间不应影响内省,只要我们不要在任何 60 秒的时间段内重新启动 dnsmasq 过多次。

似乎无法使用 dnsmasq DBus 接口为单个 MAC 地址设置“dhcp-ignore”选项 [4] [6]

替代方案

一种替代方法是在所有主机的所有接口上使用 DHCP 服务器分配 IP 地址。这将简化 Heat 模板和环境文件中的配置。不幸的是,这是 TripleO 的原始方法,并且被最终用户认为不足,他们希望 IP 地址稳定,并且不想对 DHCP 有外部依赖性。

另一个考虑的方法是简单地将所有网络回传到 Undercloud,以便 dnsmasq 可以直接响应 DHCP 请求,而不是需要 DHCP 中继。不幸的是,这已被一些大型运营商确定为不可接受,他们拥有大量使用路由器进行 L2 分离的网络架构。这也不适用于地理位置 VLAN 之间的分离,例如在拆分站点部署中。

另一种方法是使用网络交换机基础设施中的 DHCP 服务器功能来 PXE 启动系统,然后在通过 DHCP 完成 PXE 启动后分配静态 IP 地址。这种方法需要在交换机级别进行配置,从而影响系统 PXE 启动的位置,可能会打开不在 OpenStack 控制下的安全漏洞。这种方法也不利于考虑 PXE 镜像更改等因素的自动化。

不必使用硬件路由器来转发 DHCP 数据包。有适用于 Linux 的 DHCP 中继和 DHCP 代理包。可以将系统或 VM 放置在配置网络和远程网络上,以便转发 DHCP 请求。这可能是实施 CI 测试的一种方法。另一种方法是将所有远程配置网络回传到 Undercloud,并在 Undercloud 上运行 DHCP 中继以转发到本地 br-ctlplane。

安全影响

与标准隔离网络的主要区别之一是,各种子网通过路由器连接,而不是完全隔离。这意味着如果没有路由器上的适当 ACL,私有网络可能会暴露给外部流量。

应在文档中解决此问题,并强调应实施 ACL 以防止不受欢迎的网络流量。例如,内部 API 网络是敏感的,因为数据库和消息队列服务在该网络上运行。它应该与外部连接隔离。如果使用 *超网*,可以相对容易地实现这一点,以便如果所有内部 API 子网都是 172.19.0.0/16 超网的一部分,则 ACL 规则将仅允许内部 API IP 之间的流量(这是一个简化的示例,可以应用于所有内部 API 路由器 VLAN 接口或作为全局 ACL)

allow traffic from 172.19.0.0/16 to 172.19.0.0/16
deny traffic from * to 172.19.0.0/16

在 Ironic Inspector 的情况下,TFTP 服务器是一个潜在的漏洞点。TFTP 本质上是未经验证的,并且不包含访问控制模型。Ironic Inspector 运行的网络应从远程访问中保护起来。

其他最终用户影响

使用 spine-and-leaf 部署将需要额外的参数来提供路由信息和所需的多个子网。这将需要记录。此外,验证脚本可能需要更新,以确保配置已验证,并且 overcloud 节点之间具有适当的连接。

性能影响

许多今天通过层 2 进行的流量将在此设计中跨越层 3 路由边界。这会增加一些最小的延迟和开销,尽管在实践中,差异可能并不明显。一个重要的考虑因素是,路由器在其上行链路上的提交不能过多,并且必须监视路由器以确保它们不会成为瓶颈,尤其是在使用复杂的访问控制列表时。

DHCP 过程可能不会受到影响,但是通过 TFTP 传递系统镜像可能会受到性能下降。由于 TFTP 不擅长处理数据包丢失,因此部署者必须小心不要使路由交换机之间的链路饱和。

其他部署者影响

spine-and-leaf 部署比仅使用一组 VLAN 的部署更难进行故障排除。部署者可能需要更多的网络专业知识,或者在某些情况下可能需要专门的网络工程师来进行故障排除。

开发人员影响

spine-and-leaf 很难在 virt 环境中进行测试。这应该是可行的,但由于设置 libvirt 桥接和路由的复杂性,我们可能希望为虚拟环境提供 spine-and-leaf 的模拟。这可能涉及在 Undercloud 上构建多个 libvirt 桥接并在它们之间进行路由,或者可能涉及在 virt-host 上使用 DHCP 中继以及 virt-host 上的路由来模拟完整的路由交换机。需要制定一个开发和测试计划,因为并非每个开发人员都期望在具有路由环境中使用。

实现

负责人

主要负责人

Dan Sneddon <dsneddon@redhat.com>

最终分配人待定。

Approver(s)

主要审批人

Emilien Macchi <emacchi@redhat.com>

工作项

  1. 修改 Ironic Inspector dnsmasq.conf 生成以允许导出多个 DHCP 范围。启用此功能的补丁已合并 [7]

  2. 修改 Ironic Inspector 黑名单机制,使其支持 DHCP 中继,因为路由器转发的 DHCP 请求将具有路由器的源 MAC 地址,而不是正在部署的节点。

  3. 修改 tripleo-docs 中的文档以涵盖 spine-and-leaf 的情况。

  4. 添加一个上游 CI 作业来测试跨子网启动(尽管硬件可用性可能会使这成为一个长期目标)。

[*] 请注意,根据 Neutron/Ironic 集成的进度,可能更有意义先通过修改处理 undercloud.conf 的 Puppet 模块来实现对多个子网的支持,然后再跟进一个补丁,将 Neutron 网络集成到 Ironic Inspector 中。

Implementation Details

内省和部署流程

  1. 网络管理员在 ctlplane 网络上配置所有置备 VLAN,并将 Undercloud 服务器的 IP 地址配置为 DHCP 中继或“helper-address”。

  2. 操作员在 undercloud.conf 中配置 IP 地址范围和默认网关。每个子网都需要自己的 IP 地址范围。

  3. 操作员导入 baremetal instackenv.json。

  4. 当运行内省或部署时,DHCP 服务器通过 DHCP 中继接收来自裸机主机的 DHCP 请求。

  5. 如果节点尚未进行内省,则回复来自内省池的 IP 地址和 inspector PXE 引导镜像。

  6. 执行内省。执行 LLDP 收集 [2],以收集有关连接的网络端口的信息。

  7. 节点在 dnsmasq.conf(或在 /etc/dnsmasq.d 中)中被列入黑名单,并重启 dnsmasq。

  8. 在下一次启动时,如果 MAC 地址在黑名单中并且 Neutron 中存在端口,则 Neutron 回复来自 Neutron 端口的 IP 地址和 overcloud-full 部署镜像。

  9. 处理 Heat 模板,生成 os-net-config 模板,并运行 os-net-config 以从正确的子网分配静态 IP,以及通过路由器网关地址到其他子网的路由。

在使用 spine-and-leaf 时,DHCP 服务器需要根据由段路由器转发的 DHCP 中继数据包中包含的信息,在适当的子网上提供内省 IP 地址。dnsmasq 会自动将转发请求的路由器的网关地址 (GIADDR) 与接收到 DHCP 请求的子网匹配,并回复该子网的 IP 和网关。

上述 DHCP 服务器流程应允许在多个子网上置备 IP。

依赖项

对于生产 spine-and-leaf 部署,将依赖于执行 DHCP 中继服务的路由交换机。由于我们在虚拟测试环境中将没有路由交换机,因此可以按照下面的测试部分所述设置 DHCP 代理。

测试

为了正确测试此框架,我们需要建立至少一个部署 spine-and-leaf 的 CI 测试。如本规范中所讨论的,为了测试此功能,不必拥有完全路由的裸机环境,尽管在 OVB 等虚拟环境中使其工作需要一些工作。

对于虚拟测试,将所有 VLAN 汇聚回 Undercloud 就足够了,然后在 Undercloud 上运行 DHCP 代理以接收所有请求并将其转发到 br-ctlplane,dnsmasq 在那里监听。这将提供运行 DHCP 中继路由器的替代方案。

文档影响

TripleO 文档需要更新,以包含有关在 spine-and-leaf 环境中部署的详细说明,包括环境设置。涵盖交换机配置的具体厂商实现超出此范围,但应包含所需配置选项的具体概述,例如启用 DHCP 中继(或称为“helper-address”)并将 Undercloud 设置为接收 DHCP 请求的服务器。

TripleO 文档的更新还必须包括关于在部署前要进行的 IP 寻址选择的详细讨论。如果使用超网进行网络隔离,则需要一个良好的 IP 寻址计划,以确保未来的可扩展性。

参考资料