Openstack cinder有一个可选的功能:镜像盘缓存,可以明显提升从镜像创建云盘的性能。主要看存储后端克隆云盘的速度有多快。
一、功能简介
当第一次从镜像创建云盘时,cinder的internal租户会创建一个镜像盘缓存(image-volume-cache)。之后再从这个镜像创建云盘,就直接克隆这个镜像盘缓存,不需要再从glance下载镜像进行格式转换后拷贝数据到云盘这个流程了。在新创建镜像盘时,要想知道当前镜像是否被缓存过,需要借助数据库记录:只需要在创建镜像盘缓存时,将镜像与缓存的关联保存到表中。当请求再次来到时,查询当前镜像是不是存在表中即可(数据库中增加表image_volume_cache_entries用来记录image-volume-cache 的host, image_id, volume_id, size等信息)。

二、配置过程
创建内部租户,对于用户来说,没必要看到这些缓存盘

创建internal用户
[root@icontrol01 ~]# openstack  user create --password-prompt cinder_internal_tenant_user
User Password:
Repeat User Password:
+---------------------+----------------------------------+
| Field               | Value                            |
+---------------------+----------------------------------+
| domain_id           | default                          |
| enabled             | True                             |
| id                  | 081851ca64c344f3b700dcf4aeefb295 |
| name                | cinder_internal_tenant_user      |
| options             | {}                               |
| password_expires_at | None                             |
+---------------------+----------------------------------+
创建internal租户
[root@icontrol01 ~]# openstack project create --description "cinder internal tenant project" cinder_internal_tenant_project
+-------------+----------------------------------+
| Field       | Value                            |
+-------------+----------------------------------+
| description | cinder internal tenant project   |
| domain_id   | default                          |
| enabled     | True                             |
| id          | cc0d1c35318643d9860a86cea8ba03ad |
| is_domain   | False                            |
| name        | cinder_internal_tenant_project   |
| options     | {}                               |
| parent_id   | default                          |
| tags        | []                               |
+-------------+----------------------------------+
添加角色
[root@bjqnl-icontrol01 ~]# openstack role add --project cc0d1c35318643d9860a86cea8ba03ad --user 081851ca64c344f3b700dcf4aeefb295 admin
[root@bjqnl-icontrol01 ~]

修改cinder-volume配置。

我的环境是使用的是kolla-ansible部署,配置文件如下:
[root@icontrol01 ~]# vim /etc/kolla/cinder-volume/cinder.conf

[default]
cinder_internal_tenant_project_id = cc0d1c35318643d9860a86cea8ba03ad    ###project id
cinder_internal_tenant_user_id = 81851ca64c344f3b700dcf4aeefb295        ###user id
image_volume_cache_enabled = True      ###开启镜像缓存
image_volume_cache_max_size_gb = 200   ###设置缓存大小
image_volume_cache_max_count = 50      ###缓存镜像个数

后端对接的是ceph存储,所以也要开启image cache
[rbd-1]
image_volume_cache_enabled = True    #####
volume_driver = cinder.volume.drivers.rbd.RBDDriver
volume_backend_name = rbd-1
rbd_pool = volumes


重启cinder-volume服务
docker restart cinder_volume

测试
从镜像创建卷,之后可以看到有缓存的镜像卷,如下:

可以看到缓存盘是以image开头的
[root@icontrol01 ~]# cinder list --all  |grep image
| 4cf6692c-9e12-49b6-877b-47b4ea1f67f8 | b704505956294ab792822e56e3cb64fd | available | image-e1c871d3-59a4-4faa-aec8-42c6ec2b96a1 | 10  | __DEFAULT__ | false    |                                 
[root@icontrol01 ~]# openstack project show b704505956294ab792822e56e3cb64fd
+-------------+----------------------------------+
| Field       | Value                            |
+-------------+----------------------------------+
| description | cinder internal tenant projectg  |
| domain_id   | default                          |
| enabled     | True                             |
| id          | b704505956294ab792822e56e3cb64fd |
| is_domain   | False                            |
| name        | cinder_internal_tenant_project   |
| options     | {}                               |
| parent_id   | default                          |
| tags        | []                               |
+-------------+----------------------------------+

