blkio.weight 是相对权重,仅在多cgroup争用同一设备时生效,不保证绝对iops;blkio.throttle.write_bps_device(或write_iops_device)才能硬性限制每秒写入字节数(或次数),需严格匹配设备号maj:min且依赖调度器与cgroup版本。

blkio.weight 和 blkio.throttle.write_bps_device 有什么区别
直接说结论:blkio.weight 是相对权重,不保证绝对 IOPS;blkio.throttle.write_bps_device 才能真正限制每秒写入字节数(进而换算为 IOPS)。很多人误设 blkio.weight 后发现 IO 毫无变化,就是因为它只在多个 cgroup 竞争同一设备时才起作用,且不适用于单容器限速场景。
实操建议:
- 要硬性限制“每秒多少次读写”,必须用
blkio.throttle.read_iops_device或blkio.throttle.write_iops_device(内核 ≥ 4.5);老内核只能用bps类参数,再按平均 IO 大小反推 IOPS -
blkio.weight默认值是 500,范围 10–1000,但它对单个 cgroup 无效——哪怕你设成 10,只要没其他 cgroup 在争盘,它照样跑满 - 路径格式必须严格:设备号要用
MAJ:MIN,比如sda通常是8:0,查法是ls -l /dev/sda看主次设备号
如何给 Docker 容器设置每秒 200 次写 IO 限制
Docker 默认不暴露 blkio IOPS 接口,得手动进 cgroup 目录操作,或者用 --blkio-weight-device(仅权重)或 --device-read-iops(需 Docker 20.10+ + 内核 ≥ 4.5)。
实操建议:
- 确认内核支持:
cat /proc/cgroups | grep blkio,确保已启用;再查/sys/fs/cgroup/blkio/下是否有throttle.*_iops_device - 如果用
docker run,优先加参数:docker run --device-read-iops /dev/sda:200 --device-write-iops /dev/sda:200 ... - 若 Docker 版本低或需要更细粒度控制,先启动容器,再进其 cgroup 目录:
echo "8:0 200" > /sys/fs/cgroup/blkio/docker/<container-id>/blkio.throttle.write_iops_device</container-id> - 注意:IOPS 是针对设备的,不是文件或分区;
/dev/sda和/dev/sda1的设备号不同,不能混用
为什么设了 throttle 却没生效
常见错误不是参数写错,而是路径、时机或权限没对上。最典型的三个坑:
- cgroup 路径不对:Docker 20.10+ 默认用
systemd驱动,cgroup v2 路径是/sys/fs/cgroup/docker/<id>/</id>,但 v1 是/sys/fs/cgroup/blkio/docker/<id>/</id>;混用就静默失败 - 设备号填错:
echo "8:1 200" > ...中的8:1对应sda1,但容器实际 IO 走的是sda(8:0),限速自然不触发 - IO 类型不匹配:设了
write_iops_device,但压测用的是dd if=/dev/zero of=test bs=4k—— 这种小块写会触发大量元数据操作,实际 IOPS 计数可能被绕过;换成oflag=direct或用fio更准
blkio IOPS 限制的实际效果受哪些因素影响
这不是开关式控制,底层依赖 CFQ 或 mq-deadline 调度器,且和 IO 大小、队列深度强相关。
实操建议:
- 小 IO(4K)和大 IO(1M)下,同样 200 IOPS 对应的带宽差 256 倍;压测时务必明确单位是「次数」还是「字节」
- 使用
cfq调度器时,throttle类参数才稳定;none(如 NVMe)或kyber可能忽略部分限速 - 容器里进程用
O_DIRECT或绕过 page cache,限速更准;走 buffer cache 的写入可能被延迟合并,导致瞬时 IOPS 突破限制 - 别忘了检查
blkio.io_service_bytes和blkio.io_serviced—— 这才是验证是否真被限住的依据,而不是只看 top 或 iostat
真正卡住 IOPS 的地方,往往不在你写的那行 echo 命令,而在设备调度器类型、IO 路径是否经过被限速的设备节点、以及 cgroup 版本与 Docker 的对接方式。调不通时,先 cat /sys/block/sda/queue/scheduler 和 find /sys/fs/cgroup/blkio -name "*iops*" 看两眼。











