Linux中限制容器IO性能的核心是使用cgroups的throttle硬性节流机制,而非weight权重;必须针对设备号(如8:0)配置blkio.throttle.{read|write}_{iops|bps}_device参数,确保IO走Direct I/O路径、路径匹配cgroup v1/v2版本,并建议IOPS与BPS组合设置以兼顾大小IO控制。

Linux 中限制容器 IO 性能,核心是用 cgroups 的 硬性节流机制,不是调权重、也不是靠调度优先级。真正起作用的是针对具体块设备的读写速率(bps)或操作次数(IOPS)限制,且必须匹配设备号、路径和 IO 类型。
关键:用 throttle,别信 weight
blkio.weight 是相对权重,只在多个容器争同一块盘时才生效;单容器下设成 10 也照样打满磁盘。它不提供任何绝对限制能力。真正能卡死 IO 的只有 throttle 类参数:
- 限每秒操作次数(IOPS):用
blkio.throttle.read_iops_device或blkio.throttle.write_iops_device - 限每秒字节数(带宽):用
blkio.throttle.read_bps_device或blkio.throttle.write_bps_device - 建议两者同时设置:只限 IOPS 容易放过大 IO(比如 1MB 一次),只限 BPS 控不住高频小 IO(比如 4KB × 5000 次/秒)
设备号和路径必须精准
规则写错、路径不对、时机不对,是限速失效最常见的原因:
- 查设备号:运行
ls -l /dev/sda,看到brw-rw---- 1 root disk 8, 0就说明主次号是8:0;/dev/sda1是8:1,不能混用 - cgroup 路径分 v1 和 v2:
– Docker 默认仍走 v1:路径为/sys/fs/cgroup/blkio/docker/<container-id>/
– Docker 20.10+ 默认用 v2:路径为/sys/fs/cgroup/docker/<container-id>/
混用就静默失败 - 写入时机:容器启动后 PID 稳定再操作,否则目录可能还没创建好
IO 类型决定是否生效
cgroups blkio throttle 只对 Direct I/O 生效。常规文件操作(如 echo > file、cp、rsync 默认模式)走 Buffered I/O:数据先进 PageCache,后续刷盘由内核调度,cgroups 管不到。
- 天然适配的场景: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 - 若用 Docker 命令启动,可直接加参数:
docker run --device-write-iops /dev/sda:200 --device-read-iops /dev/sda:200 ...(需 Docker ≥ 20.10 + 内核 ≥ 4.5)



















