0%

使用cgroup限制iops失败的问题

前言

我们经常使用cgroup做一些资源隔离,比如内存、CPU、磁盘空间以及磁盘IO。对应的子系统是cpuset、memory、blkio。具体cgroup相关详细介绍,请查看redhat官方文档,不再详述,这里只是记录下我在使用cgroup限制diskio时遇到的一个问题。

问题

我们要对自己的一组agent做iops限制,agent是安装在/data目录下,磁盘信息如下图:

disk信息

可以看到/data目录挂载的设备为/dev/sda4,根据设备查找设备编号为(8:4),如下图:

设备编号

现在,我们开始使用cgroup限制agent的diskio,具体操作脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#定义校验函数
function verify_cg_val_iops()
{
metric_name="$1"
expected_val_dev_num="$2"
expected_val_dev_iops="$3"

#获取已配置的设备号
val_get_res_dev_num=`cgget -n -r ${metric_name} agents | awk '{print $2}'`
test_exitcode "cgget ${metric_name} failed for ${port}, cgget_result=${val_get_res_dev_num}"

#获取已配置的iops值
val_get_res_dev_iops=`cgget -n -r ${metric_name} agents | awk '{print $3}'`
test_exitcode "cgget ${metric_name} failed for ${port}, cgget_result=${val_get_res_dev_iops}"

#校验设备号
if [ "${expected_val_dev_num}" != "${val_get_res_dev_num}" ]; then
echo "${metric_name} expected dev_num val=${expected_val_dev_num} not equal to from cgget=${val_get_res_dev_num}"
exit 1
fi

#校验iops值
if [ "${expected_val_dev_iops}" != "${val_get_res_dev_iops}" ]; then
echo "${metric_name} expected dev_iops val=${expected_val_dev_iops} not equal to from cgget=${val_get_res_dev_iops}"
exit 1
fi
}

#创建一个隔离组agents
cgcreate -g blkio:/agents

#限制agent组对指定设备号的disk的读iops为3000
cgset -r blkio.throttle.read_iops_device="8:4 3000" agents
test_exitcode "io read set for 8:4 failed"

#检查读iops是否配置正确
verify_cg_val_iops "blkio.throttle.read_iops_device" "8:4" "3000"

#限制agent组对指定设备号的disk的写iops为3000
cgset -r blkio.throttle.write_iops_device="8:4 3000" agents
test_exitcode "io write set for 8:4 failed"

#检查写iops是否配置正确
verify_cg_val_iops "blkio.throttle.write_iops_device" "8:4" "3000"

执行时报错,错误信息为:

blkio.throttle.read_iops_device expected dev_num val=8:4 not equal to from cgget=

读iops配置失败,校验的设备号(为空)与预期设备号(8:4)不一致。

设备号写错了吗?/dev/sda4的设备号确实是8:4,没错啊,什么原因呢?

手动配置呢?

1
2
3
4
5
cd /sys/fs/cgroup/blkio/agents

echo "8:4 3000" > blkio.throttle.read_iops_device

-bash: echo: write error: Invalid argument

显示参数错误,再尝试直接vim打开写入,保存退出时报错:

“blkio.throttle.read_iops_device” E667: Fsync failed

解决

无奈之下,寻求谷歌大神,最终在stackoverflow上找到问题原因和解决方法。

原帖回答如下:

The problem was that I used /dev/sda5 as the device name, while in fact the physical device name (as opposed to the partitioned, logical device) must be use. It now works when I specify the : id of /dev/sda – user1734905

意思就是:在使用blkio做iops隔离时,应该指定的是物理磁盘的编号,而不是物理盘的某个分区的编号

回到上面的问题,我们使用的是/dev/sda4的编号,实际上我们的机器只有一块物理盘,做了4个分区,/dev/sda4只是物理盘/dev/sda的一个分区,应该使用/dev/sda的编号(8:0)。

物理盘信息

修改脚本中的设备编号8:4为8:0,再执行脚本,问题解决。

参考链接

如果对您有帮助