cgroups管理进程磁盘io

本文介绍了 Linux cgroups 如何通过 blkio 子系统限制和监控进程的磁盘 I/O,详细解释了相关参数及其作用,并提供了实际应用案例。

linux 的 cgroups 还可以限制和监控进程的磁盘 io。这个功能通过 blkio 子系统实现。

blkio 子系统里东西很多。不过大部分都是只读的状态报告,可写的参数就只有下面这几个:

复制代码代码如下:
blkio.throttle.read_bps_device
blkio.throttle.read_iops_device
blkio.throttle.write_bps_device
blkio.throttle.write_iops_device
blkio.weight
blkio.weight_device

这些都是用来控制进程的磁盘 io 的。很明显地分成两类,其中带“throttle”的,顾名思义就是节流阀,将流量限制在某个值下。而“weight”就是分配 io 的权重。

“throttle”的那四个参数看名字就知道是做什么用的。拿 blkio.throttle.read_bps_device 来限制每秒能读取的字节数。先跑点 io 出来

复制代码代码如下:
dd if=/dev/sda of=/dev/null &
[1] 2750 
用 iotop 看看目前的 io

复制代码代码如下:
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
2750 be/4 root 66.76 M/s 0.00 B/s 0.00 % 68.53 % dd if=/dev/sda of=/dev/null
...

然后修改一下资源限制,把进程加入控制组

复制代码代码如下:
echo '8:0 1048576' >/sys/fs/cgroup/blkio/foo/blkio.throttle.read_bps_device
echo 2750 >/sys/fs/cgroup/blkio/foo/tasks
这里的 8:0 就是对应块设备的主设备号和副设备号。可以通过 ls -l 设备文件名查看。如

复制代码代码如下:
# ls -l /dev/sda
brw-rw----. 1 root disk 8, 0 Oct 24 11:27 /dev/sda
这里的 8, 0 就是对应的设备号。所以,cgroups 可以对不同的设备做不同的限制。然后来看看效果

复制代码代码如下:
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
2750 be/4 root 989.17 K/s 0.00 B/s 0.00 % 96.22 % dd if=/dev/sda of=/dev/null
...


可见,进程的每秒读取立马就降到了 1MB 左右。要解除限制,写入如 “8:0 0” 到文件中即可

不过需要注意的是,这种方式对小于采样间隔里产生的大量 io 是没用的。比如,就算在 1s 内产生一个每秒写入 100M 的峰值,也不会因此被限制掉。

再看看 blkio.weight 。blkio 的 throttle 和 weight 方式和 cpu 子系统的 quota 和 shares 有点像,都是一种是绝对限制,另一种是相对限制,并且在不繁忙的时候可以充分利用资源,权重值的范围在 10 – 1000 之间。

测试权重方式要麻烦一点。因为不是绝对限制,所以会受到文件系统缓存的影响。如在虚拟机中测试,要关闭虚机如我用的 VirtualBox 在宿主机上的缓存。如要测试读 io 的效果,先生成两个几个 G 的大文件 /tmp/file_1,/tmp/file_2 ,可以用 dd 搞。然后设置两个权重

复制代码代码如下:
# echo 500 >/sys/fs/cgroup/blkio/foo/blkio.weight
# echo 100 >/sys/fs/cgroup/blkio/bar/blkio.weight
测试前清空文件系统缓存,以免干扰测试结果

复制代码代码如下:
sync
echo 3 >/proc/sys/vm/drop_caches
在这两个控制组中用 dd 产生 io 测试效果。

复制代码代码如下:
# cgexec -g "blkio:foo" dd if=/tmp/file_1 of=/dev/null &
[1] 1838
# cgexec -g "blkio:bar" dd if=/tmp/file_2 of=/dev/null &
[2] 1839

还是用 iotop 看看效果

复制代码代码如下:
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
1839 be/4 root 48.14 M/s 0.00 B/s 0.00 % 99.21 % dd if=/tmp/file_2 of=/dev/null
1838 be/4 root 223.59 M/s 0.00 B/s 0.00 % 16.44 % dd if=/tmp/file_1 of=/dev/null


 

参数说明

