当前位置:首页 > 文章列表 > 文章 > linux > Linux cgroup v2 io.max 如何限制设备带宽

Linux cgroup v2 io.max 如何限制设备带宽

来源:17golang原创 2026-09-12 11:05:18 0浏览 收藏

Linux 上想给某个服务限制磁盘读写,关键不是给挂载目录“限速”,而是把进程放进 cgroup v2,再在该 cgroup 的 io.max 中按块设备的 MAJ:MIN 写入上限。比如目标设备是 8:16,可以设置每秒最多读取 2 MiB、每秒最多写入 8 MiB;未配置的方向仍是 max

最小闭环是:确认 cgroup v2 和 io 控制器可用,创建专用 cgroup,向 io.max 写入设备号与 rbps/wbps,然后用 io.stat 和进程归属文件复查。限额到达后 I/O 会被延迟,短时突发仍可能出现。
要点速览
  • io.max 的键是设备主次号,不是 /data 这类路径。
  • rbps/wbps 是字节/秒,riops/wiops 是 I/O 次数/秒;写 max 可以移除某个限制。
  • 验证时要同时看进程是否在目标 cgroup,以及 io.stat 是否出现对应设备行。

io.max 限制的对象是设备,而不是挂载目录

cgroup v2 的资源控制是层级模型:进程先归属于一个 cgroup,控制器再针对这个层级中的资源消耗施加边界。io.max 由 I/O 控制器提供,配置行使用块设备的主设备号和次设备号,例如 8:16。因此,同一个挂载目录如果跨越多个块设备,就不能只写一个目录名来表达限制。

这个接口支持四个独立维度:rbpswbps 分别限制读、写字节速率;riopswiops 分别限制读、写 I/O 次数。它们可以在同一行按任意顺序组合。内核文档还特别说明,BPS 和 IOPS 按读写方向分别计量,达到限制时请求会延迟,但临时突发并不会被完全禁止。

Linux cgroup v2 io.max 将应用进程、工作负载 cgroup、设备主次号与读写字节速率边界关联起来的静态技术框图
图1:从应用进程到工作负载 cgroup,再到 io.max 的设备与读写速率字段,理解限额实际作用在哪个边界。
字段含义示例
MAJ:MIN块设备主次设备号8:16
rbps / wbps读 / 写字节每秒2097152
riops / wiops读 / 写 I/O 次数每秒120
max移除该字段的具体限制wiops=max

先确认 cgroup v2 和 io 控制器

先找出统一层级挂载点,不要假定所有发行版都使用相同目录。下面的检查只读取状态;真正写入控制器前,应确认你管理的是专用层级,并了解发行版的 systemd 是否会接管该目录。

# 查看 cgroup v2 的挂载点;输出为空时先处理层级配置
findmnt -t cgroup2 -o TARGET,FSTYPE,OPTIONS

# 以常见挂载点为例,确认 io 控制器是否对父级可用
CG=/sys/fs/cgroup
cat "$CG/cgroup.controllers"
cat "$CG/cgroup.subtree_control"

# 创建专用工作负载边界;生产环境请使用明确的服务生命周期管理
mkdir -p "$CG/limited-worker"
echo "+io" > "$CG/cgroup.subtree_control"
cat "$CG/limited-worker/cgroup.controllers"

控制器是向下分配的:父级没有在 cgroup.subtree_control 启用 io,子级就不能越过父级单独启用。不同发行版可能由 systemd 维护 cgroup 树;如果手工目录和服务管理器争用同一层级,重启或重新加载服务后配置可能被覆盖,最好选定一种管理方式并记录归属。

按主次设备号写入 rbps 与 wbps

用设备文件而不是挂载路径得到 MAJ:MIN。下面以示例设备 /dev/sdb 和工作负载目录为例:读限制设为 2 MiB/s,写限制设为 8 MiB/s。数值单位是字节,不是“MiB”字符串,因此 2 MiB 要写成 2097152

# 从块设备读取十进制主次设备号,避免凭路径猜设备
DEVICE=/dev/sdb
DEVNO=$(lsblk -no MAJ:MIN "$DEVICE")
CG=/sys/fs/cgroup/limited-worker

# 同一设备行一次写入读写字节上限;值按字节/秒计算
echo "$DEVNO rbps=2097152 wbps=8388608" > "$CG/io.max"

# 立即回读,确认未限制方向仍显示为 max
grep -F "$DEVNO" "$CG/io.max"

如果还要限制请求次数,可以在同一行加入 riops=wiops=。不要把同一个键在一行中重复写入;内核文档明确指出这种结果未定义。取消单项限制时保留设备号,只把对应值改为 max

# 只移除写字节速率限制,读限制保持不变
echo "$DEVNO wbps=max" > "$CG/io.max"
cat "$CG/io.max"

