k8s cpu 预留

37 阅读8分钟

Kubernetes 文档《CPU Management Policies》详细分析 + align-by-socket 与 CPU 预留核心关系拆解

文档核心定位:该文档聚焦 K8s 节点级 CPU 管理策略(none/static),解决CPU 资源独占性、拓扑亲和性、资源碎片问题,核心面向 Guaranteed QoS 等级的 Pod 提供精准 CPU 管控,align-by-socketstatic 策略下的核心配置,直接约束 CPU 预留的分配粒度与拓扑规则。

先给核心结论:align-by-socketCPU 预留(仅 Guaranteed 类型)的拓扑对齐约束,不改变 CPU 预留的总量,只决定「预留的 CPU 如何分配到节点硬件拓扑(socket/core)」,核心是强制按 socket 粒度分配预留 CPU,避免跨 socket 拆分,同时绑定 CPU 独占性

一、 先吃透文档核心基础(理解关联的前提)

要理清两者关系,必须先掌握文档中 3 个核心前置概念,这是文档的基础框架

1. K8s 两种 CPU 管理策略(文档核心)

K8s 节点的 cpuManagerPolicy 支持 2 种模式,仅 static 策略涉及 align-by-socket 和精准 CPU 预留,none 为默认策略,无强约束。

策略类型适用场景核心逻辑是否涉及 align-by-socket是否支持 CPU 独占预留
none(默认)大部分普通 PodCPU 以共享方式分配,按 cgroup 限制,不绑定具体核❌ 不涉及❌ 无独占预留,仅共享 cpu.shares
static高性能/低延迟 Pod(如数据库、AI 推理)仅对 Guaranteed Pod 分配独占 CPU 核心,绑定固定核,无争抢✅ 核心配置项✅ 强制 CPU 预留(requests=limits)+ 独占绑定

2. CPU 预留的核心定义(文档中触发 static 策略的关键)

文档明确:只有满足 Guaranteed QoS 的 Pod,才会触发 static 策略和 align-by-socket 逻辑,这是 CPU 预留与 align-by-socket 产生关联的前提。

  • CPU 预留满足条件:spec.containers[*].resources.requests.cpu = spec.containers[*].resources.limits.cpu(requests 和 limits 相等)
  • 预留本质:节点为 Pod 预留固定 CPU 核,该核被 Pod 独占,其他 Pod(非 Guaranteed)无法使用,避免资源争抢
  • 注意:文档中还区分了「节点级预留(kube-reserved/system-reserved)」和「Pod 级预留」,align-by-socket 仅作用于 Pod 级预留,节点级预留不受其约束

3. 硬件拓扑基础(文档隐含前提,理解 align-by-socket 必懂)

文档中 align-by-socket 的「socket」是服务器硬件拓扑的核心层级,层级关系如下(从上到下): Node(节点) → Socket(插槽,对应物理 CPU) → Core(核心) → Hyper-Thread(超线程)

  • 1 个 Socket = 1 颗物理 CPU,内含多个 Core(如 1 Socket = 16 Core)
  • 超线程:1 个 Core 可虚拟为 2 个逻辑核,文档中 static 策略默认按「逻辑核」分配,可通过 cpuManagerReconcilePeriod 调整

二、 align-by-socket 核心定义(文档原文拆解)

1. 文档中官方定义

align-by-socketstatic 策略下的可选配置(默认开启),核心描述:

When align-by-socket is true (the default), the CPU manager allocates CPUs in multiples of the number of cores per socket. This ensures that all CPUs allocated to a container are within the same socket or spread evenly across sockets when multiple sockets are required.

直译+核心提炼:

  • 默认开启,仅作用于 static 策略(即 Guaranteed Pod 的 CPU 预留)
  • 分配 CPU 时,必须按「每个 socket 的核心数」为最小分配单位(倍数分配)
  • 核心目标:要么让 Pod 预留的 CPU 全在同一个 socket,要么跨 socket 时均匀分配,绝不跨 socket 拆分核心

