专用于卷的备份状态字段

本规范建议为卷引入一个新的 backup_status 字段,以消除活动备份任务对卷附加工作流程的阻塞或序列化问题。

问题描述

目前,所有 cinder 任务都使用状态字段来检查合适的卷 status,同时执行任何特定操作。 在任务的活动阶段,其状态也会通过相同的卷状态字段被持有和更新。 最后,任务抛出的某些错误也会通过此字段传回。 基本上,这个单个字段创建了一种锁定或同步机制,以确保任何时候只有一个任务作用于一个卷。

虽然这有助于协调影响卷本身的任务,但将相同的逻辑应用于备份实际上是不必要的或有帮助的

  • 作用于卷本身的操作(例如 resizeattaching)和备份(备份)在技术上并不相关。 备份驱动程序和块设备驱动程序独立运行,备份是从卷快照读取的,或者,如果配置选项 backup_use_temp_snapshot 设置为 false,则是卷的克隆。

  • 备份可能需要很长时间才能完成,并且在此期间会阻止卷上的任何其他任务。 如果假设正在备份一个 8TB 的卷,即使备份速度为 1 GB/s,卷备份仍然需要 ~2.5 小时才能完成。 从状态机角度来看,解耦这一点(因为它对于大多数通过快照工作的驱动程序或实现来说已经是这样)似乎非常有益。

用例

将备份任务与其他卷上的任务解耦,有两个方面的用例

1. 对于云运营商 - 目前,在实例实时迁移期间,将卷从源计算节点分离并将其附加到目标计算节点,会被并发运行的卷备份阻塞。 更糟糕的是,可能长时间运行的备份(任务)也可能由用户触发,从而阻塞管理操作,例如将所有实例迁移到其他主机以关闭超visor 进行维护。

如果卷足够大或备份传输速率慢,这可能会导致用户无限期地“锁定”管理任务。

2. 对于云用户 - 当前正在运行的备份任务会阻止紧急操作任务。 正在运行的备份会阻止用户快速调整正在耗尽可用空间的卷的大小,或将其附加到另一个实例。 如果备份任务甚至是由云提供商或某些自动调度触发的,则此问题会更加严重。

提议的变更

对于卷,应该有一个字段 backup_status 来保存当前存储在 status 中的备份相关值

  • ‘backing-up’

  • ‘error_backing-up’

  • ‘restoring-backup’

  • ‘error_restoring’

(backup_status 也可以是 null,以指示当前此卷没有备份相关状态。)

然后,这些应该从 status 的有效值列表中删除,并成为 backup_status 的值。

某些任务启动的条件检查会有一些变化,但通常依赖于将保留在状态字段中的那些卷状态值。

备选方案

之前有一个规范 [1] 将所有任务状态移动到一个新的字段。 但最终这过于复杂,并且不适合描述的解耦卷备份的用例。

数据模型影响

  • 必须向卷表中添加一个额外的字段 backup_status,并更改其可能保存的有效值列表。

  • 这将首先通过数据库模式更改来引入,以添加新字段。

  • 然后,通过在线更新/升级来拆分“移出”的与备份相关的状态到它们的新专用字段。

  • 卷状态的有效值也必须减少。 https://opendev.org/openstack/cinder/src/commit/5c23c9fbe41baef22a71eac4406fd9db269d1271/cinder/objects/fields.py#L168-L190 因为状态 backing-uperror_backing-up 仅存储在备份状态中。

  • 该方法 conditional_update 需要支持数据库更新过程中不同版本的卷数据模型。 此外, cinder 项目中对该方法的调用都必须更新为使用新字段。

REST API 影响

由于引入了一个新字段以及随之而来的状态字段的拆分,因此需要一个新的 API 微版本。 为了服务旧的微版本,必须引入数据模型之间的映射。 基本上,API 必须在旧的微版本中使用时,将来自两个字段(状态、备份_状态)的状态呈现为单个状态字段。

必须将 backup_status 的附加字段发送给用户。 卷的有效状态仅允许减少的集合。 此外,端点 reset_status_backup 操作需要适应新的数据模型,以允许(仅限管理员)设置备份状态。

注意:要更改的端点列表基于当前提出的更改,可能会发生变化。

  • 显示卷

