关键不是设权重,而是用throttle.write_iops_device或throttle.read_iops_device做硬性节流,需确保io走direct i/o路径、设备号准确(如8:0)、cgroup路径正确(v1为/sys/fs/cgroup/blkio/docker//),并建议iops与bps组合设置以兼顾小io频率和大io带宽。

要限制单个容器的磁盘IOPS、真正规避“邻居干扰”,关键不是设权重,而是用 throttle.write_iops_device 或 throttle.read_iops_device 做硬性节流,并确保IO路径落在blkio管控范围内——否则限速形同虚设。
必须用 throttle,别信 weight
blkio.weight 是相对权重,只在多个cgroup同时争用同一块设备时才起作用。单容器场景下,哪怕设成10(最低值),只要没其他cgroup在抢盘,它照样跑满。这不是配置错误,是设计如此。真正能卡死每秒操作次数的,只有 throttle 类参数。
- 写IOPS限制:写入
8:0 200到blkio.throttle.write_iops_device - 读IOPS限制:写入
8:0 150到blkio.throttle.read_iops_device - 设备号必须准确:
ls -l /dev/sda查主次设备号,8:0 是 sda,8:1 是 sda1,不能混用
确认IO走的是Direct I/O路径
blkio throttle 只对 Direct I/O 生效。常规文件写(如日志重定向 > app.log、cp、rsync 默认模式)走的是 Buffered I/O:数据先进 PageCache,后续刷盘由内核调度,blkio管不到这段。
- 数据库类服务(MySQL +
innodb_flush_method=O_DIRECT、PostgreSQL 默认)天然适配 - 压测验证务必加
oflag=direct:例如dd if=/dev/zero of=/mnt/test bs=4k count=10000 oflag=direct - 普通应用若需限速,应配合调整内核参数(如
vm.dirty_ratio)或改用支持 O_DIRECT 的工具
选对cgroup路径与时机
Docker 20.10+ 默认启用 cgroup v2,但多数生产环境仍跑在 v1 上;路径错位会导致静默失败。
- cgroup v1 路径:
/sys/fs/cgroup/blkio/docker/<container-id>/</container-id> - cgroup v2 路径:
/sys/fs/cgroup/docker/<container-id>/</container-id> - 启动后立即写入:容器PID稳定后再 echo 设备限速值,避免因路径未就绪而失效
- 权限检查:操作需 root 权限,且确保 blkio 子系统已启用(
cat /proc/cgroups | grep blkio应有输出)
建议组合设置,兼顾IOPS与吞吐量
单设 IOPS 可能放行超大IO请求(如一次写 1MB),瞬间占满带宽;单设 BPS 又可能不限制高频率小IO(如大量 4K 随机写)。两者并用更稳妥:
-
echo "8:0 1000" > blkio.throttle.write_iops_device(最多1000次/秒) -
echo "8:0 52428800" > blkio.throttle.write_bps_device(最多50MB/s) - 测试时用
iostat -x 1观察w/s和write KB/s是否双双被卡在设定值附近











