继研究了Neutron之后,继续Nova的外围研究之旅。本站是研究块存储服务Cinder。
0。验证环境
环境包括:
1、一个controller节点,运行nova-api, nova-scheduler, cinder-api, cinder-scheduler, mysql, rabbitmq
2、一个Nova compute节点,运行一个虚机
3、三个cinder volume节点,每个节点使用LVMISCSIDriver来使用本地存储
4. 创建一个volume type,设置 volume_backend_name = lvmbackend
cinder.conf 在 block1上 enabled_backends = lvmdriver-b1 [lvmdriver-b1] volume_group = cinder-volumes volume_driver = cinder.volume.drivers.lvm.LVMISCSIDriver volume_backend_name = lvmbackend cinder.conf 在 block2上 enabled_backends = lvmdriver-b21,lvmdriver-b22 storage_availability_zone=az1 [lvmdriver-b21] iscsi_ip_address = 10.0.1.29 volume_group = cinder-volumes1 volume_driver = cinder.volume.drivers.lvm.LVMISCSIDriver volume_backend_name = lvmbackend [lvmdriver-b22] volume_group = cinder-volumes2 volume_driver = cinder.volume.drivers.lvm.LVMISCSIDriver volume_backend_name = lvmbackend cinder.conf 在 block3上
enabled_backends = lvmdrier-network [lvmdriver-network] volume_group = system volume_driver = cinder.volume.drivers.lvm.LVMISCSIDriver volume_backend_name = lvmbackend
关于几个小问题的说明:
- [***] 会定一个一个 backend,下面几行是该backend 的配置。需要启用的backend 需要添加到 enabled_backends 的值中
- volume_backend_name 会被 volume type 用到,通过 --property volume_backend_name 属性来设置。
- 多个backends 中的 volume_backend_name 可以相同。此时 scheduler 会按照指定的调度放在在多个 backend 之内选择一个最合适的。
- 每个 backend 都会有一个 cinder volume service instance,出现在 cinder service-list 命令的输出中,其 Host 的格式为 <节点名称>@<backend 值>
cinder的service如下:
root@controller:/home/s1# cinder service-list +------------------+---------------------------+------+---------+-------+----------------------------+-----------------+ | Binary | Host | Zone | Status | State | Updated_at | Disabled Reason | +------------------+---------------------------+------+---------+-------+----------------------------+-----------------+ | cinder-backup | controller | nova | enabled | up | 2015-01-11T16:36:00.000000 | None | | cinder-scheduler | controller | nova | enabled | up | 2015-01-11T16:36:01.000000 | None | | cinder-volume | block1@lvmdriver-b1 | nova | enabled | up | 2015-01-11T16:36:08.000000 | None | | cinder-volume | block2@lvmdriver-b21 | az1 | enabled | up | 2015-01-11T16:36:06.000000 | None | | cinder-volume | block2@lvmdriver-b22 | az1 | enabled | up | 2015-01-11T16:36:05.000000 | None | | cinder-volume | network@lvmdriver-network | nova | enabled | up | 2015-01-11T16:36:02.000000 | None | +------------------+---------------------------+------+---------+-------+----------------------------+-----------------+
说明:
- Cinder为每一个backend运行一个cinder-volume服务
- 通过在cinder.conf中设置 storage_availability_zone=az1 可以指定cinder-volume host的Zone。用户创建volume的时候可以选择AZ,配合cinder-scheduler的AvailabilityZoneFilter可以将volume创建到指定的AZ中。 默认的情况下Zone为nova。
- 通过在cinder.conf中的backend配置部分设置 iscsi_ip_address = 10.0.1.29 可以指定iSCSI session使用的网卡,从而做到数据网络和管理网络的分离。
- 搭以上多节点环境,一定要注意各节点之间使用NTP进行时间同步,否则可能出现cinder-volume没有任何错误,但是其状态为down的情况。
1、关于OpenStack块存储
1.1 OpenStack中的存储
1.2 虚机对块存储的要求
1.3 Cinder概述
1.4 Cinder的内部架构
- 三个主要组成部分
- –cinder-api 组件负责向外提供Cinder REST API
- –cinder-scheduler 组件负责分配存储资源
- –cinder-volume 组件负责封装driver,不同的driver负责控制不同的后端存储
- 组件之间的RPC靠消息队列(Queue)实现
- Cinder的开发工作主要集中在scheduler和driver,以便提供更多的调度算法、更多的功能、以及指出更多的后端存储
- Volume元数据和状态保存在Database中
1.5 Cinder的基本功能
1 |
卷操作 |
创建卷 |
2 |
从已有卷创建卷 (克隆) |
|
3 |
扩展卷 |
|
4 |
删除卷 |
|
5 |
卷-虚机操作 |
挂载卷到虚机 |
6 |
分离虚机卷 |
|
7 |
卷-快照操作 |
创建卷的快照 |
8 |
从已有卷快照创建卷 |
|
9 |
删除快照 |
|
10 |
卷-镜像操作 |
从镜像创建卷 |
11 |
从卷创建镜像 |
1.6 Cinder 插件
1.6.1 LVMISCSIDriver
上图说明:
- cinder-volume 服务部署在控制节点上。该节点上创建了一个 volume group。所谓LVM中的 Local,指的就是 volume group 和 cinder-volume 在同一个节点上,因为 cinder LVM driver 需要调用本地的相关命令来管理 volume group。
- 每个 nova-compute 计算节点作为 iSCSI Intiator 和存储节点通信。每当 VG 中为一个计算节点的一台虚机分配一个volume 后,在计算节点上就会出现一个 /dev/sdx 设备。此设备会被 qemu-kvm 提供给虚机,作为虚机的一个disk。
- 一个 cinder-volume 节点上可以有多个 volume group。此时每个 volume group 都有一个 cinder-volume 服务实例。
- 一个 openstack 环境中可以有多个 cinder-volume 节点。
root@compute1:/home/s1# cat /etc/iscsi/initiatorname.iscsi InitiatorName=iqn.1993-08.org.debian:01:8d794081cd6a
root@compute1:/home/s1# iscsiadm -m session tcp: [10] 192.168.1.24:3260,1 iqn.2010-10.org.openstack:volume-5cfc715d-a7b3-47b4-bded-44c0a228360c tcp: [11] 192.168.1.19:3260,1 iqn.2010-10.org.openstack:volume-4039eb07-90eb-4a92-8fd3-e3514cb4969b tcp: [14] 192.168.1.29:3260,1 iqn.2010-10.org.openstack:volume-3f204086-609e-449f-90a1-3a0d2c92c525 tcp: [16] 10.0.1.29:3260,1 iqn.2010-10.org.openstack:volume-1b7f6669-06db-474e-bf78-4feea529be5b tcp: [6] 192.168.1.24:3260,1 iqn.2010-10.org.openstack:volume-39363c5f-cf3c-4461-af83-00314839f05a tcp: [9] 192.168.1.24:3260,1 iqn.2010-10.org.openstack:volume-a0a7ccb3-8864-4fd0-aee2-0e20d43ba8dd
每个target的详细信息:
tgtadm --lld iscsi --op show --mode target Target 1: iqn.2010-10.org.openstack:volume-136354c3-5920-46b9-a930-52c055c53295 System information: Driver: iscsi State: ready I_T nexus information: I_T nexus: 2 Initiator: iqn.1993-08.org.debian:01:8d794081cd6a alias: compute1 Connection: 0 IP Address: 192.168.1.15 LUN information: LUN: 0 Type: controller SCSI ID: IET 00010000 SCSI SN: beaf10 Size: 0 MB, Block size: 1 Online: Yes Removable media: No Prevent removal: No Readonly: No SWP: No Thin-provisioning: No Backing store type: null Backing store path: None Backing store flags: LUN: 1 Type: disk SCSI ID: IET 00010001 SCSI SN: beaf11 Size: 1074 MB, Block size: 512 Online: Yes Removable media: No Prevent removal: No Readonly: No SWP: No Thin-provisioning: No Backing store type: rdwr Backing store path: /dev/cinder-volumes/volume-136354c3-5920-46b9-a930-52c055c53295 Backing store flags: Account information: s6KdhjSUrU2meEyxPTDZ ACL information: ALL
1.6.2 IBM SVC/DS8K/XIV 插件
上图说明:
- cinder-volume 通过管理网络和存储的控制器进行通信来管理volume,因此,理论上最少只需要一个 cinder-volume 实例。但是,为了高可用需要,往往会再部署一个备 cinder-volume 服务,并用 Pacemaker 进行控制。当主服务down后,备服务会接管。
- 以 XIV iSCSI driver (代码在这里)为例说明创建卷的过程
- 该 cinder 通过远程运行SSH 来执行XIV命令来操纵 XIV,比如运行 svctask mkvdisk 命令来创建一个XIV 卷。
- 当为虚机分配一个XIV volume 时 cinder driver 所做的工作:(1)计算计算节点的 host name (2)在 XIV 上为该host 创建一个 virtual host,需要指定HBA卡的WWPN(当采用FC连接时),或者host 的 IQN(当采用 iSCSI 连接时) (4)在XIV 上创建一个 LUN (5)将该LUN mount 给virtual host
- 此时,host 上每个 volume 都会有一个 /dev/sdx 设备
- qemu 将 sdx 设备虚拟化为虚机的一个 disk
1.6.3 LVM插件和Vendor插件的比较
2、 Cinder操作
下面讲讲几个比较有意思的操作。
2.1 tranfer volume:将volume 的拥有权从一个tenant中的用户转移到另一个tenant中的用户。
两步走:
+------------+--------------------------------------+
| Property | Value |
+------------+--------------------------------------+
| auth_key | a94e45d06dd54500 |
| created_at | 2015-01-07T07:36:33.916921 |
| id | b14d1d26-8249-4dd2-8213-258ccfe31542 |
| name | None |
| volume_id | d146a947-9c1e-489f-b7a3-6b9604d9fb49 |
+------------+--------------------------------------+
+-----------+--------------------------------------+
| Property | Value |
+-----------+--------------------------------------+
| id | b14d1d26-8249-4dd2-8213-258ccfe31542 |
| name | None |
| volume_id | d146a947-9c1e-489f-b7a3-6b9604d9fb49 |
+-----------+--------------------------------------+
2.2 volume migrate: 将volume从一个backend迁移到另一个backend
多种可能的情况:
2.3 volume backup
2.4 qos 支持
3 cinder的组件
关于RPC: cinder内部各组件之间使用基于RabbitMQ的RPC通信。cinder-scheduler和cinder-volume分别 会 创建RPC连接,启动消费者线程,然后等待队列消息。当轮询查询到消息到达后,创建线程处理相关消息。
3.1 cinder-api
主要服务接口, 负责接受和处理外界的API请求,并将请求放入RabbitMQ队列,交由后端执行。
cinder-api提供两个版本的REST API:V1提供Volume,Vloume type,Snapshot操作的API;V2增加了QoS,Limits,Backup操作的API。
除了V1和V2文档列出来的API外,一些volume的操作需要通过POST + action的方式实现,比如extend volume:
POST http://controller:8776/v1/fa2046aaead44a698de8268f94759fc1/volumes/8e87490c-fa18-4cff-b10e-27645c2a7b99/action
Action body: {"os-extend": {"new_size": 2}}
此类操作有:
- os-reset_status
- os-force_delete
- os-force_detach
- os-migrate_volume
- os-migrate_volume_completion
- os-reset_status
- os-update_snapshot_status
- os-attach
- os-detach
- os-reserve
- os-unreserve
- os-begin_detaching
- os-roll_detaching
- os-initialize_connection
- os-terminate_connection
- os-volume_upload_image
- os-extend
- os-update_readonly_flag
- os-retype
- os-set_bootable
- os-promote-replica
- os-reenable-replica
- os-unmanage
cinder-api service 的启动过程分析见 探索 OpenStack 之(11):cinder-api Service 启动过程分析 以及 WSGI / Paste deploy / Router 等介绍 (2015-02-04 16:01)
3.2 cinder-scheduler
cinder-scheduler的用途是在多backend环境中决定新建volume的放置host:
0。 首先判断host的状态,只有service状态为up的host才会被考虑。
1。创建volume的时候,根据filter和weight算法选出最优的host来创建volume。
2。迁移volume的时候,根据filter和weight算法来判断目的host是不是符合要求。
如果选出一个host,则使用RPC调用cinder-volume来执行volume操作。
为了维护host的状态,cinder-scheduler接受定时的host上cinder-volume状态上报:
2015-01-12 02:02:56.688 828 DEBUG cinder.scheduler.host_manager [req-403ef666-5551-4f31-a130-7bcad8e9d1ec - - - - -] Received volume service update from block2@lvmdriver-b21: {u'pools': [{u'pool_name': u'lvmbackend', u'QoS_support': False, u'allocated_capacity_gb': 1, u'free_capacity_gb': 3.34, u'location_info': u'LVMVolumeDriver:block2:cinder-volumes1:default:0', u'total_capacity_gb': 5.34, u'reserved_percentage': 0}], u'driver_version': u'2.0.0', u'vendor_name': u'Open Source', u'volume_backend_name': u'lvmbackend', u'storage_protocol': u'iSCSI'} update_service_capabilities /usr/lib/python2.7/dist-packages/cinder/scheduler/host_manager.py:434
3.2.1 Host Filtering 算法
默认的filter包括 AvailabilityZoneFilter,CapacityFilter,CapabilitiesFilter。其中:
- AvailabilityZoneFilter会判断cinder host的availability zone是不是与目的az相同。不同则被过滤掉。
- CapacityFilter会判断host上的剩余空间 free_capacity_gb 大小,确保free_capacity_gb 大于volume 的大小。不够则被过滤掉。
- CapabilitiesFilter会检查host的属性是否和volume type中的extra specs是否完全一致。不一致则被国旅掉。
经过以上Filter的过滤,cinder-scheduler会得到符合条件的host列表,然后进入weighting环节,根据weighting算法选出最优的host。得到空列表则报No valid host was found错误。
cinder.conf中,scheduler_default_filters不设置的话,cinder-scheduler默认会使用这三个filter。
3.2.2 Host Weighting 算法
- AllocatedCapacityWeigher:有最小已使用空间的host胜出。 可设置allocated_capacity_weight_multiplier为正值来反转,其默认值为-1。
-
CapacityWeigher:有最大可使用空间的host胜出。可设置capacity_weight_multiplier为负值来反转算法,其默认值为1
-
ChanceWeigher:随机从过滤出的host中选择一个host
经过此步骤,cinder-scheduler将得到一个weighted_hosts列表,它将会选择第一个host做为volume的目的host,把它加到retry_hosts列表中,然后通过RPC调用上面的cinder-volume来创建volume。
cinder.conf中,scheduler_default_weighers不设置的话,cinder-scheduler默认使用 CapacityWeigher。
3.3 cinder-volume
3.3.1 volume创建失败重试机制
用户可以在cinder.conf中使用scheduler_max_attempts来配置volume创建失败时候的重试次数,默认次数为3,值为1则表示不使用重试机制。
# Maximum number of attempts to schedule an volume (integer value)
#scheduler_max_attempts=3
cinder-sheduler和cinder-volume之间会传递当前是重试次数。如果volume创建失败,cinder-volume会通过RPC重新调用cinder-scheduler去创建volume,cinder-scheduler会检查当前的重试次数是不是超过最大可重试次数。如果没超过,它会选择下一个可以使用的host去重新创建volume。如果在规定的重试次数内仍然无法创建volume,那么会报No valid host was found错误。
比如下面的重试过程:
cinder-volume:
- Insufficient free space for volume creation on host network@lvmdriver-network#lvmbackend (requested / avail): 5/0.0
- Insufficient free space for volume creation on host block2@lvmdriver-b2#lvmbackend (requested / avail): 5/4.0
- Insufficient free space for volume creation on host block1@lvmdriver-b1#lvmbackend (requested / avail): 5/1.0
3.3.2 从image创建volume
Attempt to create a volume by efficiently copying image to volume. If both source and target are backed by gpfs storage and the source image is in raw format move the image to create a volume using either gpfs clone operation or with a file copy. If the image format is not raw, convert it to raw at the volume path.
b。若driver的clone-image方法不成功,则执行Cinder的默认方法:(1)创建一个raw的volume,设置其状态为downloading (2)将image下载并拷贝到该volume。具体方法每个driver可以自行实现,Cinder也提供默认实现。
c。拷贝image的metadata到volume的metadata。
3.3.3 从snapshot创建volume
a。获取snapshot
b。Cinder不提供默认实现方式,它调用各driver的create_volume_from_snapshot方法创建volume。以IBM SVC为例,它会在SVC存储上创建snapshot的一个拷贝。
c。如果snapshot是bootable的话,需要拷贝它的metadata到新的volume上。
3.3.4 从volume创建volume
a。获取源volume
b。Cinder不提供默认实现方式,它需要调用各driver的create_cloned_volume方法来创建volume。以IBM SVC为例,它会在存储上创建源volume的一个拷贝。
c。如果源volume是bootable的话,需要拷贝它的metadata到新的volume上。
3.3.5 创建原始volume
默认的话,cinder-volume会调用各driver创建一个原始的volume。