稳定的计算 UUID

https://blueprints.launchpad.net/nova/+spec/stable-compute-uuid

Nova 长期以来依赖于计算节点上不变的主机名。本规范旨在解决此限制,至少从检测意外更改并避免数据库中可能因主机名更改(无论是故意的还是意外的)而导致的灾难的角度来看。

问题描述

nova-compute 服务与其自身使用的唯一标识符之间没有很强的关联性。在大多数情况下,我们使用系统主机名作为标识符,通过该标识符在数据库中定位我们的 Service 和 ComputeNode 记录。然而,主机名可能会更改(有意或无意),这使得情况变得复杂。Nova 项目长期以来一直说“不要这样做”,但实际上,我们必须更具弹性,并能够在发生数据库损坏时检测并保护数据库。

用例

作为操作员,我希望 nova 能够在意外更改系统主机名而不会造成损坏或静默数据损坏的情况下幸存下来。

作为操作员,我希望 nova 检测到主机名不匹配并避免损坏其数据库。

作为部署工具开发者,我希望能够预先生成给定计算主机部署的 UUID,以便在启动服务之前提前知道它。

提议的变更

Nova 将使用一个持久化文件来存储非 Ironic 环境的计算节点 UUID。如果此文件在启动时不存在,则它将创建一次且仅创建一次。此 UUID 将用于提供数据库中 ComputeNode 对象的稳定查找,该对象代表给定的 nova-compute 实例。此标识文件应该能够位于 nova-compute 无法写入的位置,并像配置一样处理,但也应该位于可写入的位置,并像状态一样处理。后者很重要,可以避免添加必需的强制部署步骤。

计算服务将使用这种本地持久化的 UUID 可靠地找到 ComputeNode 记录,并在启动时检查主机名(或 CONF.host)是否可能已更改。如果检测到此类重命名,nova-compute 将无法启动并发出警告。

此文件将被命名为 compute_id,并且将在以下位置中的任何一个找到时被识别

  • 任何位于 CONF.config_files 中的文件的父目录

  • CONF.state_path 中指定的目录

为了安全起见,将始终搜索上述所有位置,并且找到的任何 compute_id 文件都将被检查。如果存在任何不一致之处(即,多个文件内容不相同),将记录错误并且 nova-compute 将拒绝启动。

文件格式将是一个包含以规范文本表示形式(即 uuidgen > /path/to/file)的 36 个字符的字符串。

如果启动 nova-compute 时未找到 compute_id 文件,则它将被创建一次并在 CONF.state_path 位置初始化为 UUID。

对于驱动程序设置为 Ironic 的配置,我们将不进行计算节点的持久化,因为 nova-compute 实例和 Ironic 节点之间没有 1:1 的映射。Ironic 推送的映射(通过 get_available_nodes())将被假定为正确。

请注意,Nova 中的所有驱动程序(Ironic 除外)都管理单个计算节点。Ironic 在这方面是“特殊”的,因此将针对此工作进行特殊处理。

备选方案

我们可以选择更复杂的格式,以便将来留出空间用于其他数据或属性。我认为文件很便宜,部署工具更容易编写(即 uuidgen > /path/to/file),并且避免了版本控制和迁移的潜在需要。

我们可以使 CONF.hostname 不可选且不默认为 socket.gethostname()。这可能是一种更简单的方法,但部署者和部署工具编写者不太可能青睐它。它也没有提供支持未来主机名更改的路径。

${state_dir}/instances/compute_nodes 文件中已经存在一些数据持久化,它是 JSON 编码的,并由图像缓存代码维护。我认为这是一个不太好的想法,因为它存储在一个潜在地在多个(但不是全部)计算节点之间共享的地方,因此可能难以实现稳定的“我是谁?”确定。

我们可以使用 /etc/machine-id 或其中的一部分。它不是 UUID,但很接近。它也是一个 freedesktop/systemd 东西,可能并不存在于所有地方,尤其是在容器化环境中。

数据模型影响

目前,我们在 compute_nodes 中以两种方式生成记录的新的 UUID

  • 对于大多数驱动程序,它发生在对象的深度处,位于可重定位的 create() 方法中。这意味着它们实际上是在计算节点上生成的,如果 virt 驱动程序不提供 uuid,导致资源跟踪器调用 create() 而未指定 UUID。

  • 对于 Ironic,virt 驱动程序在 resources 字典中提供 uuid,这导致它从一开始就使用所需的节点 id 创建。

因此,虽然这不直接影响数据模型,但这项工作将转向始终在创建记录时提供 ComputeNode.uuid 值,要么是因为我们从持久化文件中读取它,要么是因为我们预先生成它来写入文件。

REST API 影响

无。

安全影响

首选的 compute_id 文件位置是在配置文件的目录之一中,该目录本身不应可写。如果未提供,nova 将在 CONF.state_dir 中创建该文件,这将使其可被 nova-compute 运行的用户写入。这可能会提供一个破坏路径,尽管如果攻击者获得访问权限以写入该用户拥有的内容,所有实例磁盘和配置也同样暴露。

通知影响

无。

其他最终用户影响

无。

性能影响

无。

其他部署者影响

部署者默认情况下不会受到影响,但如果需要,将能够将计算节点的 UUID 作为配置固定。

开发人员影响

无。

升级影响

对于 2023.1 周期,nova-compute 需要优雅地处理存在代表其服务的 ComputeNode 的情况,但尚未持久化到 compute_id 文件中。我们需要在发布说明中传达这一点,警告错误地处理它的危险(这与今天的重命名几乎相同)。在支持这种兼容行为的期间,我们可以使用附加到我们的 ComputeNode 对象上的 Service.version 来确定是否应该将现有的 UUID 写入 compute_id 文件或从头开始生成它。在后续版本中,我们应该删除该行为(尽管可以保留一个启动阻止检查,如果正在跨该边界升级版本)。

实现

负责人

主要负责人

danms

功能联络人

功能联络人

sean-k-mooney

工作项

  • 编写和测试读取、写入和检查 compute_id 文件的例程。

  • init_host() 逻辑连接起来,以确保写入现有计算节点 UUID 到文件的兼容行为。

  • 修改现有的计算节点创建逻辑以尊重/生成持久的 compute_id

依赖项

无。

测试

单元和功能测试将足以覆盖此内容。我们将默认获得 grenade 和 greenfield devstack 覆盖,也许我们可以确保该文件在 job post 脚本中创建。

文档影响

安装指南需要更改以描述此文件的目的和行为。显然,需要发布说明来发出信号。

参考资料

历史

修订版

发布名称

描述

2023.1 Antelope

引入