2. 核心属性(文档补充)

  • 配置方式:修改节点 kubelet 配置 cpuManagerPolicyOptions: {alignBySocket: true/false}
  • 生效范围:仅节点内 Guaranteed Pod 的 CPU 预留,Burstable/BestEffort Pod 完全不感知
  • 依赖条件:必须同时满足 cpuManagerPolicy=static + Pod 为 Guaranteed(requests=limits),缺一不可

三、 align-by-socket 与 CPU 预留的核心关系(核心解答)

两者不是「谁决定谁」,而是「约束与被约束」的关系:CPU 预留是前提(提供资源总量),align-by-socket 是约束(规定资源怎么分配到硬件拓扑),核心关联分 3 层,每一层都对应文档核心逻辑。

关联1: align-by-socket 约束 CPU 预留的「分配粒度」(核心作用)

CPU 预留决定「要给 Pod 分配多少核」,align-by-socket 决定「分配的核必须按什么粒度拆分」,文档明确:开启时粒度是「socket 内核心数的倍数」,关闭时粒度是「单个核心」。

举例(贴合文档示例场景,节点配置:2 Socket,每 Socket 8 Core,共 16 逻辑核)

场景:Pod 声明 CPU 预留(requests=limits=4)

  • 开启 align-by-socket(默认):分配粒度是「8 Core/Socket」的倍数 → 只能给 Pod 分配 同一 Socket 内的 4 个核(不能跨 Socket 分配 2+2),因为 4 < 8,满足「单 Socket 内分配」,符合倍数约束
  • 关闭 align-by-socket:分配粒度是「单个 Core」→ 可跨 Socket 分配(如 Socket1 2 核 + Socket2 2 核),无拓扑约束
文档关键补充
  • 若 Pod 预留 CPU 数 > 单个 Socket 核心数(如上述节点,Pod 预留 10 核):开启 align-by-socket 时,会按 Socket 倍数均匀分配 → 分配 Socket1 8 核 + Socket2 2 核(而非 5+5),保证每个 Socket 分配的核数是「单 Socket 核心数」的整数倍(8 是 8 的 1 倍,2 不足 8 但为剩余量)
  • 粒度约束的本质:避免「跨 Socket 拆分小量核心」,减少 CPU 跨 Socket 调度开销

关联2: align-by-socket 决定 CPU 预留的「拓扑亲和性」(核心价值)

文档核心目标之一:通过 align-by-socket 让预留 CPU 绑定固定 Socket,提升 Pod 性能,这是 CPU 预留本身不具备的能力(CPU 预留只保证总量,不保证拓扑)。

  • CPU 预留的短板:仅保证 Pod 能拿到固定核,但默认(none 策略)可能跨 Socket 分配,跨 Socket 访问内存/缓存的延迟远高于同 Socket
  • align-by-socket 的补充:强制预留 CPU 「同 Socket 聚合」或「跨 Socket 均匀分布」,本质是拓扑亲和性绑定 ✅ 同 Socket 聚合:Pod 所有预留核在一个 Socket,缓存命中率高,延迟最低(文档推荐高性能场景) ✅ 跨 Socket 均匀:Pod 预留核超单 Socket 容量时,均匀分布在多个 Socket,避免单个 Socket 过载

关联3: align-by-socket 影响 CPU 预留的「资源碎片」(文档重点提醒)

CPU 预留总量不变,但 align-by-socket 的粒度约束会影响节点 CPU 碎片率,进而影响后续 Pod 的预留分配,文档明确这是开启该配置的潜在代价。

举例(同上述节点:2 Socket,每 Socket 8 Core)

场景1:节点已给 PodA 预留 4 核(开启 align-by-socket,分配在 Socket1)

  • Socket1 剩余:4 核,Socket2 剩余:8 核
  • 后续 PodB 申请预留 6 核:因 align-by-socket 约束,无法用 Socket1 的 4 核 + Socket2 的 2 核,只能用 Socket2 的 6 核 → Socket1 剩余 4 核变成碎片,无法分配给 >=5 核的 Pod
  • 关闭 align-by-socket:可组合 Socket1 4 核 + Socket2 2 核 → 碎片率低
