通过外部事件更新服务器电源状态

https://blueprints.launchpad.net/nova/+spec/nova-support-instance-power-update

本规范旨在为运营商提供关于 nova 中 _sync_power_states 定期任务(该任务协调数据库和 hypervisor 之间的服务器状态)的更多灵活性,尤其是在裸机实例(ironic)的使用场景下。它建议使此定期电源同步的“真相来源”可配置,具体取决于情况,例如允许物理实例作为真相来源,并使 nova 更新其数据库,而不是将数据库状态强制施加到物理实例上。

问题描述

作为 nova 和 ironic 之间这种定期电源同步的一部分,当物理实例在断电或硬件团队直接访问机器进行系统维修等情况下关闭时,nova 会将其数据库中的实例置于 SHUTDOWN 状态,因为 hypervisor 被视为真相来源。但是,当物理实例通过非 nova-api 方法(如 IPMI 访问或电源按钮)重新启动时,它将再次被 nova 置于 SHUTDOWN 状态 ,因为这里数据库被视为真相来源(异步)。这可能会导致操作不便以及云运营商和维修团队之间的不一致。目前避免这种情况的唯一方法是完全禁用电源同步,但这不建议这样做。

请注意,ironic 允许将节点置于 maintenance mode,从而将该 节点从 nova 的 _sync_power_states 定期任务中排除。这涵盖了可预测的事件,如计划的维修,但无法帮助解决意外事件,如电源故障。

用例

作为运营商,我希望我的物理实例的电源状态为 RUNNING,而不是在通过 IPMI 访问或直接物理访问在系统维修或断电后重新启动后被 nova 置于 SHUTDOWN 状态。

提议的变更

为了使 nova 听到物理实例启动(或关闭),并将其视为真相来源,想法是向 os-server-external-events nova API 添加一个 power-update 事件名称。每当 ironic 侧的物理实例的电源状态发生变化(即物理实例在 ironic 侧启动(或关闭)并且 ironic 信任硬件而不是数据库作为真相来源)时,ironic 将 发送此事件。Nova 将使用 Denver2018 PTG 中讨论的现有外部事件 API 端点侦听来自 ironic 的 power-update 事件

在 nova 侧,一旦从 ironic 收到物理实例的此类事件,它将被路由到 virt 驱动程序。在 virt 驱动程序中,我们将添加一个新的 driver.power_update_event 方法,该方法对于所有驱动程序类型(ironic 除外)都将处于 NotImplemented 状态。因此,如果收到非 ironic 驱动程序支持的实例的 power-update,我们将记录错误。在 ironic 驱动程序中,此方法将更新 nova 数据库中该实例的 vm_statepower_state 字段为 ACTIVERUNNING(或 STOPPEDSHUTDOWN)。请注意,在将调用路由到驱动程序之前,nova 将处理 power-update 的通知和实例操作,类似于正常的启动/停止操作。

即使进行了此提议的更改,根据事件发生的顺序,我们仍然可能存在竞争条件,其中定期任务已经在运行并且覆盖了 power-update 事件。但是,这个窗口非常小。为了避免定期任务和 power-update 事件相互覆盖 ,可以在它们之间共享一个锁

备选方案

过去曾尝试过解决此问题,例如允许 管理员决定在状态冲突时采取什么操作,或允许 管理员在状态冲突时重新启动实例

数据模型影响

将在 objects.InstanceExternalEvent.name enum 中添加一个新的事件名称,名为 power-update

REST API 影响

新“power-update”事件的提议 JSON 请求体是

{
    "events": [
        {
            "name": "power-update",
            "server_uuid": "3df201cf-2451-44f2-8d25-a4ca826fc1f3",
            "tag": target_power_state
        }
    ]
}

字段定义

name

事件名称。(对于此功能为“power-update”)。

server_uuid

需要更新数据库中电源状态的物理实例的服务器 UUID。

tag

target_power_state 值将是“POWER_ON”(在 nova 中映射到“RUNNING”)或“POWER_OFF”(在 nova 中映射到“SHUTDOWN”)。

新“power-update”事件的提议 JSON 响应体是

{
    "events": [
        {
            "code": 200,
            "name": "power-update",
            "server_uuid": "3df201cf-2451-44f2-8d25-a4ca826fc1f3",
            "status": "completed",
            "tag": target_power_state
        }
    ]
}

字段定义

name

事件名称。(对于此功能为“power-update”)。

status
事件状态。可能的值
  • “completed” 如果被 Nova 接受

  • “failed” 如果遇到故障

代码
事件结果代码。可能的值
  • 200 表示已接受

  • 400 表示请求缺少必需的参数

  • 404 表示找不到服务器

  • 422 表示由于实例未与主机关联,因此无法处理该事件。

server_uuid

与原始请求中提供的值相同。

tag

与原始请求中提供的值相同。

通过 GET /servers/{server_id}/os-instance-actionsGET /servers/{server_id}/os-instance-actions/{request_id} API 调用,用户(默认情况下是管理员和服务器的所有者)可以看到 nova 侧的实例启动/关闭。

安全影响

无。

通知影响

无。

其他最终用户影响

性能影响

其他部署者影响

开发人员影响

升级影响

实现

负责人

主要负责人

<tssurya>

其他贡献者

<wiebalck>

工作项

  1. 添加新的外部事件类型。

  2. 对计算 API 和管理器进行必要的更改,以便在从 ironic 接收到事件时更新实例的电源和 vm 状态。

  3. 添加新的微版本和配置选项。

依赖项

测试

单元和功能测试,以验证新的 power-update 事件是否正常工作。

文档影响

使用新的 power-update 事件更新计算 API 参考文档。

参考资料

历史

修订版

发布名称

描述

Train

引入