3、cgroup CPU 子系统基础:核心文件解析
在容器化环境中,CFS(Completely Fair Scheduler)通过 cgroup CPU 子系统的四个关键文件实现 CPU 资源的分配与限制。理解 cpu.shares、cpu.cfs_period_us、cpu.cfs_quota_us 和 cpu.stat 是配置容器 CPU 组调度的基础。本节将逐一解析每个文件的作用、参数含义及典型配置。
3.1 文件概览与功能对比
下表列出了 cgroup CPU 子系统的核心文件及其在 CFS 调度中的角色:
| 文件名 | 作用域 | 控制粒度 | 默认值 | 典型场景 |
|---|---|---|---|---|
cpu.shares |
相对权重 | CPU 时间比例 | 1024 | 多容器按比例分配 CPU |
cpu.cfs_period_us |
周期长度 | 微秒(μs) | 100000 | 定义配额计算的时间窗口 |
cpu.cfs_quota_us |
硬性上限 | 微秒(μs) | -1(无限制) | 限制容器最大 CPU 使用量 |
cpu.stat |
统计信息 | 只读 | — | 监控调度延迟与限流情况 |
关键概念区分:
cpu.shares 仅在 CPU 资源竞争时生效,属于“软限制”;cpu.cfs_quota_us 无论是否竞争都强制生效,属于“硬限制”。两者配合使用可实现精细化的 CPU 资源管控。
3.2 cpu.shares —— 相对权重分配
cpu.shares 定义了 cgroup 在 CPU 时间竞争中的相对权重。当多个 cgroup 同时需要 CPU 时,调度器按 shares 值的比例分配 CPU 时间。该值是一个整数,默认值为 1024。
工作原理:
- 假设两个 cgroup A 和 B,shares 分别为 1024 和 2048。
- 当两者都满负荷运行时,A 获得约 1/3 的 CPU 时间,B 获得约 2/3。
- 如果只有一个 cgroup 活跃,它可以占用全部 CPU 资源(不受 shares 限制)。
配置示例:为容器设置 shares 为 2048,使其在竞争时获得两倍于默认容器的 CPU 时间。
# 设置 cpu.shares 为 2048
echo 2048 > /sys/fs/cgroup/cpu/docker/container1/cpu.shares
# 验证当前值
cat /sys/fs/cgroup/cpu/docker/container1/cpu.shares
# 输出:2048
3.3 cpu.cfs_period_us 与 cpu.cfs_quota_us —— 硬性上限控制
这两个文件配合使用,实现 CFS 配额机制,对 cgroup 的 CPU 使用量进行硬性限制。
cpu.cfs_period_us:一个调度周期的时间长度,单位为微秒(μs),默认值 100000(即 100ms)。cpu.cfs_quota_us:在每个周期内,cgroup 允许使用的最大 CPU 时间,单位为微秒(μs)。默认值 -1 表示无限制。
配额计算方式:
- 有效 CPU 核心数 =
cpu.cfs_quota_us/cpu.cfs_period_us - 例如:
quota = 200000,period = 100000,则限制为 2 个 CPU 核心。 - 例如:
quota = 50000,period = 100000,则限制为 0.5 个 CPU 核心。
注意事项:当
cpu.cfs_quota_us 设置过小(如小于一个调度 tick)时,可能导致容器频繁被限流,引发调度延迟。建议生产环境中 quota 值至少为 period 的 10%。
3.4 cpu.stat —— 调度统计与限流监控
cpu.stat 是一个只读文件,提供 cgroup 的 CPU 调度统计信息,用于监控容器是否被限流以及调度延迟情况。
文件内容示例:
nr_periods 1000
nr_throttled 45
throttled_time 12345678
nr_bursts 0
burst_time 0
字段含义:
| 字段名 | 类型 | 说明 |
|---|---|---|
nr_periods |
整数 | 自 cgroup 创建以来经历的调度周期总数 |
nr_throttled |
整数 | 被限流的周期数(即 CPU 使用超过 quota 的周期) |
throttled_time |
纳秒 | 累计被限流的总时间(纳秒) |
nr_bursts |
整数 | 发生突发(burst)的次数(需内核支持 CPU burst 特性) |
burst_time |
纳秒 | 累计突发使用的时间(纳秒) |
监控指标解读:
- 限流率 = nr_throttled / nr_periods:反映容器被限流的频率。限流率过高(如 > 5%)说明 quota 设置偏小,需考虑扩容。
- throttled_time:累计限流时间持续增长,表明容器频繁等待 CPU 资源,可能影响业务延迟。
- nr_bursts / burst_time:如果 burst 值持续增长,说明容器在利用突发能力弥补短期性能缺口。
3.5 综合配置案例
以下是一个完整的 cgroup CPU 子系统配置示例,展示如何同时使用 shares、quota 和 period 控制容器 CPU 资源:
# 创建 cgroup 目录
mkdir -p /sys/fs/cgroup/cpu/demo_container
# 设置相对权重(竞争时获得 2 倍默认权重)
echo 2048 > /sys/fs/cgroup/cpu/demo_container/cpu.shares
# 设置调度周期为 100ms(默认值)
echo 100000 > /sys/fs/cgroup/cpu/demo_container/cpu.cfs_period_us
# 设置配额为 150ms(限制为 1.5 个 CPU 核心)
echo 150000 > /sys/fs/cgroup/cpu/demo_container/cpu.cfs_quota_us
# 将进程 PID 加入 cgroup
echo 12345 > /sys/fs/cgroup/cpu/demo_container/tasks
# 查看统计信息
cat /sys/fs/cgroup/cpu/demo_container/cpu.stat
最佳实践:在容器化环境中,建议将
cpu.cfs_period_us 保持为默认值 100ms,仅调整 cpu.cfs_quota_us 和 cpu.shares。频繁修改 period 值可能导致调度器行为异常,且对大多数应用场景无额外收益。