关键不是设权重,而是用throttle.read_iops_device/write_iops_device和throttle.read_bps_device/write_bps_device做硬性节流,需确保IO走Direct I/O路径、设备号准确(如8:0)、cgroup路径正确(v1为/sys/fs/cgroup/blkio/docker/<id>/),并建议IOPS与BPS组合设置。

要真正限制容器进程的磁盘 I/O,关键不是调优先级或设权重,而是用 cgroups 的硬性节流机制——针对设备号写入 throttle 规则,并确保 IO 走的是 Direct I/O 路径。
必须用 throttle,别信 weight
blkio.weight 是相对权重,只在多个容器争同一块盘时才起作用。单容器场景下,哪怕设成最低值 10,只要没其他竞争者,它照样打满磁盘。这不是配置错,是设计如此。真正能卡死每秒读写次数或带宽的,只有 throttle 类参数:
-
限 IOPS(操作次数):用
blkio.throttle.read_iops_device或blkio.throttle.write_iops_device -
限吞吐量(字节数):用
blkio.throttle.read_bps_device或blkio.throttle.write_bps_device - 两者建议同时设置,避免只限 IOPS 放过大 IO、只限 BPS 不控高频小 IO
设备号和路径必须精准匹配
规则无效,十有八九栽在这两处:
-
查设备号:运行
ls -l /dev/sda,看到brw-rw---- 1 root disk 8, 0就说明主次号是8:0;NVMe 盘如/dev/nvme0n1通常是259:0,不能凭名字猜 -
选对 cgroup 路径:Docker 默认仍跑 cgroup v1,路径是
/sys/fs/cgroup/blkio/docker/<container-id>/;若用 v2(Docker 20.10+ 默认),路径是/sys/fs/cgroup/docker/<container-id>/,混用就静默失效 - 写入时机:容器启动后 PID 稳定再操作,否则目录可能还没创建好
IO 路径决定限速是否生效
cgroups blkio throttle 只对 Direct I/O 生效。常规文件操作(如 echo "log" > app.log、cp、rsync 默认模式)走 Buffered I/O:数据先进 PageCache,后续刷盘由内核调度,blkio 管不到。
-
天然适配的场景:MySQL(
innodb_flush_method=O_DIRECT)、PostgreSQL、MongoDB 默认配置、dd oflag=direct -
普通应用想生效:要么改用支持 O_DIRECT 的工具,要么配合调内核参数(如
vm.dirty_ratio控制脏页回写节奏) -
验证务必加
oflag=direct:比如dd if=/dev/zero of=/mnt/test bs=4k count=10000 oflag=direct
操作示例:给容器限 200 写 IOPS + 50MB/s 带宽
假设容器 ID 是 abc123,目标设备是 /dev/sda(设备号 8:0),cgroup v1 环境:
- 限制写 IOPS:
echo "8:0 200" > /sys/fs/cgroup/blkio/docker/abc123/blkio.throttle.write_iops_device - 限制写带宽:
echo "8:0 52428800" > /sys/fs/cgroup/blkio/docker/abc123/blkio.throttle.write_bps_device - 验证是否写入成功:
cat /sys/fs/cgroup/blkio/docker/abc123/blkio.throttle.write_iops_device - 实时观察效果:
iostat -x 1看w/s和wkB/s是否被卡在设定值附近


















