Block Storage Service Cinder 作为 OpenStack 的块存储服务,为 Instance 提供虚拟磁盘。
操作系统获得存储空间的方式一般有两种:
- 裸盘的方式叫做Block Storage(块存储),也叫做 Volume (卷)。一般是通过某种协议(SAS、SCSI、SAN等)挂载裸盘,然后分区、格式化、创建文件系统,或者直接使用裸盘存储数据(数据库)。
- 文件系统存储。NAS 和 NFS 服务器,以及各种分布式文件系统提供的存储。
一、Cinder 架构
1. cinder-api
cinder-api 是整个 Cinder 组件的门户,所有 cinder 的请求都先由 cinder-api 处理。
cinder-api 向外界提供若干 HTTP REST API 接口。
cinder-api 对接收到的 HTTP API 请求做如下处理:
- 检查客户端出入的参数是否合法
- 调用 cinder 其他子服务处理客户端请求
- 将 cinder 其他子服务返回的结果,返回给客户端
cinder-api 只接受和 Volume 生命周期相关的操作。操作如下图:
2. cinder-scheduler
创建 Volume 时,cinder-scheduler 会基于容量、Volume Type 等条件选择出最适合的存储节点,然后创建 Volume。
在 /etc/cinder/cinder.conf
文件中,cinder 通过 scheduler_driver
、scheduler_default_filters
和 scheduler_default_weighers
三个参数来配置 cinder-scheduler。
(1)Filter scheduler
Filter scheduler 是 cinder-scheduler 默认的调度器。调度过程如下:
- 通过过滤器(filter)选择满足条件的存储节点
- 通过权重计算(weighting)选择最优(权重值最大)的存储节点
默认调度器配置如下:
scheduler_driver = cinder.scheduler.filter_scheduler.FilterScheduler
(2)Filter
在 /etc/cinder/cinder.conf
中 scheduler_default_filters
选项指定 file scheduler 使用的 filer,默认值如下:
scheduler_default_filters = AvailabilityZoneFilter,CapacityFilter,CapabilitiesFilter
Filter scheduler 将按照列表中的顺序依次过滤。
-
AvailabilityZoneFilter
为了提高容灾性和提供隔离服务,可以将存储节点和计算节点划分到不同的 Availability Zone 中。
例如:把一个机架上的机器划分到一个 Availability Zone 中,OpenStack 默认有一个命名为 “Nova” Availability 的 Zone,所有的节点初始都收放在 “Nova” 中的。用户可以根据需要创建自己的 Availability Zone,如下图
在创建 Volume 时,需要指定 Volume 所属的 Availability Zone,如下图:
cinder-scheduler 在做 filtering 时,会使用 AvailabilityZoneFilter 将不属于指定 Availability Zone 的存储节点过滤掉。
-
CapacityFilter
创建 Volume 时,用户指定 Volume 的大小。CapacityFilter 的作用是将存储空间不能满足 Volume 创建需求的存储节点过滤掉。
-
CapabilitiesFilter
不同的 Volume Provider 有自己的特性(Capabilities),比如是否支持 thin provision 等。
在创建 Volume 时,可以通过 Volume Type(卷类型)指定需要的 Capabilities,如下图
当然 Capabilities 可以根据需要定义很多个。如下图
通过 Volume Type(卷类型)的 Extra Specs(扩展规格)定义 Capabilities。Extra Specs 是 Key-Value 的形式定义的,如下图:
不同的 Volume Provider 支持的 Extra Specs 不同,查看 Volume Provider 文档。下图 Volume Type 只有一个 Extra Specs,“volume_backend_name” 这是最重要的,也是必须的 Extra Specs。
cinder-volume 会在配置文件 /etc/cinder/cinder.conf
中,设置 volume_backend_name
参数,作用是为存储节点的 Volume Provider 命名。这样,CapabilitiesFilter 就可以通过 Volume Type 的 “volume_backend_name” 赛选出指定的 Volume Provider。
下面是我测试环境 cinder.conf
中的 volume_backend_name
配置
[lvmdriver-1]
image_volume_cache_enabled = True
lvm_type = default
iscsi_helper = tgtadm
volume_group = stack-volumes-lvmdriver-1
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_backend_name = lvmdriver-1
(3)Weigher
Filter Scheduler 通过 scheduler_default_weighers
指定计算权重的 weigher,默认为 CapacityWeigher
scheduler_default_weighers = CapacityWeigher
CapacityWeigher
基于存储节点的空闲容量计算权重,空闲越多权重越大
3. cinder-volume
cinder-volume 在存储节点上运行, OpenStack 对 Volume 的操作,最后都交给 cinder-volume 来完成。
cinder-volume 自身并不管理真正的存储设备,存储设备是由 volume provider 管理的。cinder-volume 与 volume provider 一起实现 Volume 生命周期的管理。
-
通过 Driver 架构支持多种 Volume Provider
可以在 /opt/stack/cinder/cinder/volume/drivers/
目录中查看到 OpenStack 源代码中已经自带了很多 volume provider 的 Driver。
root@controller:/opt/stack/cinder/cinder/volume/drivers# cd
root@controller:~# cd /opt/stack/cinder/cinder/volume/drivers
root@controller:/opt/stack/cinder/cinder/volume/drivers# ll
total 1092
drwxr-xr-x 31 stack stack 4096 Feb 23 19:08 ./
drwxr-xr-x 5 stack stack 4096 Feb 23 19:08 ../
-rw-r--r-- 1 stack stack 21860 Feb 23 17:17 blockbridge.py
-rw-r--r-- 1 stack stack 12524 Feb 23 17:17 block_device.py
-rw-r--r-- 1 stack stack 16907 Feb 23 17:17 coho.py
-rw-r--r-- 1 stack stack 41951 Feb 23 17:17 drbdmanagedrv.py
-rw-r--r-- 1 stack stack 26030 Feb 23 17:17 hgst.py
-rw-r--r-- 1 stack stack 18002 Feb 23 17:17 infinidat.py
-rw-r--r-- 1 stack stack 0 Feb 23 17:17 __init__.py
-rw-r--r-- 1 stack stack 36712 Feb 23 17:17 lvm.py
-rw-r--r-- 1 stack stack 25907 Feb 23 17:17 nfs.py
-rw-r--r-- 1 stack stack 75815 Feb 23 17:17 nimble.py
-rw-r--r-- 1 stack stack 87290 Feb 23 17:17 pure.py
-rw-r--r-- 1 stack stack 61860 Feb 23 17:17 qnap.py
-rw-r--r-- 1 stack stack 19099 Feb 23 17:17 quobyte.py
-rw-r--r-- 1 stack stack 58110 Feb 23 17:17 rbd.py
-rw-r--r-- 1 stack stack 62600 Feb 23 17:17 remotefs.py
-rw-r--r-- 1 stack stack 28825 Feb 23 17:17 sheepdog.py
-rw-r--r-- 1 stack stack 26741 Feb 23 17:17 smbfs.py
-rw-r--r-- 1 stack stack 91524 Feb 23 17:17 solidfire.py
-rw-r--r-- 1 stack stack 25959 Feb 23 17:17 tegile.py
-rw-r--r-- 1 stack stack 39682 Feb 23 17:17 tintri.py
-rw-r--r-- 1 stack stack 29320 Feb 23 17:17 vzstorage.py
-rw-r--r-- 1 stack stack 69166 Feb 23 17:17 xio.py
存储节点在配置文件 /etc/cinder/cinder.conf
中 volume_driver
选项配置使用 driver
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
-
定期向 OpenStack 报告计算节点的状态
在 cinder-scheduler 会用到 CapacityFilter 和 CapacityWeigher,他们都是通过存储节点的空间容量来筛选。这个容量信息就是来自 cinder-volume 的定期报告。
在 cinder-volume 的日志 /opt/stack/logs/c-vol.log
中可以发现每隔一段时间,cinder-volume 就会报告一次资源情况。如下图
-
Volume 生命周期的管理
Cinder 对 Volume 的生命周期的管理最终是通过 cinder-volume 完成的。包括 创建、挂载、快照、删除、扩展等。
4. cinder-provider
数据的存储设备,为 volume 提供物理存储空间。
cinder-volume 支持多种 volume provider, 每种 volume provider 通过自己的 driver 与 cinder-volume 协调工作。
二、物理部署方案
1. Cinder 服务
Cinder 服务部署在两类节点上,控制节点和存储节点。
控制节点中 cinder 服务。
root@controller:~# ps -e | grep cinder
7481 pts/19 00:03:25 cinder-api
7998 pts/20 00:00:42 cinder-schedule
8490 pts/21 00:03:23 cinder-volume
可以看到 cinder-api 和 cinder-scheduler 部署在控制节点上,这个是合理的。
cinder-volume 为什么也在控制节点上?
首先 OpenStack 是一个分布式系统,每个子服务都可以部署在任何地方,只要网络能够连通。
无论哪个节点,只要上面运行了 cinder-volume 服务,就是一个存储节点,当然也可以运行其他服务。
也可以使用 cinder service-list
查看 cinder 服务分布。
root@controller:~# cinder service-list
+------------------+------------------------+------+---------+-------+----------------------------+-----------------+
| Binary | Host | Zone | Status | State | Updated_at | Disabled Reason |
+------------------+------------------------+------+---------+-------+----------------------------+-----------------+
| cinder-scheduler | controller | nova | enabled | up | 2019-03-17T00:54:15.000000 | - |
| cinder-volume | controller@lvmdriver-1 | nova | enabled | up | 2019-03-17T00:54:15.000000 | - |
+------------------+------------------------+------+---------+-------+----------------------------+-----------------+
2. RabbitMQ 和 MySQL 服务
RabbitMQ 和 MySQL 通常部署在控制节点上。
3. volume provider
一般 volume provider 是独立的。cinder-volume 使用 driver 与 volume provider 通信并协调工作。
所以只需要将 driver 和 cinder-volume 放在一起就可以了。
三、操作过程
1. LVM Volume Provider
Cinder 将 LVM 作为默认的 volume provider。Devstack 安装之后, /etc/cinder/cinder.conf
已经配置好了 LVM,
default_volume_type = lvmdriver-1
enabled_backends = lvmdriver-1
[lvmdriver-1]
image_volume_cache_enabled = True
lvm_type = default
iscsi_helper = tgtadm
volume_group = stack-volumes-lvmdriver-1
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_backend_name = lvmdriver-1
配置中定义了名为 “lvmdriver-1” 的 volume provider,也称作 back-end。其 driver 是 LVM,LVM 的 volume group 名为 “stack-volumes-lvmdriver-1”。
在 /dev/sdb
中手动创建 VG “stack-volumes-lvmdriver-1” 。
创建 physical volume /dev/sdb
root@controller:~# pvcreate /dev/sdb
Device /dev/sdb not found (or ignored by filtering).
因为 Linux 的 LVM 默认配置,不允许在 /dev/sdb
上创建 PV,需要将 sdb 添加到 /etc/lvm/lvm.conf
的 global_filter
中添加 a|sdb|
global_filter = [ "a|sdb|", "a|.*/|" ]
root@controller:/~# pvcreate /dev/sdb
Physical volume "/dev/sdb" successfully created
然后创建 VG stack-volumes-lvmdriver-1
root@controller:~# gcreate stack-volumes-lvmdriver-1 /dev/sdb
Volume group "vgcreate stack-volumes-lvmdriver-1 /dev/sdb" successfully created
在 OpenStack Web 的 Volume Type 中可以查看了。