文档结论
  • 开启 align-by-socket:性能优先,碎片率高(适合高性能 Pod,不在乎碎片)
  • 关闭 align-by-socket:效率优先,碎片率低(适合多核 Pod 较多,追求资源利用率)

四、 文档中关于两者关联的关键补充(必看,避坑)

  1. 仅 Guaranteed Pod 生效:文档反复强调,若 Pod 不是 Guaranteed(requests≠limits),即使开启 static 策略和 align-by-socket,也无 CPU 独占预留,align-by-socket 不生效(本质是无合格的 CPU 预留触发约束)
  2. 不改变预留总量:align-by-socket 从不调整 Pod 的 CPU requests/limits(即预留总量),只调整分配的核的位置和粒度,文档明确「it does not change the amount of CPU requested」
  3. 与超线程的关系:文档中,align-by-socket 按「逻辑核」计算粒度,若开启超线程(1 Core=2 逻辑核),「每 Socket 核心数」指逻辑核数(如 1 Socket 8 Core 开启超线程 → 16 逻辑核,分配粒度为 16 的倍数)
  4. 节点级预留不受约束:文档区分「Pod 预留」和「kube-reserved/system-reserved」(节点为 kubelet、系统进程预留的 CPU),align-by-socket 不约束后者,后者按 none 策略分配,共享使用

五、 实操配置&验证(文档落地步骤,直接可用)

1. 开启 static 策略 + align-by-socket(默认开启)

修改 kubelet 配置(/var/lib/kubelet/config.yaml)

cpuManagerPolicy: static
cpuManagerPolicyOptions:
  alignBySocket: true  # 默认true,可省略;关闭则设为false
cpuManagerReconcilePeriod: 10s

重启 kubelet:systemctl restart kubelet

2. 创建符合 CPU 预留条件的 Pod(触发关联逻辑)

apiVersion: v1
kind: Pod
metadata:
  name: guaranteed-cpu-pod
spec:
  containers:
  - name: app
    image: nginx
    resources:
      requests:
        cpu: 4  # requests=limits,满足Guaranteed
        memory: 1Gi
      limits:
        cpu: 4
        memory: 1Gi

3. 验证 align-by-socket 对预留 CPU 的约束(文档推荐命令)

1. 查看 Pod 绑定的 CPU 核

kubectl exec guaranteed-cpu-pod -- cat /sys/fs/cgroup/cpuset/cpuset.cpus

2. 查看节点硬件拓扑(确认 socket 与 core 对应关系)

lscpu | grep -E "Socket|Core|CPU"

3. 验证是否按 socket 对齐:对比 cpuset.cpus 与 socket 核范围,判断是否跨 socket


## 六、 文档核心总结 + 两者关系复盘
### 1.  文档核心目标
通过 `static` 策略实现 CPU 独占预留,通过 `align-by-socket` 优化预留 CPU 的拓扑分配,最终提升高性能 Pod 的稳定性和低延迟能力。

### 2.  align-by-socket 与 CPU 预留 核心关系复盘
1.  前提:CPU 预留满足 `Guaranteed`(requests=limits)是两者产生关联的基础,否则 align-by-socket 无作用
2.  核心:CPU 预留给 Pod 「定量」,align-by-socket 给 Pod 「定位置+定粒度」
3.  价值:CPU 预留解决「资源争抢」,align-by-socket 解决「拓扑低效」,两者结合是高性能 Pod 的最优 CPU 配置

### 3.  适用场景(文档建议)
-  开启 align-by-socket + static 策略:AI 推理、数据库、实时计算等低延迟场景(优先性能,容忍碎片)
-  关闭 align-by-socket + static 策略:多核 Pod 密集部署、资源利用率优先场景(容忍跨 socket 延迟,追求低碎片)


# 参考
1. https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/