CPU 配额(cpu.cfs_quota_us)与周期(cpu.cfs_period_us)的配置机制

在 Linux CFS(Completely Fair Scheduler)调度器下,容器运行时通过 cpu.cfs_quota_us 和 cpu.cfs_period_us 两个 cgroup 参数共同定义 CPU 资源配额。理解这两个参数的配置机制,是定位 CPU 配额竞争瓶颈的前提。

3.1 核心参数定义

参数 单位 默认值 含义
cpu.cfs_period_us 微秒(µs) 100000(100ms) 一个调度周期的时间窗口长度
cpu.cfs_quota_us 微秒(µs) -1(无限制) 在一个周期内,该 cgroup 中所有进程可使用的最大 CPU 时间
cpu.stat — — 记录调度延迟(nr_periods, nr_throttled, throttled_time)
关键理解:配额与周期的比值决定了容器可获得的 CPU 核心数上限。例如 quota=200000、period=100000 表示容器最多可使用 2 个完整 CPU 核心。

3.2 配额计算与 CPU 核心数映射

容器可获得的 CPU 核心数上限计算公式为:

CPU 核心数上限 = cpu.cfs_quota_us / cpu.cfs_period_us

常见配置示例:

  • 1 核限制:quota=100000,period=100000 → 比值 = 1.0
  • 2 核限制:quota=200000,period=100000 → 比值 = 2.0
  • 0.5 核限制:quota=50000,period=100000 → 比值 = 0.5
  • 无限制:quota=-1 → 不进行配额限制,可抢占宿主机所有空闲 CPU
常见误区:配额比值不是硬保留,而是上限。即使配置了 2 核,若宿主机空闲,容器仍可能被限制在 2 核以内;若宿主机繁忙,容器可能无法达到 2 核。

3.3 调度周期与配额耗尽机制

CFS 调度器在每个周期开始时重置配额计数器。若容器内进程在该周期内消耗的 CPU 时间达到 quota 值,则会被 throttled(节流),直到下一个周期开始才能继续运行。

CFS 配额周期与节流示意图 周期 1(100ms) 周期 2(100ms) T0 T0+100ms T0+200ms 已消耗 83ms(未超限) 已消耗 100ms(配额耗尽) ⚠ 进程被 throttled,等待下一周期 说明: • 周期1:进程消耗 83ms,未达 quota(100ms),正常调度。 • 周期2:进程消耗 100ms 后触发节流,剩余时间必须等待下一周期。

3.4 多核场景下的配额分配

当配额比值大于 1 时,容器可以在一个周期内同时使用多个 CPU 核心。CFS 调度器会将配额时间分配到各个核心上,但总消耗不超过 quota。

配额比值 理论最大核心数 调度行为
0.5 0.5 核 每 100ms 周期内最多运行 50ms,无论使用几个核心
1.0 1 核 可在一个核心上运行 100ms,或两个核心各运行 50ms
2.0 2 核 可在两个核心上各运行 100ms,或四个核心各运行 50ms
4.0 4 核 可在四个核心上各运行 100ms,或八个核心各运行 50ms
性能调优要点:当容器内存在大量短线程并发时,即使配额比值足够,也可能因为线程切换开销导致实际吞吐量低于预期。此时应检查 /sys/fs/cgroup/cpu/cpu.stat 中的 nr_throttled 是否持续增长。

3.5 配置生效与验证

在容器运行时(如 Docker、containerd)中,CPU 配额通常通过命令行参数或 Kubernetes resource limits 进行配置:

# Docker 示例:限制容器使用 1.5 核
docker run --cpus=1.5 --name my_container nginx

# 等效 cgroup 配置
echo 150000 > /sys/fs/cgroup/cpu/docker/<container_id>/cpu.cfs_quota_us
echo 100000 > /sys/fs/cgroup/cpu/docker/<container_id>/cpu.cfs_period_us

# 验证当前配置
cat /sys/fs/cgroup/cpu/docker/<container_id>/cpu.cfs_quota_us
cat /sys/fs/cgroup/cpu/docker/<container_id>/cpu.cfs_period_us

# 查看节流统计
cat /sys/fs/cgroup/cpu/docker/<container_id>/cpu.stat
# 输出示例:
# nr_periods 1000
# nr_throttled 45
# throttled_time 23456789

3.6 配置陷阱与最佳实践

  • 周期过短(< 10ms):增加调度器开销,可能导致频繁节流,适合延迟敏感型业务。
  • 周期过长(> 1s):配额耗尽后等待时间过长,导致容器响应延迟飙升。
  • 配额设置过小:即使宿主机 CPU 空闲,容器也无法利用,造成资源浪费。
  • 配额设置过大:容器可能抢占过多 CPU,影响同节点其他容器。
  • 推荐实践:保持 period=100000(100ms),根据业务负载调整 quota,并通过 cpu.stat 监控节流比例。
排查命令速查:使用 cat /sys/fs/cgroup/cpu/cpu.stat | grep throttled 快速判断容器是否遭遇 CPU 配额竞争。若 nr_throttled 持续增长且 throttled_time 占比超过 5%,说明配额不足或周期配置不合理。