可设置的参数:

  • blkio.weight
    说明:指定 cgroup 默认可用 IO 的比例(加权),值的范围为 100 至 1000。该值可由具体设备的 blkio.weight_device 参数覆盖。
    示例:设置 cgroup lv0 的默认加权为 500: cgset -r blkio.weight=100 lv0
  • blkio.weight_device
    说明:指定 cgroup 中指定设备的可用 IO 比例(加权),范围是 100 至 1000。该值的的格式为 major:minor weight ,其中 major 和 minor 参考文档 Linux 分配的设备
    示例:设置 cgroup lv0 对 /dev/sda 的加权为 500: cgset -r blkio.weight_device="8:0 500" lv0
  • blkio.throttle.read_bps_device / blkio.throttle.write_bps_device
    说明:指定 cgroup 中某设备每秒钟读/写数据的字节上限。其格式为 major:minor bytes_per_second
    示例:设置 cgroup lv0 在 /dev/sdc 上每秒最多读 10KiB 数据: cgset -r blkio.throttle.read_bps_device="8:32 10240" lv0
  • blkio.throttle.read_iops_device / blkio.throttle.write_iops_device
    说明:指定 cgroup 中某设备每秒钟可以执行的读/写请求数上限。其格式为major:minor operations_per_second
    示例:设置 cgroup lv0 在 /dev/sdc 上每秒最多执行 1000 次读请求: cgset -r blkio.throttle.read_iops_device="8:32 1000" lv0

报告参数:

  • blkio.time
    报告 cgroup 对具体设备的 I/O 访问时间。条目有三个字段:majorminor 和timetime 的单位为毫秒(ms)
  • blkio.sectors
    报告 cgroup 对具体设备的扇区读写数。条目有三个字段:majorminor 和sectors
  • blkio.io_service_bytes
    报告 cgroup 对具体设备的读写字节数。条目有四个字段:majorminoroperation和 bytes。其中 operation 表示操作类型,包括 read, write, sync 和 async
  • blkio.io_serviced
    报告 cgroup 对具体设备的 I/O 操作数。条目有四个字段:majorminoroperation和 number
  • blkio.io_service_time
    报告 cgroup 对具体设备的 I/O 操作请求发送和请求完成之间的时间。条目有四个字段:majorminoroperation 和 time,其中 time 的单位为纳秒(ns)
  • blkio.io_wait_time
    报告 cgroup 对具体设备的 I/O 操作在队列中等待的时间。条目有四个字段:major,minoroperation 和 time,其中 time 的单位为纳秒(ns)
  • blkio.io_merged
    报告 cgroup 将 BIOS 请求合并到 I/O 操作请求的次数。条目有两个字段:number和 operation
  • blkio.io_queued
    报告 cgroup 为 I/O 操作排队的请求次数。条目有两个字段:number 和 operation
  • blkio.throttle.io_service_bytes
    报告 cgroup 限流对具体设备的读写字节数。blkio.io_service_bytes 与blkio.throttle.io_service_bytes 的不同之处在于,CFQ 调度请求队列时,前者不会更新。条目有四个字段:majorminoroperation 和 bytes
  • blkio.throttle.io_serviced
    报告 cgroup 限流对具体设备的读写操作数。条目有四个字段:majorminor,operation 和 number
  • blkio.reset_stats
    向该文件中写入一个整数,可以重置该 cgroup 中的报告计数。

blkio子系统使用心得

  1. 查看一个设备的 major 和 minor 可以使用:ls -l /dev/DEV
    例如,要查看 /dev/dm-0 的 major 和 minor

    ~ ] # ls -l /dev/dm-0
    brw -rw ----  1 root disk  253 ,  0 Dec  3 01:02  /dev /dm - 0

    其中 253, 0 即为 /dev/dm-0 的 major, minor

  2. blkio.throttle.* 的限制是针对整个 cgroup 组的,而不是针对组中单个进程的。
    例如,当设置 lv0 blkio.throttle.write_bps_device="253:0 1048576" 时,整个 lv0 组内所有进程向 /dev/dm-0 的写入速率之不能超过 1 MiB/秒。
  3. 经测试,对某个进程的 blkio 限制有可能影响 Cgroup 之外的进程。复现方法:
    /dev/sdb + /dev/sdc 做 flashcache,设置 lv0blkio.throttle.write_bps_device="8:32 1048576" ,即限制 lv0 内的进程对 /dev/sdc 的写入速率为 1MiB/秒,然后使用 cgexec -g blkio:lv0 dd if=/dev/zero of=/data0/testfile1 bs=10240 count=100000 启动一个在 lv0 限制下的 dd 向 flashcache 写文件。dd 很快便完成,但使用 iostat 观察,发现 /dev/sdc 的写入受 cgroup 限制,只有 1MiB/秒。这时我们再直接执行一个 dd: dd if=/dev/zero of=/data0/testfile1 bs=10240 count=100000,再使用 iostat 查看磁盘 IO 状态,/dev/sdc 写入速率仍然是 1MiB/秒,也就是说后面一个 dd 虽不在 cgroup lv0 限制之内,却也受到了 lv0 限流的影响。
  4. 进程对 pagecache 的读写操作不受 blkio.throttle.* 限制。