查看ceph后端存储,如下:

(ceph-mon)[root@icontrol01 /]# rbd ls volumes| grep 4cf6692c-9e12-49b6-877b-47b4ea1f67f8
volume-4cf6692c-9e12-49b6-877b-47b4ea1f67f8
(ceph-mon)[root@icontrol01 /]# rbd info volumes/volume-4cf6692c-9e12-49b6-877b-47b4ea1f67f8
rbd image 'volume-4cf6692c-9e12-49b6-877b-47b4ea1f67f8':
        size 10 GiB in 2560 objects
        order 22 (4 MiB objects)
        snapshot_count: 0
        id: d4c75fbe9c985e
        block_name_prefix: rbd_data.d4c75fbe9c985e
        format: 2
        features: layering, exclusive-lock, object-map, fast-diff, deep-flatten
        op_features:
        flags:
        create_timestamp: Wed Dec 29 10:09:47 2021
        access_timestamp: Wed Dec 29 10:29:05 2021
        modify_timestamp: Wed Dec 29 10:09:47 2021

三、缓存过程解析

  • 通知
    缓存操作会触发Telemetry消息,这几种消息会被发送:
  • image_volume_cache.miss - 创建云盘时,没有从缓存中找到相应的镜像,会有新的缓存会被创建 ;
  • image_volume_cache.hit - 从镜像创建云盘时,在缓存中找到相应的镜像并将被使用;
  • image_volume_cache.evict - 镜像盘缓存被删除。
  • 数据库中新建image_volume_cache_entries表,用以保存云盘和镜像的关联

当由镜像创建云盘时,根据数据库记录判断是否由该镜像创建过镜像盘:
若未创建,则向glance请求下载镜像,将镜像数据格式转换后拷贝到云盘中,然后由该云盘克隆一个缓存盘(归属于所配置的Service项目);同时更新数据库表中的缓存记录;
若创建过(并且云盘在当前主机上),则由缓存盘克隆出新的云盘(该克隆功能直接由存储后端提供),若新云盘与请求的云盘大小不一致,则扩展(Extend)该云盘。

数据库记录如下:

MariaDB [cinder]> select * from image_volume_cache_entries\G
*************************** 1. row ***************************
image_updated_at: 2021-06-04 01:08:33
            id: 3
          host: control@rbd-1#rbd-1
      image_id: e1c871d3-59a4-4faa-aec8-42c6ec2b96a1
     volume_id: 4cf6692c-9e12-49b6-877b-47b4ea1f67f8
          size: 10
     last_used: 2021-12-29 02:29:06
  cluster_name: NULL
1 row in set (0.000 sec)
  • 管理image-volume缓存
    通常来说,缓存都是自动管理的,不需要手动干预。如果需要,可以手动删除缓存。通过标准的云盘删除API,cinder服务会执行删除云盘的操作。若缓存盘被删除,再由该镜像创建云盘会回到“下载镜像->创建云盘->创建镜像盘缓存”的过程。
  • 若当前镜像的大小超过总容量大小,则不缓存镜像;
    若当前镜像大小未超过总容量大小,但是超过当前可用的缓存容量大小,则按照“最久未使用”的方式删除已经缓存的镜像盘,直至可用容量满足当前镜像大小;
    若当前镜像大小未超过总容量大小,并且当前可用的缓存容量大小能够满足当前镜像,则直接创建镜像缓存。
  • 除了配置缓存容量和个数,镜像盘缓存的创建还会受到service项目volume配额的限制。

四、总结:

缓存机制将创建镜像盘的流程从glance下载镜像拷贝数据到云盘的操作改为在后端存储上克隆。如果后端存储的克隆性能比较好,将极大的提升创建镜像盘的速度。