Internal DNS Resolution

作者:

Carl Baldwin <carl.baldwin@hp.com>

https://blueprints.launchpad.net/neutron/+spec/internal-dns-resolution

OpenStack 云的用户希望能够以直观的方式使用域名系统 (DNS) 按名称查找他们的实例。他们使用 Nova 启动一个实例,并在 Horizon 界面中为该实例指定一个“实例名称”。该名称用作实例中运行操作系统的视角的hostname。将此名称与 DNS 集成是合理的期望。

问题描述

Neutron 已经启用了使用内部 dnsmasq 实例的实例 DNS 查找。它基于分配给系统的私有 IP 地址生成一个通用 hostname。例如,如果实例使用 10.224.36.4 启动,则生成的 hostname 为 host-10-224-36-4.openstacklocal.

此实现的首个问题是 DNS 中使用的名称与实例知道的 hostname 不匹配。这给 sudo 和其他期望能够使用 DNS 查找自身 hostname 的软件带来了问题 [1]

此实现的第二个问题是,除非具备一些特殊知识,否则最终用户无法知道此名称。生成的名称未在任何 API 中显示,因此也无法在任何 UI 中显示。

提议的变更

概述

此蓝图将协调 Nova 和 Neutron 之间的 DNS 名称。Neutron DHCP 响应将使用 Nova 的实例 hostname 值作为其 hostname,而不是 Neutron 生成的 hostname。Neutron DNS 将响应对新 hostname 的查询。有关将传递的 hostname 的更多详细信息,请参阅相应的 Nova 蓝图 [2]

Neutron Port API 将扩展,以在 port 中添加一个 dns_name 字段。Nova 将在创建或更新 port 时使用此字段来传递实例的 hostname。此字段的有效值是

  • 部分限定域名 (PQDN)。

  • 完全限定域名 (FQDN)。

为了处理现有安装,如果 port 没有提供 dns_name,Neutron 将完全回退到当前行为。

此外,作为另一层向后兼容性,以前由 Neutron 创建的 DNS 名称将继续可用于 dnsmasq 中的前向 DNS 查找。

Neutron API 将在显示 port 详细信息时添加 dns_name 字段,以便用户可以看到它。

下表显示了 DNS 将如何响应各种查询。该表使用 example.com. 而不是 openstacklocal.,以反映只有在关联域名时才会启用它。

记录类型

查询

dns_name

响应

A

name.example.com.

name

10.224.36.4

A

host-10-224-36-4.example.com.

(n/a)

10.224.36.4

AAAA

name.example.com.

name

fd5d:19f:52e9::2

PTR

4.36.224.10.in-addr.arpa

(none)

host-10-224-36-4.example.com.

PTR

4.36.224.10.in-addr.arpa

name

name.example.com.

PTR

fd5d:19f:52e9::2.ip6.arpa

name

name.example.com.

如果 Neutron 无法接受来自 Nova 的名称,因为它未通过验证,Neutron 将使 port 创建或更新失败。有关此关联的更多详细信息,请参阅 数据模型影响 部分。

第二个只读属性 dns_fqdn 将添加到 Neutron port。API 将在显示 port 详细信息时添加此 dns_fqdn 属性,并存储 Neutron 基于在 port 创建或更新期间传递的 dns_name 生成的 FQDN。下表显示了如何根据配置的域名 example.com.dns_name 生成 FQDN

dns_name

dns_fqdn

vm01

vm01.example.com.

vm01.test1

vm01.test1.example.com.

vm01.test1.example.com.

vm01.test1.example.com.

vm01.test1.other.com.

API 将使 port 创建或更新失败

用户未指定

是否为空

根据上表,dns_fqdn 生成规则可以总结如下

  • 如果 dns_name 是 FQDN,则验证较高层级的标签是否与配置的域名匹配。

  • 如果 dns_name 是 PQDN,则附加配置的域名以形成 FQDN。

  • 如果用户未指定 dns_name,则 dns_fqdn 将为 null。

不是

此更改未提出使用其他方式(而不是 dnsmasq)实现内部 DNS 的驱动程序实现的模型。可以在此蓝图的后续蓝图中完成此操作。未来需要考虑的一些事项是

  1. DNS 当前侦听的 port 与 DHCP 相同。这是 dnsmasq 的工作方式,但可能不适用于其他解析器。共享此 port 存在固有的问题。例如,DHCP port 几乎不需要具有可预测的 IP 地址。但是,DNS 必须具有可预测的 IP 地址。由于此问题导致了问题 [3]。值得考虑为 DNS 解析器在本地网络上保留 IP 地址。

  2. 将 DNS 解析器与网关路由器耦合并将其 IP 地址用作 DNS IP 地址在没有网关的隔离网络上不起作用。

  3. 对于内部 DNS,解析器应为本地域提供权威响应,并转发其他查询到上游解析器或提供递归解析。

数据模型影响