限额是 cgroup 对该设备的绝对边界,不是整块盘的性能承诺。父级已有更紧限制时,子级不能把它“放宽”;多个子 cgroup 的限额之和也不应被理解为设备一定能同时提供的吞吐量。

用 io.stat 和进程归属复查是否生效

只看到 io.max 的配置并不能证明目标服务正在受控。先把服务 PID 放入 cgroup,再检查三处:进程的 /proc/PID/cgroup、目标目录的 cgroup.procs,以及该 cgroup 的 io.stat

# 将已经启动的工作负载迁入目标 cgroup;写入 PID 会迁移该进程的线程组
PID=12345
echo "$PID" > "$CG/cgroup.procs"

# 两种方向交叉确认进程归属
grep '0::' "/proc/$PID/cgroup"
grep -Fx "$PID" "$CG/cgroup.procs"

# 按设备查看累计读写字节与 I/O 次数
grep -F "$DEVNO" "$CG/io.stat"

io.stat 里的常见字段包括 rbyteswbytesrioswios,设备行同样以 MAJ:MIN 标识。它适合确认统计归属和变化趋势,不应拿一次读数当成稳定带宽基准;需要判断限流效果时,应在固定负载下按时间窗口观察业务吞吐、请求延迟和 I/O 压力。

Linux cgroup v2 通过 PID、proc cgroup、cgroup.procs、io.max 和 io.stat 交叉确认设备限额归属的静态技术框图
图2:把进程归属检查与 io.max 配置、io.stat 设备统计放在同一张关系图中,避免只看配置不看实际观测。

上线前保留回退和审计边界

生产变更至少记录四项:目标服务和 PID 归属、设备的 MAJ:MIN、每个读写字段的旧值与新值、回退命令。若只想撤销限制,可以对相应字段写 max;若要整体删除临时 cgroup,应先停止或迁出其中进程,再按发行版管理方式清理目录。

还要注意缓存写回的边界。内核文档说明,cgroup writeback 需要底层文件系统支持,当前明确支持 ext2、ext4、btrfs、f2fs 和 xfs;其他文件系统的写回 I/O 可能归到 root cgroup。多个 cgroup 同时修改同一个 inode 时,归属也可能不符合直觉。因此,“配置回读正确”和“业务看到的吞吐下降”是两个都要观察的结果。

最终检查可以压缩成这张清单:父级有 io、目标目录有 io.max;设备号来自实际块设备;服务 PID 出现在目标 cgroup;io.stat 有对应设备行;systemd 或其他管理器不会在重启时覆盖配置;回退值和审计记录已保存。

相关问题

io.max 能直接限制某个挂载目录吗?

不能直接按目录匹配。它按块设备主次号生效;如果目录对应多个设备,需要分别确认并配置各设备。

rbps 和 riops 应该选哪个?

需要限制总读写量时选 BPS,需要限制请求频率时选 IOPS;两者可以组合,但都应结合实际负载观察,而不是只凭设备标称值设定。

为什么 io.stat 有数据但体感没有明显限速?

先确认 PID 在目标 cgroup,再看读写是否经过页缓存、写回文件系统是否支持,以及限制是否配置在真正发生 I/O 的设备上。

如何取消一个设备的写限制?

向该 cgroup 的 io.max 写入同一设备号和 wbps=max;回读文件确认该字段恢复为 max

参考资料

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go JSON 数字进 interface 后为什么变成 float64Go JSON 数字进 interface 后为什么变成 float64
上一篇
Go JSON 数字进 interface 后为什么变成 float64
ReadableStream 如何把 Fetch 响应分块显示到页面
下一篇
ReadableStream 如何把 Fetch 响应分块显示到页面
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    98次使用
  • OpenCompass大模型评测体系详解:功能、使用指南与应用场景
    OpenCompass
    OpenCompass是上海AI实验室推出的开源大模型评测平台,提供CompassKit、CompassHub和CompassRank三大核心组件,支持LLM及多模态模型的一站式标准化评估与排行榜查询。
    28次使用
  • SuperCLUE中文大模型评测基准:功能、能力维度与应用指南
    SuperCLUE
    SuperCLUE是权威的中文大语言模型综合评测基准,涵盖语言理解、知识应用、AI Agent智能体及安全性等12项核心能力。通过多轮对话与客观测试,定期发布榜单与技术报告,为模型研发、优化及行业选型提供科学依据。
    253次使用
  • C-Eval中文评测基准:大语言模型多学科能力评估指南
    C-Eval
    深入了解C-Eval中文评估套件,涵盖52个学科与4级难度。本文详解其功能特点、Zero-shot/Few-shot使用方法及代码示例,助您全面评测LLM中文理解与泛化能力。
    180次使用
  • AI Prompt Library:免费AI提示词库,助力ChatGPT高效创作与营销
    AI Prompt Library
    探索AI Prompt Library免费资源库,涵盖营销、写作及多场景AI提示词。兼容ChatGPT、Claude等工具,一键复制优化输出,提升工作效率。
    114次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码