实现CPU、内存、I/O资源的精细化控制
1. 什么是Linux Cgroup
Linux Control Group(简称Cgroup)是Linux内核提供的一种强大的资源管理机制,它允许我们将任意进程进行分组化管理,并对每个分组分配特定的系统资源。这些资源包括CPU、内存、块设备I/O、网络带宽等核心系统资源。
Cgroup的核心价值在于资源隔离与精细化控制。在实际应用中,无论是服务器虚拟化、容器技术(如Docker、LXC),还是多用户共享服务器资源的场景,Cgroup都扮演着关键角色。它解决了传统Linux系统中资源分配"一刀切"的问题,让系统管理员可以根据业务优先级灵活分配资源。
Cgroup的核心组成
- 控制组(Cgroup):进程的集合,通过虚拟文件系统呈现为目录结构
- 子系统(Subsystem):具体的资源控制器,如CPU控制器、内存控制器等
- 虚拟文件系统(cgroupfs):用户与内核交互的接口,通过文件读写完成配置

图1:Linux Cgroup核心架构示意图
2. Cgroup基础操作:挂载与配置
Cgroup通过特殊的虚拟文件系统(cgroupfs)提供用户接口。所有配置操作本质上都是对该文件系统中的文件进行读写。下面我们从基础的挂载操作开始,逐步掌握Cgroup的使用方法。
2.1 挂载cgroup文件系统
默认情况下,部分Linux发行版(如CentOS、Ubuntu)已自动挂载cgroup。我们可以手动挂载特定子系统,以CPU和内存控制器为例:
# 创建挂载点 mkdir -p /sys/fs/cgroup/cpu_and_mem # 挂载CPU和内存子系统 mount -t cgroup -o cpu,memory cgroup /sys/fs/cgroup/cpu_and_mem
2.2 创建与管理控制组
在挂载点下创建目录即创建了一个新的控制组,系统会自动在目录中生成该子系统对应的配置文件:
# 创建两个控制组:high_priority(高优先级)和low_priority(低优先级) cd /sys/fs/cgroup/cpu_and_mem mkdir high_priority low_priority # 查看控制组的默认配置文件 ls high_priority/ # 输出包含:cgroup.procs cpu.cfs_period_us cpu.cfs_quota_us memory.limit_in_bytes tasks
提示:tasks文件记录了该控制组中所有进程的PID;cgroup.procs记录的是进程组ID。向这两个文件写入PID即可将进程加入对应控制组。
3. 实战:CPU资源精细化控制
CPU子系统允许我们限制控制组的CPU使用时间。核心配置参数是cpu.cfs_period_us和cpu.cfs_quota_us,这两个参数共同定义了CPU的分配比例。
cpu.cfs_period_us:CPU调度周期(微秒),默认100000微秒(100ms)
cpu.cfs_quota_us:该周期内允许使用的CPU时间(微秒),默认-1表示无限制
3.1 配置CPU使用率限制
示例:限制low_priority控制组最多使用50%的CPU资源,high_priority控制组使用无限制CPU:
# 配置low_priority控制组CPU使用率50% cd /sys/fs/cgroup/cpu_and_mem/low_priority # 设置周期为100ms echo 100000 > cpu.cfs_period_us # 设置配额为50ms(100ms周期内最多使用50ms,即50%) echo 50000 > cpu.cfs_quota_us # high_priority控制组保持默认无限制配置 cd ../high_priority echo -1 > cpu.cfs_quota_us
3.2 将进程加入CPU控制组
启动一个CPU密集型进程(如无限循环脚本),并将其加入低优先级控制组:
# 后台运行CPU密集型进程 while :; do :; done & # 查看进程PID(假设为12345) echo $! # 将进程加入low_priority控制组 echo 12345 > /sys/fs/cgroup/cpu_and_mem/low_priority/tasks

