能够将镜像导入到多个存储¶
https://blueprints.launchpad.net/glance/+spec/import-multi-stores
尽管镜像服务支持多种后端来存储虚拟机镜像,但导入工作流仅允许将镜像数据推送到一个存储。本规范的目标是允许此工作流将镜像数据导入到多个存储,并避免操作员手动复制数据和更新镜像位置。
问题描述¶
目前,导入工作流仅允许将镜像数据推送到一个存储。因此,今天操作员需要执行许多手动步骤来复制后端 Glance 存储上的镜像位,即使使用了“enabled_backends”配置选项也是如此。
注意
示例
操作员提供一个 Openstack 云,其中包含不同的站点,每个站点都有其本地存储,Nova 主机直接访问这些存储(Ceph)。
该操作员使用多存储支持,并希望其镜像在每个存储中可用,以防止每次创建新的虚拟机时都通过 Glance 下载镜像,并让 Nova 使用 COW。
为此,在创建新镜像时,他需要使用导入工作流将镜像数据存储在存储中。由于镜像现在处于“ACTIVE”状态,他不能再使用导入工作流,并且需要手动将数据上传到 store2 到 storeN,并使用 Glance API 注册这些其他位置的 URL。
由于 Glance 支持多存储,因此应该提出一项功能,以便一次将镜像数据上传到这些存储,以方便操作员的工作。
提议的变更¶
本规范提出以下高级功能来支持多存储导入
增强镜像导入 API,以支持针对镜像位的存储列表。
想法是在 json 有效负载中提供一个新的“stores”数组字段,用户将在其中列出他想要导入数据的全部存储(例如:[‘ceph_fast’,‘ceph_cheap’])。
如果提交了不可用的存储,API 应该拒绝该请求。
如果用户或操作员想要将镜像导入到所有启用的存储,那么指定列表中的所有存储可能很困难或开销很大。为此,将提供一个布尔字段“all_stores”。
如果设置为 false(默认行为),我们使用先前描述的逻辑。
如果设置为 true,数据将被导入到可以从此特定 Glance 部署中使用的存储集合(即:在 Glance-API 收到的调用 /v2/info/stores 返回的相同存储集合)。这不能与“stores”参数同时使用。如果用户同时提交两者,API 应该拒绝该请求。
另一个布尔字段“all_stores_must_succeed”将添加到有效负载中,以指定用户想要应用的错误行为
如果将此字段设置为“true”(默认行为),并且在至少一个存储中上传期间发生错误,则应该拒绝该请求,从存储中删除数据(非暂存),并且镜像的状态保持不变。只有在请求完全执行并成功后,镜像的状态才会设置为“ACTIVE”。
如果将此字段设置为“false”,则请求将失败(数据从存储中删除,…),仅当所有用户指定的存储中的上传都失败时。在部分成功的情况下,添加到镜像的位置将是已正确上传数据到存储的位置。只要在一个存储中的上传完全执行并成功,镜像的状态就会设置为“ACTIVE”。
每次在存储中成功上传时,都会更新镜像位置(包含此存储的信息)。
用户可以通过查看 2 个保留的镜像属性来跟踪任务进度
os_glance_importing_to_stores:此属性包含尚未处理的存储列表。在导入流程开始时,它将填充请求中提供的存储。每次完全处理一个存储时,它将从列表中删除。
os_glance_failed_import:每次在存储中导入失败时,它都会添加到此列表中。此属性在导入流程开始时被清空。
如果在请求过程中删除了镜像,则剩余存储的导入将不会被处理,并且已经上传的数据应该被删除。
当前的位置策略模块不应受到这些更改的影响,因为我们没有更改镜像位置的行为。当前可以通过修补镜像并指定位置列表来做到这一点。
同样,由于在导入工作流中使用时选择存储已经是一种选择,因此无需添加新的策略来限制多存储导入。
备选方案¶
此解决方案的替代方案是允许将数据导入到状态为“ACTIVE”的镜像。这将是另一个规范的主题。
数据模型影响¶
无
REST API 影响¶
此规范提出了以下 API 更改
修改后的 API
导入镜像。
常见响应代码
正常的 http 响应代码:202
202: 已接受
预期的错误 http 响应代码:400、401、403、404、409、410
400:错误请求,包含详细信息。
401:未授权
404:未找到(镜像不存在或不属于调用者所有)
409:冲突(镜像状态不合适)
410:已消失(在操作进行中删除镜像)
API 版本
此更改需要次要版本更新。所有 URL 都在 v2 Glance API 下。
[修改后的 API] 将镜像导入到存储
将镜像导入到存储
POST /v2/images/{image_id}/import
此修改现有的 REST API,以添加三个新的可选主体字段。为了保持向后兼容性,如果未指定“stores”参数,则评估标头“X-Image-Meta-Store”。如果既未指定“X-Image-Meta-Store”标头和“stores”参数,则使用配置为默认的存储(例如 default_backend)来上传镜像。如果同时提供了两个参数,或者将“all_stores”参数设置为 true,则请求将被拒绝为错误请求(即:http 400)。
新的主体字段
stores – (字符串数组) 如果存在,则包含要将镜像二进制数据导入到的存储 ID 列表。
all_stores – (布尔值,默认为 false) 如果设置为 true,数据将被导入到所有配置的存储中。如果设置为 false,则评估“stores”和/或“X-Image-Meta-Store”。
all_stores_must_succeed – (布尔值,默认为 true) 如果设置为 false,则只有在所有指定的存储中上传失败时,任务才会失败。如果设置为 true,则如果在一个提到的存储中上传失败,任务将失败。
更改的响应代码
400 – 如果存在“stores”字段,但指定了至少包含一个不存在或只读存储(如 http)的存储 ID 列表。或者,如果同时指定了“all_stores”:’true’、‘stores’、‘X-Image-Meta-Store’ 中的任意两个或多个。
示例 curl 用法
curl -i -X POST -H "X-Auth-Token: $token"
-H "Content-Type: application/json"
-d '{"method":{"name":"glance-direct"},
"stores": ["ceph1", "ceph2"],
"all_stores_must_succeed": false}'
$image_url/v2/images/{image_id}/import
安全影响¶
无
通知影响¶
在通过镜像导入工作流时,在通知阶段发送的有效负载已经包含一个字段“backend”,其中包含用户在使用多后端支持时指定的存储。应该为用户要求的每个存储发送通知,其中包含该特定存储的上传状态。新的属性将添加到通知有效负载中。
注意
示例
操作员使用以下参数调用导入镜像 API
curl -i -X POST -H "X-Auth-Token: $token"
-H "Content-Type: application/json"
-d '{"method": {"name":"glance-direct"},
"stores": ["ceph1", "ceph2"],
"all_stores_must_succeed": false}'
$image_url/v2/images/{image_id}/import
对于“ceph2”上传失败,但“ceph1”上传成功。由于将参数“all_stores_must_succeed”设置为“false”,因此任务成功结束,镜像现在处于活动状态。
Glance 发送的通知如下所示(有效负载已截断以提高清晰度)
{
"priority": "INFO",
"event_type": "image.prepare",
"timestamp": "2019-08-27 16:10:30.066867",
"payload": {"status": "importing",
"name": "example",
"backend": "ceph1",
"os_glance_importing_to_stores": ["ceph1", "ceph2"],
"os_glance_failed_import": [],
...},
"message_id": "1c8993ad-e47c-4af7-9f75-fa49596eeb10",
...
}
{
"priority": "INFO",
"event_type": "image.upload",
"timestamp": "2019-08-27 16:11:30.058812",
"payload": {"status": "active",
"name": "example",
"backend": "ceph1",
"os_glance_importing_to_stores": ["ceph2"],
"os_glance_failed_import": [],
...},
"message_id": "8b8993ad-e47c-4af7-9f75-fa49596eeb11",
...
}
{
"priority": "INFO",
"event_type": "image.prepare",
"timestamp": "2019-08-27 16:10:30.066867",
"payload": {"status": "importing",
"name": "example",
"backend": "ceph2",
"os_glance_importing_to_stores": ["ceph2"],
"os_glance_failed_import": [],
...},
"message_id": "1c8993ad-e47c-4af7-9f75-fa49596eeb10",
...
}
{
"priority": "ERROR",
"event_type": "image.upload",
"timestamp": "2019-08-27 16:11:30.058812",
"payload": {"status": "active",
"name": "example",
"backend": "ceph2",
"os_glance_importing_to_stores": [],
"os_glance_failed_import": ["ceph2"],
...},
"message_id": "8b8993ad-e47c-4af7-9f75-fa49596eeb11",
...
}
其他最终用户影响¶
Glance 客户端
Glance 客户端(CLI + REST 客户端)必须根据本规范进行更新。特别是
CLI / API 支持在导入时指定存储 ID 列表。
CLI / API 支持在导入时指定 all_stores_must_succeed 选项。
性能影响¶
由于我们将数据写入多个存储,这将根据指定的存储数量增加 Glance 节点的 IO。从用户角度来看,导入工作流也将根据完成上传的存储而花费更多时间。
其他部署者影响¶
无
开发人员影响¶
无
实现¶
负责人¶
主要负责人
yebinama
评审人员¶
核心评审人
jokke
工作项¶
实施任务可能包括
提供了存储列表的镜像导入。
添加 python-glanceclient 支持
依赖项¶
无
测试¶
适当的单元和功能测试,以确保 Glance 的更改正常工作。
文档影响¶
我们需要确保更新 Glance 文档以获取
镜像导入的新主体字段。