此蓝图将向 Port 数据模型添加一个 dns_name 字段。值将验证为合法的部分限定域名 (PQDN) 或完全限定域名 (FQDN)。在这些名称中,DNS 标签将根据 RFC 1035 进行验证,该 RFC 1035 描述了有效格式,如下所示

它们必须以字母开头,以字母或数字结尾,并且内部字符只能是字母、数字和连字符。长度也存在一些限制。标签必须少于或等于 63 个字符。 [4]

一个复杂之处是 DNS 标签被视为不区分大小写 [5]。Neutron 会在记录名称之前将大写字符转换为小写。

仅当用户通过将域名与网络关联来为 port 的网络启用 DNS 时,才会对名称进行验证。

第二个只读属性 dns_fqdn 将添加到 Port 数据模型。API 将在显示 port 详细信息时添加此 dns_fqdn 属性,并存储 Neutron 生成的 FQDN,如“概述”部分所述。

将提供适当的数据库迁移脚本,以便在升级时将这些字段添加到 port 表中。

这些字段的默认值将为 null,以便与现有安装保持兼容。null 值对应于该字段在 API 中未指定。

REST API 影响

将 dns_name 和 dns_fqdn 字段添加到数据模型中的 port 对象需要对 Ports API 进行相应的更改。这些更改将以保持与现有 API 兼容的方式进行。

用户可以在 POST 和 PUT 操作中指定 dns_name 字段。在 API 调用中未指定它将导致模型中的值为 null。传递到此字段的任何非 null 值都将在 API 级别验证为 PQDN 或 FQDN。格式在 数据模型影响 部分中描述。

dns_fqdn 是一个只读属性,将在返回 port 详细信息作为 POST、PUT 或 GET 操作的结果时,由 API 包含。当用户未指定 dns_name 的值时,此属性将具有 null 值。“概述”部分描述了 Neutron 如何生成此属性的值。

不需要策略更改。

安全影响

此更改将启用 dns_name 字段中的用户数据收集。此数据将验证为合法的 PQDN 或 FQDN。然后,此用户数据将用于使用 Neutron 内部的名称启用 DNS 查找。我不期望这会带来任何新的安全风险,因为此功能的設計。与往常一样,应在代码审查中小心,以确保不会无意中引入任何风险。

通知影响

其他最终用户影响

python-neutronclient 可能需要修改才能处理新的字段。

性能影响

由于添加了 dns_name 字段的新约束,创建和更新 port 的数据库操作可能会受到轻微影响。不需要新的数据库锁,因此预计效果将是最小的。

IPv6 影响

其他部署者影响

此更改经过精心设计,可以独立部署新的 Nova 和 Neutron 代码。完成这两个升级后,新功能将可用。

如果先升级 Neutron,则没有问题,因为 dns_name 字段不是必需的,行为默认为旧行为。

如果先升级 Nova,那么 Nova 在尝试传递 dns_name 字段时会从 Neutron API 收到错误。Nova 将识别此错误并重试操作,而不使用 dns_name。

DNS 名称仅在新实例之后才会传递,在此功能启用后。

此更改没有引入新的配置选项。

开发人员影响

社区影响

社区中的许多人抱怨 Neutron 中计算实例 hostname 与 DNS 名称不一致。除了在此蓝图中多次提到的错误之外,还进行了 IRC 讨论 [6] 和在峰会上进行的面对面讨论,讨论了这个问题。这不是 Neutron 中最大的问题,但已经存在一段时间了,并且让许多人感到恼火。

备选方案

另一种选择是使用 API 中现有的 port name 字段,允许 Nova 将名称传递给 Neutron,而不是添加新字段。不这样做的原因是

  1. 该字段可能由 Neutron API 消费者用于其他目的。

  2. 该字段并非旨在携带 PQDN 或 FQDN,因此不会验证这些值。

实现

负责人

主要负责人

miguel-lavalle

其他贡献者

zack-feldstein

工作项

  1. 数据库升级脚本。

  2. 带有验证器的 API 扩展。

  3. 更改 API 以在 GET 时返回 dns_name 或默认生成的名称和 dns_fqdn。

  • 将默认 hostname 生成移动到 API 服务器。

  1. 更改为 RPC,以便在 DHCP 代理请求网络数据时,在 port 部分包含 dns 名称。

  2. 更改为 DHCP 代理,以便在更新 dnsmasq 时将 dns 名称写入 hosts 文件。

依赖项

为了使端到端工作,我们需要 Nova 中的协调更改。

https://blueprints.launchpad.net/nova/+spec/internal-dns-resolution

测试

Tempest 测试

应添加或修改 Tempest 测试以用于以下用例

  • 在 port 创建中未指定名称。DNS 查找应使用旧方法工作。

  • 在网络上复制名称的 port 创建应失败。

  • 使用 nova API 创建的实例可以使用实例名称查找。

我相信可以使用单元测试来测试输入验证。

功能测试

API 测试

文档影响

用户文档

开发人员文档

应记录 REST api 影响

参考资料

https://bugs.launchpad.net/nova/+bug/1175211