图2:CPU控制组资源分配效果图
4. 实战:内存资源限制
内存子系统可以限制控制组的最大内存使用量,防止某个进程过度占用内存导致系统OOM(Out of Memory)。核心配置文件包括memory.limit_in_bytes(最大内存限制)和memory.swappiness(交换分区使用策略)。
4.1 配置内存硬限制
示例:限制low_priority控制组最大使用100MB内存,high_priority控制组最大使用500MB内存:
# 配置low_priority控制组内存限制100MB cd /sys/fs/cgroup/cpu_and_mem/low_priority echo $((100 * 1024 * 1024)) > memory.limit_in_bytes # 100MB # 配置high_priority控制组内存限制500MB cd ../high_priority echo $((500 * 1024 * 1024)) > memory.limit_in_bytes # 500MB # 设置swappiness为0,尽量不使用交换分区 echo 0 > memory.swappiness
4.2 监控内存使用情况
Cgroup提供了内存使用统计文件,可实时查看控制组的内存占用情况:
# 查看low_priority控制组内存使用统计 cat /sys/fs/cgroup/cpu_and_mem/low_priority/memory.stat # 关键输出项: # cache: 缓存使用量 # rss: 进程实际使用的物理内存 # swap: 交换分区使用量
注意:当进程内存使用量超过限制时,内核会触发OOM Killer终止该控制组内的进程。可以通过memory.oom_control文件禁用OOM Killer,但不建议在生产环境使用。
5. 实战:Block I/O资源控制
块设备I/O子系统(blkio)用于控制进程对磁盘等块设备的I/O优先级和带宽。在混合部署场景中(如数据库服务与日志服务共存),该功能可以防止日志写入占用过多I/O资源,导致数据库响应缓慢。
5.1 挂载blkio子系统
# 创建并挂载blkio控制组 mkdir -p /sys/fs/cgroup/blkio mount -t cgroup -o blkio blkio /sys/fs/cgroup/blkio
5.2 配置I/O权重
通过blkio.weight设置I/O优先级权重(范围100-1000,默认500),权重值越大,获得的I/O资源越多:
# 创建数据库和日志两个控制组 cd /sys/fs/cgroup/blkio mkdir db_group log_group # 数据库组设置高优先级(权重1000) cd db_group echo 1000 > blkio.weight # 日志组设置低优先级(权重100) cd ../log_group echo 100 > blkio.weight # 将数据库进程加入db_group echo 12345 > tasks # 12345为数据库进程PID

图3:Block I/O权重分配示意图
6. Cgroup的典型应用场景
Cgroup作为底层技术,已广泛应用于各种Linux系统资源管理场景中,以下是几个典型应用:
6.1 容器技术基石
Docker、LXC等容器技术的底层资源隔离完全依赖Cgroup实现。每个容器本质上就是一个独立的Cgroup集合,容器的CPU、内存限制都是通过Cgroup配置实现的。
6.2 服务器资源共享
在多用户共享的服务器上,可以为每个用户创建独立的Cgroup,限制其资源使用上限,防止单个用户的程序占用过多资源影响其他用户。
6.3 关键服务保障
对数据库、核心API等关键服务设置高优先级资源分配,确保在系统负载高峰时,核心业务依然能获得充足的CPU、内存和I/O资源。
| 应用场景 | 核心控制子系统 | 配置要点 |
|---|---|---|
| 容器隔离 | CPU、内存、blkio、网络 | 全面限制各资源上限,实现完全隔离 |
| 数据库服务 | CPU、内存、blkio | 高CPU权重、充足内存、优先I/O |
| 日志采集服务 | CPU、blkio | 低CPU使用率、低I/O权重 |
7. 注意事项与最佳实践
7.1 注意事项
- Cgroup配置不会自动持久化,系统重启后配置会丢失,需通过启动脚本或systemd服务实现自动配置
- 子系统之间存在依赖关系,如内存子系统依赖CPU子系统时,需同时挂载相关子系统
- 避免过度限制资源,导致关键进程无法正常运行
7.2 最佳实践
- 按业务类型划分控制组,如核心服务组、普通服务组、后台任务组
- 结合
systemd管理Cgroup,现代Linux发行版已原生支持通过systemd配置Cgroup - 定期监控控制组资源使用情况,根据业务变化动态调整配置

1076

被折叠的 条评论
为什么被折叠?



