处理下线 Cell¶
https://blueprints.launchpad.net/nova/+spec/handling-down-cell
本规范旨在解决支持 Nova 的一些基本操作(例如在 Cell 下线时列出实例和服务)所需的行为变更。
问题描述¶
目前在 Nova 中,当一个 Cell 下线时(例如,如果无法访问 Cell 数据库),基本功能(如 nova list 和 nova service-list)将无法工作,并返回 API 错误消息。然而,单个 Cell 下线不应阻止这些操作对最终用户和操作员有效。另一个问题是,在创建 VM 期间计算配额时,不会考虑下线 Cell 的资源,并且 nova boot 操作被允许进入已启动的 Cell。这可能导致在启动时针对特定项目报告不正确的配额,这在下线 Cell 恢复时可能会产生影响。
用例¶
本规范要解决的具体用例包括
nova list即使在 Cell 下线时也应能工作。这可以分为两个用例nova show也应为下线 Cell 中的实例返回一个简约的结构,类似于nova list。nova service-list即使在 Cell 下线时也应能工作。解决方案可以分为两个阶段我们跳过下线 Cell,并最终显示来自其他 Cell 的所有服务,就像在 cells_v1 设置中一样。这已通过 弹性服务列表 修复。
我们优雅地处理下线 Cell。这将通过本规范通过创建一个简约的结构来修复。
nova boot如果请求项目在下线 Cell 中有任何正在运行的 VM,则不应成功,直到通过 使用 Placement 的配额 实现一个与全 Cell 迭代无关的配额计算解决方案。
提议的变更¶
本规范建议在 nova_api.instance_mappings 表中添加一个新的 queued_for_delete 列,如在 都柏林 PTG 中的 Cell 摘要 中讨论的那样。此列的类型为布尔值,默认情况下为 False,并在相应实例删除(正常/本地/软删除)时设置为 True。在软删除的情况下,如果实例被恢复,则该列的值将再次设置为 False。相应的 queued_for_delete 字段将添加到 InstanceMapping 对象中。
从下线 Cell 列出实例和服务将从 scatter-gather 工具返回一个 did_not_respond_sentinel 对象。使用此响应,我们可以知道一个 Cell 是否下线,并相应地修改列表命令,为来自下线 Cell 的记录以以下方式工作
nova list应从 API DB 中可用的信息返回一个简约的结构,其中包括created_at、instance_uuid 和 project_id 来自 instance_mapping 表。
实例状态将为“UNKNOWN”,这将是表明此记录是部分记录的主要指示。
其余字段键将缺失。
有关在使用过滤器、标记、排序和分页时运行此命令的更多信息,请参阅 边缘情况 部分。
nova show应从 API DB 中可用的信息返回一个简约的结构,类似于nova list。如果GET /servers/{id}无法访问 Cell 数据库,我们可以查看 instance_mapping 和 request_spec 表中的实例详细信息,其中包括instance_uuid、created_at 和 project_id 来自 instance_mapping 表。
实例状态将为“UNKNOWN”,这将是表明此记录是部分记录的主要指示。
user_id、flavor、image 和 availability_zone 来自 request_spec 表。
power_state 设置为 NOSTATE。
其余字段键将缺失。
nova service-list应从 API DB 中可用的信息返回一个简约的结构,其中包括host 和 binary 来自 host_mapping 表,用于计算服务。
其余字段键将缺失。
请注意,如果 cell0 下线,控制器服务将不会被列出。
nova boot如果请求项目在下线 Cell 中有正在运行的 VM,则不应成功。因此,如果 scatter-gather 工具在计算配额时返回 did_not_respond_sentinel,我们必须检查该项目是否在 instance_mapping 表中在下线 Cell 中有正在运行的实例,并在有正在运行的实例时阻止启动请求。然而,如果单个 Cell 下线,阻止用户在多个 Cell 中拥有 VM 创建 VM 可能不是理想的。因此,可以添加一个新的策略规则os_compute_api:servers:create:cell_down,默认值为rule:admin_api,通过该规则可以控制在项目在下线 Cell 中有实例时创建实例的能力,从而在用户/管理员之间进行控制。使用此方法,部署可以以他们想要的方式配置其设置。
为了使第一个、第二个和第四个操作在 Cell 下线时有效,我们需要在 API DB 中有关实例是否处于 SOFT_DELETED/DELETED 状态的信息,以便将正在运行的实例与已删除的实例区分开,这就是为什么我们添加新的列 queued_for_delete 的原因。
为了防止客户端抱怨缺失的键,我们需要一个新的微版本来接受上述最小结构中的服务器,这些服务器与已启动 Cell 中的服务器的完整结构位于同一个列表中。将来,我们可以使用缓存机制来填充下线 Cell 实例的信息。
请注意,所有其他非列表操作(例如创建和删除)将无法对下线 Cell 中的服务器进行操作,因为如果无法访问 Cell 数据库,则无法明确地执行任何操作。它们将继续像当前场景一样返回 500 错误。
边缘情况¶
过滤器:如果用户使用过滤器列出服务器,则将跳过下线 Cell 的结果,并且不会提供简约的结构,因为如果缺少过滤器键的值,则无法验证下线 Cell 中的过滤结果。请注意,默认情况下
nova list使用deleted=False和project_id=tenant_id过滤器,由于我们从 instance_mapping 表中知道这两个值,因此它们将是允许的唯一过滤器。因此,只有执行nova list和nova list --minimal才会显示下线 Cell 的简约结果。其他过滤器(如nova list --deleted或nova list --host xx)将跳过下线 Cell 的结果。标记:如果用户执行
nova list --marker,如果标记位于下线 Cell 中,则将返回 500 错误。排序:我们忽略下线 Cell,就像我们忽略过滤器一样,因为无法从缺少关键信息的下线 Cell 获得有效结果。
分页:我们忽略下线 Cell。例如,如果我们有三个 Cell A(已启动)、B(已下线)和 C(已启动),如果标记位于 A 的中间位置,我们将获得 A 的剩余一半结果、C 的所有结果并忽略 Cell B。
备选方案¶
将删除信息添加到 instance_mappings 表中的替代方案是在各自的 RequestSpec 记录中,但是 PTG 决定继续在 instance_mappings 表中添加新列,因为它更合适。对于主要逻辑,如果列表操作需要在 Cell 下线时有效,则在 API DB 中拥有已删除信息没有替代解决方案。
如果没有新的微版本,在列出下线 Cell 时,在响应中包含“shell”服务器,这些服务器将对缺失信息的键具有 UNKNOWN 值。但是,客户端无法处理带有“UNKNOWN”值的响应。此外,不可能将“UNKNOWN”分配给所有字段,因为并非所有字段都是字符串类型。
使用新的微版本,在新的顶级 API 响应键
unavailable_servers中包含下线 Cell 中的服务器 UUID 集合,并将两个列表(一个用于来自已启动 Cell 的服务器,另一个用于来自下线 Cell 的服务器)分开处理。有关更多详细信息,请参阅 unavailable_servers 的 POC。使用 Searchlight 在有下线 Cell 时进行回填。有关更多详细信息,请参阅 使用 Searchlight 列出实例。
为每个 Cell 数据库添加备份数据库,这些数据库将在危机时刻充当原始数据库的只读副本,但是这需要大量的同步,并且可能会获取陈旧的结果。
数据模型影响¶
需要对 nova_api DB 模式进行更改,以便将类型为布尔值的 queued_for_delete 列添加到 nova_api.instance_mappings 表中。此列默认设置为 False。
此外,InstanceMapping 对象将具有一个名为 queued_for_delete 的新字段。将添加一个在线数据迁移工具来填充现有 instance_mappings 的此字段。该工具基本上将遍历所有 Cell 中的实例记录,如果实例的 vm_state 为 DELETED 或 SOFT_DELETED,则将 queued_for_delete 更新为 True,否则将其保留为默认值。
REST API 影响¶
当 Cell 下线时,我们当前会跳过该 Cell,本规范旨在为 GET /servers、GET /os-services、GET /servers/detail 和 GET /servers/{server_id} REST API 提供部分信息。客户端将有一个新的微版本来识别响应中缺失的键和 NULL 值。
下面给出了 GET /servers/detail 的示例服务器响应,其中包含一个可用的服务器和一个不可用的服务器。
JSON 响应体示例
{
"servers": [
{
"OS-EXT-STS:task_state": null,
"addresses": {
"public": [
{
"OS-EXT-IPS-MAC:mac_addr": "fa:xx:xx:xx:xx:1a",
"version": 4,
"addr": "1xx.xx.xx.xx3",
"OS-EXT-IPS:type": "fixed"
},
{
"OS-EXT-IPS-MAC:mac_addr": "fa:xx:xx:xx:xx:1a",
"version": 6,
"addr": "2sss:sss::s",
"OS-EXT-IPS:type": "fixed"
}
]
},
"links": [
{
"href": "http://1xxx.xxx.xxx.xxx/compute/v2.1/servers/b546af1e-3893-44ea-a660-c6b998a64ba7",
"rel": "self"
},
{
"href": "http://1xx.xxx.xxx.xxx/compute/servers/b546af1e-3893-44ea-a660-c6b998a64ba7",
"rel": "bookmark"
}
],
"image": {
"id": "9da3b809-2998-4ada-8cc6-f24bc0b6dd7f",
"links": [
{
"href": "http://1xx.xxx.xxx.xxx/compute/images/9da3b809-2998-4ada-8cc6-f24bc0b6dd7f",
"rel": "bookmark"
}
]
},
"OS-EXT-SRV-ATTR:user_data": null,
"OS-EXT-STS:vm_state": "active",
"OS-EXT-SRV-ATTR:instance_name": "instance-00000001",
"OS-EXT-SRV-ATTR:root_device_name": "/dev/vda",
"OS-SRV-USG:launched_at": "2018-06-29T15:07:39.000000",
"flavor": {
"ephemeral": 0,
"ram": 64,
"original_name": "m1.nano",
"vcpus": 1,
"extra_specs": {},
"swap": 0,
"disk": 0
},
"id": "b546af1e-3893-44ea-a660-c6b998a64ba7",
"security_groups": [
{
"name": "default"
}
],
"OS-SRV-USG:terminated_at": null,
"os-extended-volumes:volumes_attached": [],
"user_id": "187160b0afe041368258c0b195ab9822",
"OS-EXT-SRV-ATTR:hostname": "surya-probes-001",
"OS-DCF:diskConfig": "MANUAL",
"accessIPv4": "",
"accessIPv6": "",
"OS-EXT-SRV-ATTR:reservation_id": "r-uxbso3q4",
"progress": 0,
"OS-EXT-STS:power_state": 1,
"OS-EXT-AZ:availability_zone": "nova",
"config_drive": "",
"status": "ACTIVE",
"OS-EXT-SRV-ATTR:ramdisk_id": "",
"updated": "2018-06-29T15:07:39Z",
"hostId": "e8dcf7ab9762810efdec4307e6219f85a53d5dfe642747c75a87db06",
"OS-EXT-SRV-ATTR:host": "cn1",
"description": null,
"tags": [],
"key_name": null,
"OS-EXT-SRV-ATTR:kernel_id": "",
"OS-EXT-SRV-ATTR:hypervisor_hostname": "cn1",
"locked": false,
"name": "surya-probes-001",
"OS-EXT-SRV-ATTR:launch_index": 0,
"created": "2018-06-29T15:07:29Z",
"tenant_id": "940f47b984034c7f8f9624ab28f5643c",
"host_status": "UP",
"trusted_image_certificates": null,
"metadata": {}
},
{
"created": "2018-06-29T15:07:29Z",
"status": "UNKNOWN",
"tenant_id": "940f47b984034c7f8f9624ab28f5643c",
"id": "bcc6c6dd-3d0a-4633-9586-60878fd68edb",
}
]
}
安全影响¶
无。
通知影响¶
无。
其他最终用户影响¶
当无法连接 Cell 数据库时,nova list、nova show 和 nova service-list 将使用下线 Cell 中的记录,这些记录不包含所有信息。当这些命令与过滤器/排序/分页一起使用时,输出将完全跳过下线 Cell,并仅返回来自已启动 Cell 的信息。根据默认策略,如果该 tenant_id 在下线 Cell 中有任何正在运行的实例,nova boot 将无法工作。
性能影响¶
在正常情况下,对性能没有重大影响。但是,当 Cell 下线时,在 show/list/boot 时间,由于对 instance_mapping 和/或 request_spec 表的额外检查以及 scatter-gather 工具返回 did_not_respond_sentinel 时构建简约记录所需的时间,性能会略有下降。
其他部署者影响¶
无。
开发人员影响¶
无。
升级影响¶
由于 API DB 模式将发生变化,因此必须运行 nova-manage api_db sync 命令以更新 instance_mappings 表。将添加一个新的在线数据迁移工具来填充新列。
实现¶
负责人¶
- 主要负责人
<tssurya>
- 其他贡献者
<belmoreira>
工作项¶
在 nova_api.instance_mappings 表中添加一个新列
queued_for_delete。在 InstanceMapping 对象中添加一个新字段
queued_for_delete。添加一个新的在线迁移工具来填充现有 instance_mappings 的
queued_for_delete。优雅地处理在从 Cell 接收到超时时的
nova list此处。优雅地处理在从 Cell 接收到超时时的
nova service-list。处理
nova boot在配额计算期间,在 配额计算代码 中,当结果是 did_not_respond_sentinel 或 raised_exception_sentinel 时。在 instance_mapping 表中实现额外的检查,以查看请求项目在 down cell 中是否有任何存活实例,并相应地阻止请求。
依赖项¶
无。
测试¶
单元和功能测试,用于验证在接收到 did_not_respond_sentinel 时的正常工作情况。
文档影响¶
更新计算 API 参考的描述,关于这些命令,包括 UNKNOWN 记录的含义。
参考资料¶
历史¶
发布名称 |
描述 |
|---|---|
Rocky |
引入 |