Glance Interoperable Image Import功能介绍

Glance最核心的功能就是镜像管理,我们最常做的操作就是管理员给Glance上传一个镜像,然后大家就都可以从这个镜像创建虚拟机了,这在私有云场景下,没有任何问题。但是在公有云场景下,需要考虑的问题就比较多了,像“应用市场”就是可以让普通用户上传自己制作的镜像,并且共享给其他人,这一方面是请求量比在私有云场景大了很多,可能同时有很多人在传镜像,而且镜像一般都很大,如果不做优化,Glance API可能很快就卡死了;另一方面是安全性问题,普通用户是不可信的,管理员要对其上传的镜像做各种安全性、合法性检查;其他的,像管理员可能需要对用户上传的镜像自动做类型转换,以及打一些元数据标签之类的;所以,Glance的核心功能虽然简单,但是随着需求的不断提出,它还是经历过了一个比较“漫长”的演进过程。

整体来看,主要经历了三个阶段:

1. 通过API同步上传

早期版本,大概是在L版本之前,实现的是最简单粗暴的上传镜像,直接通过API把本地数据传到Glance的后端存储上去,这个也是私有云最常用的传镜像的方式,到现在该API仍然保留:

1
2
POST /v2/images
PUT /v2/images/{image_id}/file

对应的命令行为:

1
2
glance image-create
glance image-upload

POST /v2/images只是创建一个镜像的数据库记录,然后通过PUT /v2/images/{image_id}/file向该镜像上传数据,该上传镜像的接口是阻塞式的,它直接调用后端存储的接口传输数据,等到传输完成,才会返回。

示例:

1
2
glance image-create --disk-format raw --container-format bare --visibility public --name testfast
glance image-upload --file CentOS---7.3-64bit---2017-12-11-a.dsk e80e40ea-8567-4919-83b5-632829cf530b

其实也可以合并写成一条命令:

1
glance image-create --disk-format raw --container-format bare --visibility public --name testfast --file CentOS---7.3-64bit---2017-12-11-a.dsk

这条命令背后会依次调用上面的两个API。

2. Tasks的引入

在大概L版左右,引入了一个Tasks这个特性,Tasks的引入其实主要就是为了解决上面说的公有云场景下镜像管理的需求的,Tasks可以将镜像相关的耗时比较长的操作异步执行,即将这些操作放在后台执行,不再阻塞API,然后可以查看这些task的状态,是成功了还是失败了,并且可以通过自定义插件的形式,对镜像做一些特殊操作,相关的API为:

1
2
3
POST /v2/tasks
GET /v2/tasks
GET /v2/tasks/{task_id}

对应的命令行分别为:

1
2
3
glance task-create
glance task-list
glance task-show

比如上传镜像,比较耗时,那么可以创建一个上传镜像的task,让其在后台执行,示例Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
def create_task(url, **imageinfo):

input_parameter = {
'type': 'import',
'input': {
'image_properties': imageinfo,
"import_from": url,
"import_from_format": ""}}
glance = get_glance_client()
task = glance.tasks.create(**input_parameter)
return task.id

主要传typeinput两个参数,input是镜像相关的一些信息,typeimport,表示导入镜像,具体这个task可以干什么事,其实是通过插件的形式实现的,每一个type对应一个插件,input就是这个task需要用到的参数,当前Glance内置了两个type: importapi_image_import,后者就是我们本篇文章的主题Interoperable Image Import用到的task类型,管理员可以通过写插件的方式,来自定义一个task type,实现一些和镜像相关的操作。

这个task异步执行的实现,其实依赖的是TaskFlow这个库,将一个task中的步骤都抽象成Flow,编排在一起,可以线性执行这些Flow,如果有报错,可以顺序回滚,确保这些任务执行的可靠性和一致性。不同Task是可以并发执行的,使用GreenThread实现,可以通过task list或者task show查看到当前的状态以及详情信息。

值得注意的是,上面介绍的两种类型的task,又可以通过插件的形式向其中添加自定义的Flow,在真正上传镜像到Glance后端之前,可以通过自定义的Flow来实现前面说到的安全检查、合法性检查、类型转换等操作。如下图为import task的workflow示意图:

  • _CreateImage,这个Flow的作用就是创建image的数据库记录
  • _ImportToFS,这个Flow是将镜像导入到一个临时的目录中,供插件对该镜像进行处理,这个只有在有插件的时候,才会执行这个Flow
  • 三个虚线框,标识的就是插件式的Flow,目前是硬编码指定这三个插件
  • _ImportToStore,这个Flow就是经过了前面插件的处理,最终要上传到Glance的后端存储去
  • _DeleteFromFS,这个Flow就是上传完成后,从临时目录中删除临时镜像

3. Interoperable Image Import

这个大概是在R版引入的功能,Tasks的引入其实已经可以将镜像上传异步化,但是并没有将此外封装API提供出来,想要异步上传镜像的话,必须得像第2步中介绍的操作一样,通过创建Task来实现,这多少有点麻烦,而且镜像的来源可能多种多样,可能是本地文件,也可能是网络文件,也可能是现有的镜像,所以Glance就又通过插件的方式实现了一个叫做api_image_import的task类型,并且实现了相关的API,该API可以调用api_image_import task的workflow来实现异步上传镜像,这种新的上传镜像的方式就叫做:Interoperable Image Import

来看下新增的这两个API:

1
2
PUT /v2/images/{image_id}/stage
POST /v2/images/{image_id}/import

对应的命令行为:

1
2
glance image-stage
glance image-import

image-import这个接口又有三种上传镜像的方式,通过参数method指定:

  • glance-direct,这种方式需要先通过image-stage API将镜像文件先上传到一个临时目录,称作staging area,然后image-import API再将staging area中的镜像通过异步的方式传到最终的后端存储中去,这种方式是默认的,即不指定method的话,默认采用这种方式。
  • web-download,这种方式是将一个位于网络位置中的镜像,首先下载到staging area中,然后再将其传到最终的后端存储中去;
  • copy-image,这种方式是通过拷贝现有的一个镜像来上传一个新镜像。

我们以glance-direct方式为例,来看下怎么使用:

1
2
3
glance image-create --disk-format raw --container-format bare --visibility public --name testfast
glance image-stage --file CentOS---7.3-64bit---2017-12-11-a.dsk f456c8a6-23f6-42a4-85df-507fcb3abe34
glance image-import --backend fast f456c8a6-23f6-42a4-85df-507fcb3abe34

先通过image-create命令建一个镜像记录,拿到image id,然后通过image-stage命令将镜像传到staging area,再然后通过image-import命令将staging area中的镜像异步传输到后端存储中。

以上也可以合并成一条命令:

1
glance image-create-via-import --disk-format raw --container-format bare --visibility public --name testfast --file CentOS---7.3-64bit---2017-12-11-a.dsk

这个staging area通过下面的配置项配置:

1
2
[os_glance_staging_store]
filesystem_store_datadir = /var/lib/glance/staging

需要注意的是,如果需要起多个glance-api做高可用的话,那么这个目录得是一个在多个节点之间共享的目录,否则可能会报找不到镜像的错误。

import task类似,api_image_import task也可以通过插件的方式对上传的镜像做一些处理,目前内置的有inject_image_metadata, image_conversion这两个。

参考资料:

作者

hackerain

发布于

2020-11-11

更新于

2023-03-11

许可协议