<think>嗯,用户问的是如何通过cgroup注入磁盘故障,需要具体的实现方法和配置指南。首先,我得回忆一下cgroup的功能,它主要是用来做资源控制和管理的,比如CPU、内存等。不过磁盘I/O方面,cgroup v1有blkio子系统,可以限制带宽和IOPS,但注入故障的话,可能不是直接支持的功能。 用户可能想模拟磁盘故障的情况,比如延迟、错误或者IO失败,来测试系统的容错能力。这时候可能需要结合其他工具,比如FUSE或者故障注入框架。比如使用dm-flakey设备映射目标,它可以模拟磁盘的间歇性故障。或者用libfiu库在用户空间进行注入。 然后,我需要分步骤说明如何配置cgroup来限制磁盘I/O,虽然这不能直接导致故障,但可以模拟高负载下的情况。接着,介绍使用dm-flakey的方法,这需要加载内核模块,创建虚拟设备,设置故障参数。这部分需要具体命令,比如dmsetup的使用。 另外,用户空间的故障注入工具比如fault_inject可能更灵活,可以动态触发错误。需要安装相应的工具,并配置触发条件和类型。还有FUSE文件系统的例子,编写一个简单的文件系统,在特定操作时返回错误,这样就能模拟磁盘故障。 需要注意权限问题,很多操作需要root权限,以及内核模块的加载。同时,测试环境要隔离,避免影响生产系统。最后,用户可能需要根据具体场景调整参数,比如错误类型和触发频率。 可能用户的需求是测试系统在磁盘故障下的行为,比如分布式系统的容错机制,或者文件系统的恢复能力。因此,除了配置方法,还要提醒用户注意安全,确保在受控环境中操作,避免数据丢失。</think>### 通过cgroup注入磁盘故障的实现方法 #### 一、cgroup磁盘I/O控制基础 1. **cgroup子系统选择** cgroup v1的$blkio$子系统可对块设备I/O进行限制,但**原生不支持故障注入**。需结合其他工具实现模拟故障效果[^1]。 2. **关键参数说明** - `blkio.throttle.read_bps_device`:限制读取速率 - `blkio.throttle.write_iops_device`:限制写入IOPS ```bash # 示例:限制/dev/sda写入IOPS为100 echo "8:0 100" > /sys/fs/cgroup/blkio/your_group/blkio.throttle.write_iops_device ``` #### 二、结合内核模块实现故障注入 1. **使用dm-flakey设备映射** ```bash # 1. 加载dm-flakey模块 modprobe dm-flakey # 2. 创建虚拟故障设备 echo "0 1048576 flakey /dev/sda1 10 180" | dmsetup create flakey-dev ``` - `10`:正常工作时间(秒) - `180`:故障保持时间(秒) 2. **通过cgroup绑定进程** ```bash # 将进程PID绑定到cgroup echo $PID > /sys/fs/cgroup/blkio/your_group/cgroup.procs ``` #### 三、用户空间故障注入方案 1. **使用fault_inject工具** ```bash # 安装工具 apt-get install fault-inject # 注入磁盘读取错误 echo "disk_read_fault 50" > /sys/kernel/debug/fail_make_request ``` 2. **自定义错误触发规则** ```bash # 设置错误概率为30%,最多触发5次 echo "probability=30 times=5" > /sys/kernel/debug/fail_make_request ``` #### 四、FUSE文件系统模拟(高级) ```python from fuse import FUSE, Operations class FaultFS(Operations): def read(self, path, size, offset, fh): if random.random() < 0.3: # 30%概率返回错误 raise IOError("Simulated disk fault") return os.pread(fh, size, offset) # 挂载故障模拟文件系统 FUSE(FaultFS(), '/mnt/faulty_disk', foreground=True) ``` #### 五、注意事项 1. 需要root权限执行操作 2. 建议在虚拟机或隔离环境测试 3. 故障注入可能导致数据损坏,需提前备份 4. 内核版本要求:建议≥4.19(完整支持dm-flakey)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值