背景
由于Ceph存储和Nova计算节点是混合部署的,而且虚拟机的数据卷是共用Ceph的Volume存储池。难免会出现集群中某一台虚拟机的数据卷io飚高的情况,造成其他虚拟机iowait跟着飚高。出现这种情况对于io比较敏感的业务是灾难性的。大部分情况,业务虚拟机会随着磁盘io下降自动恢复。但是很多情况我们并不希望集群内出现这种io资源抢占的情况。
方案
第一种
对于io密集型的虚拟机,我们通常采用高性能的存储集群来满足此类业务的需求。
Ceph方面
利用SSD硬盘或者高性能硬盘创建一个新的存储池,手动修改CRush,将新硬盘关联到新存储池
OpenStack方面
- 配置cinder.conf,创建一个新的volume-backend
- 创建新的volume-type,io高密集的卷创建在新的volume-type里面
第二种
对于Ceph存储本身是低成本的构建架构,没有SSD或者高性能硬盘时,只能通过限制虚拟机对于数据卷的读写io或者速率了。
Ceph方面
没有对于配置,目前我用的Jewel版本暂时不支持RBD的Qos设置,后面新版本也许支持
OpenStack方面
1. Qos策略
Cinder的Qos支持前端和后端两种策略,前端是在qemu中实现,后端是在存储集群上实现。由于Ceph不支持,那我们就只能在前端实现
目前前端qemu支持配置的qos key如下:
- total_bytes_sec: the total allowed bandwidth for the guest per second
- read_bytes_sec: sequential read limitation
- write_bytes_sec: sequential write limitation
- total_iops_sec: the total allowed IOPS for the guest per second
- read_iops_sec: random read limitation
- write_iops_sec: random write limitation
2. 实现方法
通过调用libvirt接口,对数据卷添加了iotune信息,如下:
创建标准和关联qos
# cinder qos-create middleRW.limit consumer="front-end" read_iops_sec=300 write_iops_sec=300 read_bytes_sec=104857600 write_bytes_sec=62914560
# cinder qos-associate <qos_specs> <volume_type_id>
libvirt中对数据卷的限制
</disk>
<disk type='network' device='disk'>
<driver name='qemu' type='raw' cache='none'/>
<auth username='cinder'>
<secret type='ceph' uuid='48baec00-46f8-4aa1-908f-c7991961b022'/>
</auth>
<source protocol='rbd' name='volumes/volume-756ed2a4-5c54-4b02-956f-e1ec371a2c58'>
<host name='10.33.64.100' port='6789'/>
<host name='10.33.64.101' port='6789'/>
<host name='10.33.64.102' port='6789'/>
<host name='10.33.64.103' port='6789'/>
<host name='10.33.64.104' port='6789'/>
</source>
<backingStore/>
<target dev='sdb' bus='scsi'/>
<iotune>
<read_bytes_sec>104857600</read_bytes_sec>
<write_bytes_sec>41943040</write_bytes_sec>
<read_iops_sec>300</read_iops_sec>
<write_iops_sec>300</write_iops_sec>
</iotune>
<serial>756ed2a4-5c54-4b02-956f-e1ec371a2c58</serial>
<alias name='scsi0-0-0-1'/>
<address type='drive' controller='0' bus='0' target='0' unit='1'/>
</disk>
3. 简单测试
限制之前
# dd bs=1M count=4k if=/dev/zero of=test conv=fdatasync
4096+0 records in
4096+0 records out
4294967296 bytes (4.3 GB, 4.0 GiB) copied, 35.2682 s, 122 MB/s
写限制在40M/s,基本满足需求
# dd bs=1M count=4k if=/dev/zero of=test conv=fdatasync
4096+0 records in
4096+0 records out
4294967296 bytes (4.3 GB, 4.0 GiB) copied, 102.72 s, 41.8 MB/s
其它
当然也可以用libvirt的blkdeviotune
命令对虚拟机做io限制,这样不光可以对数据卷做限制,也可以对虚拟机的根盘做个性化配置。
# virsh blkdeviotune myinstances sda --read-bytes-sec 104857600 --write-bytes-sec 41943040 --read-iops-sec 300 --write-iops-sec 300 --read-bytes-sec-max 104857600 --write-bytes-sec-max 41943040 --group-name drive-scsi0-0-0-1 --read-bytes-sec-max-length 1 --write-bytes-sec-max-length 1 --read-iops-sec-max-length 1 --write-iops-sec-max-length 1
# virsh blkdeviotune 8 sdb
total_bytes_sec: 0
read_bytes_sec : 104857600
write_bytes_sec: 41943040
total_iops_sec : 0
read_iops_sec : 300
write_iops_sec : 300
total_bytes_sec_max: 0
read_bytes_sec_max: 10485760
write_bytes_sec_max: 4194304
total_iops_sec_max: 0
read_iops_sec_max: 30
write_iops_sec_max: 30
size_iops_sec : 0
group_name : drive-scsi0-0-0-1
total_bytes_sec_max_length: 0
read_bytes_sec_max_length: 1
write_bytes_sec_max_length: 1
total_iops_sec_max_length: 0
read_iops_sec_max_length: 1
write_iops_sec_max_length: 1