{
  "volume": {
      "attachments": [],
      "availability_zone": "nova",
      "bootable": "false",
      "consistencygroup_id": null,
      "created_at": "2018-11-29T06:50:07.770785",
      "description": null,
      "encrypted": false,
      "id": "f7223234-1afc-4d19-bfa3-d19deb6235ef",
      "links": [
          {
              "href": "http://127.0.0.1:45839/v3/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/f7223234-1afc-4d19-bfa3-d19deb6235ef",
              "rel": "self"
          },
          {
              "href": "http://127.0.0.1:45839/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/f7223234-1afc-4d19-bfa3-d19deb6235ef",
              "rel": "bookmark"
          }
      ],
      "metadata": {},
      "migration_status": null,
      "multiattach": false,
      "name": null,
      "os-vol-host-attr:host": null,
      "os-vol-mig-status-attr:migstat": null,
      "os-vol-mig-status-attr:name_id": null,
      "os-vol-tenant-attr:tenant_id": "89afd400-b646-4bbc-b12b-c0a4d63e5bd3",
      "replication_status": null,
      "size": 10,
      "snapshot_id": null,
      "source_volid": null,
      "status": "creating",
      "backup_status": null,
      "updated_at": null,
      "user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e",
      "volume_type": "__DEFAULT__",
      "provider_id": null,
      "group_id": null,
      "service_uuid": null,
      "shared_targets": true,
      "cluster_name": null,
      "volume_type_id": "5fed9d7c-401d-46e2-8e80-f30c70cb7e1d",
      "consumes_quota": true
  }
}
  • 更新卷

    • 返回 backup_status 的附加字段

  • 列出卷

    • 显示 backup_status 的附加字段

    • backup_status 的附加过滤器

  • 列出详细卷

    • 显示 backup_status 的附加字段

    • backup_status 的附加过滤器

此外(仅在使用新的微版本时可用)

  • 设置卷 backup_status

  • 取消设置卷 backup_status

安全影响

通知影响

其他最终用户影响

性能影响

虽然本身没有性能影响,但将备份状态机与状态解耦将减少卷上发生任务的序列化。

其他部署者影响

开发人员影响

卷的状态只能设置为减少的状态列表。 此外,备份状态现在只能通过引入的 backup_status 字段设置或取消设置。

上述更改的影响是,所有方法都必须检查哪些允许与卷并发交互的方法,并使用 backup_status 字段而不是状态字段来指示正在运行的进程。 此更改应传达给依赖 cinder api 来检查状态的其他开发团队,以使用旧的微版本或更新为使用状态和 backup_status。

由于当前将状态用作锁定机制,以防止在达到无效状态时启动操作,因此 API 中的方法调用必须更新为在必要时也包括对 backup_status 的检查。 目前,这部分工作由 conditional_update 方法完成,该方法需要接收对更新的卷模型的支持。 仅当接收到旧数据库模型时才需要此版本控制。 API 始终发送新的模型,即使使用旧的 API 版本也是如此,因为翻译层。 此翻译层保证与旧 API 版本的向后兼容性,并将 (status, backup_status) -> status 和 status -> (status, backup_status) 进行翻译。

为了能够对 openstack 的数据库进行在线迁移以进行更新,需要一种将状态 -> (status, backup_status) 重新映射并将其保存到数据库中的方法。 只有在完成模式更新后才应调用此方法。 此方法将允许旧版本的 openstack 能够像以前一样执行并根据需要设置或检查其状态。 这些方法应在后续版本中删除。

升级影响

实现

必须维护以下关于可以对卷执行哪些操作/任务的现有限制

  • 在卷当前正在备份时,拒绝删除卷

  • 如果一个已经正在进行中,则拒绝卷的并发备份

  • 如果当前正在运行备份,则拒绝卷或“块存储”迁移

负责人

主要负责人

Christian Rohmann (IRC: crohmann)

其他贡献者

工作项

  • 将状态字段拆分为上述状态和 backup_status 字段

    • 通过向卷表中添加 backup_status 列来更新 SQL 数据模型

    • 创建 DB 迁移 (Alembic)

    • 允许在线迁移数据库的模型的附加方法

    • 通过添加 backup_status 字段和增加版本号来更新卷类

  • 引入验证方法,用于新的 backup_status 字段,以保证不会设置错误的状态

  • 更新状态字段的验证方法,以保证不会设置错误的状态

  • old 数据库模型添加对 conditional_update 方法的版本控制

  • 更新对 conditional_update 的方法调用,以使用状态和 backup_status

  • 引入 API 层作为翻译器,以服务旧的微版本

  • 引入一个新的微版本,以允许备份与使用卷的状态字段作为锁定机制的其他操作隔离。

  • 文档

    • 破坏性更改

    • API 文档

      • 模型

      • 端点

    • 旧数据库模型的升级指南/脚本

      • 在线迁移

      • 模式更新

依赖项

必须将依赖关系传达给其他开发团队,以确保他们使用旧的微版本以避免破坏性更改,并切换到新的拆分字段。 此更改应特别传达给 nova 团队,nova 团队会定期检查附加卷的状态。

测试

  • 由于只有减少的集合的状态通过 status 字段处理,并且 backup_status 作为新引入的字段,因此必须调整一些功能测试以使用新的数据模型。

  • 必须添加进一步的测试,以确保旧 API 微版本的翻译层按预期工作。 例如,备份状态通过旧版本中的 status,然后通过新版本中的 backup_status 来呈现。

  • 由于 conditional_update` 方法需要在此版本中支持版本控制,因此应编写测试以验证版本控制是否正确发生。

文档影响

  • 添加一个发布说明,解释更改的动机和效果

  • 记录卷本身以及备份和恢复任务的状态机。

  • 记录旧微版本的翻译层以及翻译行为。

参考资料

[1] 之前提出的添加任务状态的规范:https://review.opendev.org/c/openstack/cinder-specs/+/818551

历史记录

修订版

发布名称

描述

2023.02

引入