15.10.3 磁盘与IO限制策略
3. 磁盘与IO限制策略#
磁盘与IO限制主要依赖 cgroups 的 blkio(v1)或 io(v2)控制器,通过配额与权重限制容器读写吞吐与 IOPS,避免单容器抢占磁盘导致整体抖动。适用于数据库容器隔离、日志批处理限速与多容器混部公平调度。
原理草图(Docker -> cgroups -> Block Device)
限制维度与策略选择
- 带宽限制(BPS):限制顺序读写吞吐,适合备份/归档。
- IOPS限制:限制随机IO请求数,适合数据库抑制抖动。
- 权重(weight):争抢时相对优先级,非硬上限。
环境与工具准备(安装)#
1)检查 cgroup 版本
# v1 通常看到 /sys/fs/cgroup/blkio
ls /sys/fs/cgroup/blkio 2>/dev/null && echo "cgroup v1"
# v2 通常看到 /sys/fs/cgroup/io
ls /sys/fs/cgroup/io 2>/dev/null && echo "cgroup v2"
2)安装压测与观测工具
# 以 Debian/Ubuntu 为例
sudo apt-get update
sudo apt-get install -y fio sysstat
# 说明:
# fio 用于IO压测
# sysstat 提供 iostat, pidstat 等监控工具
关键参数与命令解释(Docker)#
常用参数(cgroup v1/部分v2兼容)
- --device-read-bps /dev/sdX:20mb:读带宽限制 20MB/s
- --device-write-bps /dev/sdX:10mb:写带宽限制 10MB/s
- --device-read-iops /dev/sdX:1000:读IOPS限制 1000
- --device-write-iops /dev/sdX:500:写IOPS限制 500
- --blkio-weight 300:权重 10–1000,数值大优先级高
完整示例:限速 + 压测 + 验证#
1)启动受限容器
# 说明:
# --device-read-bps /dev/sda:20mb 限制读带宽
# --device-write-bps /dev/sda:10mb 限制写带宽
# --device-read-iops /dev/sda:1000 限制读IOPS
# --device-write-iops /dev/sda:500 限制写IOPS
docker run -d --name io-limit-demo \
--device-read-bps /dev/sda:20mb \
--device-write-bps /dev/sda:10mb \
--device-read-iops /dev/sda:1000 \
--device-write-iops /dev/sda:500 \
ubuntu:22.04 sleep infinity
2)在容器内安装压测工具并执行
docker exec -it io-limit-demo bash
# 容器内执行:
apt-get update && apt-get install -y fio
# 顺序写压测 (带宽)
fio --name=write_test --filename=/tmp/fio.dat \
--rw=write --bs=1m --size=1g --ioengine=libaio \
--direct=1 --numjobs=1 --iodepth=8
# 随机读压测 (IOPS)
fio --name=randread_test --filename=/tmp/fio.dat \
--rw=randread --bs=4k --size=1g --ioengine=libaio \
--direct=1 --numjobs=1 --iodepth=32
预期效果:fio 输出的 bw(带宽)与 iops 应接近限制值。
3)宿主机观测
# 查看容器PID并观察IO
PID=$(docker inspect --format '{{.State.Pid}}' io-limit-demo)
sudo pidstat -d -p $PID 1
# 查看设备整体IO
iostat -dx 1
cgroup v2 说明与验证#
1)cgroup v2 文件检查
# 容器进程所在 cgroup 路径
cat /proc/$PID/cgroup
# v2 统一层级下的 io.max, io.weight
sudo grep . /sys/fs/cgroup/system.slice/docker-*.scope/io.{max,weight} 2>/dev/null
2)常见兼容性说明
- v2 使用 io.max 和 io.weight,单位与写法不同。
- 对虚拟设备(loop、dm-crypt)限制可能不生效,应指向底层块设备。
排错清单(常见问题与处理)#
1)限制不生效
# 检查是否针对正确设备
lsblk -f
# 确认容器写入路径所在磁盘设备是 /dev/sda 还是 /dev/nvme0n1
处理:重新指定正确块设备,例如 /dev/nvme0n1。
2)fio 结果高于限制
- 可能因为缓存影响(page cache)。
处理:使用 --direct=1 并清理缓存后重测:
sudo sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3)cgroup v2 参数不生效
- Docker 版本或内核不支持。
处理:确认 docker info 中 Cgroup Version,升级 Docker/内核。
练习#
- 同时启动两个容器,一个
--blkio-weight 100,一个--blkio-weight 900,用fio压测,观察带宽差异。 - 对数据库容器设置
--device-read-iops和--device-write-iops,记录 TPS 是否稳定。 - 切换到 NVMe 设备(/dev/nvme0n1)进行限制测试,比较传统 SATA 设备表现差异。