3. Cgroups CPU子系统:cgroups v1与v2概述、cpu.shares与cpu.weight、cpu.cfs_period_us与cpu.cfs_quota_us
CPU 子系统是 cgroups 中控制容器 CPU 资源分配的核心模块。理解 cgroups v1 与 v2 的架构差异、权重分配机制以及带宽控制参数,是进行容器 CPU 绑核与性能调优的基础。本节将系统梳理这些关键概念。
3.1 cgroups v1 与 v2 概述
cgroups(Control Groups)自 Linux 2.6.24 引入以来,经历了从 v1 到 v2 的重大演进。v1 采用多层级、多挂载点的树形结构,每个子系统独立挂载;v2 则统一为单层级树,所有子系统挂载在同一根目录下,解决了 v1 中进程在不同子系统间不一致的问题。
| 对比维度 | cgroups v1 | cgroups v2 |
|---|---|---|
| 层级结构 | 多层级树,每个子系统独立挂载 | 单层级树,所有控制器统一挂载 |
| 进程归属 | 进程可在不同子系统属于不同 cgroup | 进程只能属于一个 cgroup 节点 |
| CPU 控制器 | cpu、cpuacct 分离 | cpu 控制器合并统计与限制 |
| 权重接口 | cpu.shares |
cpu.weight |
| 带宽控制 | cpu.cfs_period_us + cpu.cfs_quota_us |
cpu.max(格式:quota period) |
| 实时调度 | cpu.rt_period_us + cpu.rt_runtime_us |
暂不支持实时控制器 |
3.2 cpu.shares 与 cpu.weight:CPU 权重分配
CPU 权重决定了多个 cgroup 在 CPU 资源竞争时的分配比例。v1 使用 cpu.shares,v2 使用 cpu.weight,两者本质都是相对权重,而非限制。
3.2.1 cpu.shares(cgroups v1)
cpu.shares 的默认值为 1024,取值范围为 2~262144。当多个 cgroup 中的进程同时争用 CPU 时,调度器按 shares 比例分配 CPU 时间。如果只有一个 cgroup 有进程运行,它可以占用全部 CPU 资源。
# 创建两个 cgroup 并设置不同的 shares
mkdir -p /sys/fs/cgroup/cpu/group_high /sys/fs/cgroup/cpu/group_low
echo 2048 > /sys/fs/cgroup/cpu/group_high/cpu.shares
echo 512 > /sys/fs/cgroup/cpu/group_low/cpu.shares
# 将进程 PID 加入对应 cgroup
echo $PID_HIGH > /sys/fs/cgroup/cpu/group_high/tasks
echo $PID_LOW > /sys/fs/cgroup/cpu/group_low/tasks
# 此时 group_high 与 group_low 的 CPU 分配比例为 2048:512 = 4:1
3.2.2 cpu.weight(cgroups v2)
cpu.weight 的默认值为 100,取值范围为 1~10000。v2 使用线性权重模型,计算更直观。v2 还提供了 cpu.weight.nice 接口,允许通过 nice 值(-20~19)映射到权重。
# cgroups v2 设置权重
mkdir -p /sys/fs/cgroup/group_high /sys/fs/cgroup/group_low
echo 200 > /sys/fs/cgroup/group_high/cpu.weight
echo 50 > /sys/fs/cgroup/group_low/cpu.weight
# 将进程写入 cgroup.procs
echo $PID_HIGH > /sys/fs/cgroup/group_high/cgroup.procs
echo $PID_LOW > /sys/fs/cgroup/group_low/cgroup.procs
# 分配比例 200:50 = 4:1
| 参数 | 所属版本 | 默认值 | 取值范围 | 权重模型 |
|---|---|---|---|---|
cpu.shares |
v1 | 1024 | 2 ~ 262144 | 相对比例 |
cpu.weight |
v2 | 100 | 1 ~ 10000 | 线性权重 |
cpu.weight.nice |
v2 | 0 | -20 ~ 19 | nice 映射 |
3.3 cpu.cfs_period_us 与 cpu.cfs_quota_us:CPU 带宽控制
CFS(Completely Fair Scheduler)带宽控制提供了 CPU 使用的硬限制。通过 cpu.cfs_period_us 和 cpu.cfs_quota_us 两个参数,可以精确限制一个 cgroup 在指定周期内最多使用的 CPU 时间。
3.3.1 参数含义
- cpu.cfs_period_us:带宽控制周期,单位微秒(µs),默认 100000(100ms),取值范围 1000~1000000。
- cpu.cfs_quota_us:在每个周期内允许使用的 CPU 时间,单位微秒(µs),默认 -1(不限制)。
通过这两个参数可以计算出 cgroup 能使用的 CPU 核心数上限:
CPU 核心数上限 = cpu.cfs_quota_us / cpu.cfs_period_us
示例:
period = 100000 µs(100ms)
quota = 200000 µs(200ms)
→ 可使用 2 个 CPU 核心
period = 100000 µs
quota = 50000 µs(50ms)
→ 可使用 0.5 个 CPU 核心
3.3.2 实际配置示例
# 限制 cgroup 最多使用 1.5 个 CPU 核心
echo 100000 > /sys/fs/cgroup/cpu/mycontainer/cpu.cfs_period_us
echo 150000 > /sys/fs/cgroup/cpu/mycontainer/cpu.cfs_quota_us
# 限制 cgroup 最多使用 4 个 CPU 核心
echo 100000 > /sys/fs/cgroup/cpu/mycontainer/cpu.cfs_period_us
echo 400000 > /sys/fs/cgroup/cpu/mycontainer/cpu.cfs_quota_us
# 取消限制(恢复为不限制)
echo -1 > /sys/fs/cgroup/cpu/mycontainer/cpu.cfs_quota_us
3.3.3 cgroups v2 中的对应接口
在 cgroups v2 中,带宽控制通过 cpu.max 文件统一管理,格式为 $MAX $PERIOD:
# 限制最多使用 1.5 个 CPU 核心
echo "150000 100000" > /sys/fs/cgroup/mycontainer/cpu.max
# 取消限制
echo "max 100000" > /sys/fs/cgroup/mycontainer/cpu.max
3.4 权重与带宽的协同使用
在实际容器编排中,权重和带宽控制通常配合使用:
- 带宽控制(硬限制):通过
cfs_quota_us设定容器 CPU 使用上限,防止单个容器抢占过多资源。 - 权重分配(软保证):通过
cpu.shares或cpu.weight设定容器在 CPU 争用时的优先级。
spec.containers[].resources.limits.cpu→ 映射为cpu.cfs_quota_us/cpu.cfs_period_usspec.containers[].resources.requests.cpu→ 映射为cpu.shares(v1)或cpu.weight(v2)
3.5 性能调优注意事项
| 场景 | 推荐配置 | 说明 |
|---|---|---|
| 延迟敏感型应用 | quota 略高于实际需求 | 避免频繁节流导致延迟抖动 |
| 批处理任务 | quota 精确匹配需求 | 充分利用资源,避免浪费 |
| 混部场景 | 权重差异化 + 带宽限制 | 高优服务高权重,低优任务低权重并设硬限 |
| period 选择 | 默认 100ms 通常足够 | 过小(<10ms)增加调度开销;过大(>500ms)降低响应性 |
cpu.cfs_period_us 设置为 10000µs(10ms),配合适当的 quota 值,可以在毫秒级粒度上控制 CPU 分配,减少突发流量下的调度延迟。