从 cgroup v1 CPU Shares 到 v2 CPU Weight 的新转换
I’m happy to translate the article for you, but I’ll need the full text you’d like translated. Could you please paste the content (excluding the source line you already provided) here? Once I have it, I’ll translate it into Simplified Chinese while preserving the original formatting, markdown syntax, and technical terms.
公告:改进的 CPU 份额 → CPU 权重 转换公式
我们很高兴推出一个新的转换公式,将 cgroup v1 CPU shares 转换为 cgroup v2 CPU weight。此改进解决了在使用 cgroup v2 的系统上运行的 Kubernetes 工作负载的 CPU 优先级分配相关的关键问题。
背景
Kubernetes 最初是为 cgroup v1 设计的,在该版本中,CPU 份额通过以 millicpu 形式分配容器的 CPU 请求来简单定义。
示例:请求 1 CPU(1024m)的容器会得到 cpu.shares = 1024。
过了一段时间,cgroup v1 开始被其继任者 cgroup v2 替代。在 cgroup v2 中,CPU 份额的概念(范围从 2 到 262 144,即 (2^{1}) 到 (2^{18}))被 CPU 权重(范围从 1 到 10 000,即 (10^{0}) 到 (10^{4}))所取代。
随着向 cgroup v2 的迁移,KEP‑2254 引入了一个转换公式,用于将 cgroup v1 的 CPU 份额映射到 cgroup v2 的 CPU 权重:
cpu.weight = (1 + ((cpu.shares - 2) * 9999) / 262142)
该公式将 ([2^{1}, 2^{18}]) 的值线性映射到 ([10^{0}, 10^{4}])。

虽然这种方法简单,但线性映射会带来若干显著问题,影响性能和配置粒度。
Source: …
先前转换公式的问题
当前的转换公式带来了两个主要问题。
对非 Kubernetes 工作负载的优先级降低
-
在 cgroup v1 中,CPU shares 的默认值为
1024。
因此,请求 1 CPU(1024 m)的容器与在 Kubernetes 之外运行的系统进程拥有相同的优先级。 -
在 cgroup v2 中,CPU weight 的默认值为
100,但当前公式将 1 CPU(1024 m) 转换为仅 ≈ 39 的 weight——不到默认值的 40 %。
示例
| 场景 | 设置 | 值 |
|---|---|---|
| 容器请求 | 1 CPU(1024 m) | – |
| cgroup v1 | cpu.shares | 1024(默认) |
| cgroup v2(当前) | cpu.weight | 39(远低于默认 100) |
影响
迁移到 cgroup v2 后,Kubernetes(或 OCI)工作负载相对于非 Kubernetes 进程的 CPU 优先级会下降。这在节点上运行大量系统守护进程且资源紧张的情况下尤为严重。
粒度难以管理
当前公式对小的 CPU 请求会得到非常低的数值,导致在容器内部为细粒度资源分配创建子 cgroup 时困难(参见 KEP #5474)。
示例
| 场景 | 设置 | 值 |
|---|---|---|
| 容器请求 | 100 m CPU | – |
| cgroup v1 | cpu.shares | 102 |
| cgroup v2(当前) | cpu.weight | 4(对子 cgroup 配置来说太低) |
影响
在 cgroup v1 中,100 m CPU(102 shares)的请求能够在子 cgroup 之间合理分配 CPU weight。而在 cgroup v2 中,4 的 weight 过于粗糙,阻碍了 CPU 资源在子 cgroup 之间的有效分配。随着 为非特权容器提供可写 cgroup(KEP #5474)的即将支持,这一问题将变得更加关键。
新的转换公式
描述
新的公式更为复杂,但在 cgroup v1 CPU shares 与 cgroup v2 CPU weight 之间的映射效果要好得多:
[ \text{cpu.weight} = \Bigl\lceil 10^{\left(\frac{L^{2}}{612} + \frac{125L}{612} - \frac{7}{34}\right)} \Bigr\rceil, \qquad\text{其中 } L = \log_{2}(\text{cpu.shares}) ]
它是一个二次函数,经过以下三个关键点:
cgroup v1 cpu.shares | cgroup v2 cpu.weight |
|---|---|
| 2 (最小值) | 1 (最小值) |
| 1024 (默认值) | 100 (默认值) |
| 262 144 (最大值) | 10 000 (最大值) |
从视觉上看,新函数如下所示:

放大重要区域:

该函数“接近线性”,但经过精心设计,使上述三个关键点恰好对齐。
它如何解决问题
更好的优先级对齐
请求 1 CPU(1024 m)的容器现在得到
cpu.weight = 102
这接近 cgroup v2 的默认权重 100。这恢复了 Kubernetes 工作负载与系统进程之间的预期优先级关系。
改进的粒度
请求 100 m CPU 的容器得到
cpu.weight = 17
(参见此处演示)。这使得容器内部的资源分配更加细致。
采用与集成
此更改在 OCI 层实现。换句话说,它 未 在 Kubernetes 本身实现;因此,新转换公式的采用完全取决于 OCI 运行时的采用情况。
支持的运行时
| 运行时 | 启用新公式的版本 |
|---|---|
runc | v1.3.2 – release notes |
crun | v1.23 – release notes |
对现有部署的影响
Important: 如果某些使用者仍假设使用旧的线性转换公式,可能会受到影响。直接根据之前公式计算预期 CPU‑weight 值的应用程序或监控工具可能需要更新,以适配新的二次转换。
相关场景包括:
- 预测 CPU‑weight 值的自定义资源管理工具。
- 验证或期望特定权重值的监控系统。
- 程序化设置或校验 CPU‑weight 值的应用程序。
Kubernetes 项目建议在升级 OCI 运行时之前,在非生产环境中测试新转换公式,以确保与现有工具链的兼容性。
我可以在哪里了解更多?
- Kubernetes GitHub Issue #131216 – 详细的技术分析和示例,包括讨论以及选择上述公式的理由。
- KEP‑2254: cgroup v2 – Kubernetes 中 cgroup v2 的原始实现。
- Kubernetes cgroup documentation – 当前的资源管理指南。
我该如何参与?
如果您有兴趣为 Kubernetes 节点级功能做贡献,请加入 Kubernetes Node Special Interest Group (SIG‑Node)。
我们欢迎新的贡献者以及对资源管理挑战的多元化视角。