2、CPU资源抽象:从物理CPU到K8s的CPU单位(millicores),理解CPU Manager与拓扑感知

2.1 CPU资源抽象层级

Kubernetes 对 CPU 资源的抽象经历了从物理硬件到调度单位的多次转换。理解这一抽象链条,是进行 CPU 容量配额调优的基础。

抽象层级 单位/概念 说明
物理 CPU 物理核心 (Core) 服务器上的物理处理器核心,拥有独立的 L1/L2 缓存
逻辑 CPU vCPU / 超线程 (HT) 通过超线程技术,一个物理核心可提供 2 个逻辑 CPU
操作系统 CPU /proc/cpuinfo 中的 processor Linux 内核看到的调度单元,对应逻辑 CPU
K8s Node CPU capacity.cpu kubelet 上报到 API Server 的节点总 CPU 数量(逻辑核数)
K8s 容器 CPU millicores (m) 容器可使用的 CPU 时间片配额,1000m = 1 个逻辑 CPU
关键认知:K8s 中的 CPU 资源本质上是 时间片配额,而非独占物理核心。1000m 表示容器在 1 秒内最多占用 1 个逻辑 CPU 的全部时间片。

2.2 millicores:CPU 时间片的抽象单位

millicores(毫核)是 K8s 中最小的 CPU 分配单位。1 millicore = 1/1000 个逻辑 CPU 的时间片。这种抽象使得细粒度的 CPU 资源分配成为可能。

# Pod 定义中的 CPU 资源示例
apiVersion: v1
kind: Pod
metadata:
  name: cpu-demo
spec:
  containers:
  - name: app
    image: nginx
    resources:
      requests:
        cpu: "250m"        # 保证 0.25 个逻辑 CPU 的时间片
      limits:
        cpu: "500m"        # 最多使用 0.5 个逻辑 CPU 的时间片
millicores 值 等效逻辑 CPU 典型场景
100m 0.1 核 轻量 sidecar、日志采集
500m 0.5 核 中等负载 Web 服务
1000m 1 核 标准微服务实例
2000m 2 核 计算密集型任务
8000m 8 核 批处理/机器学习训练
常见误区:设置 cpu: "1000m" 并不意味着容器独占一个物理核心。它只保证容器在调度周期内获得相当于 1 个逻辑 CPU 的 时间片配额。实际运行中,时间片可能来自多个不同的逻辑 CPU。

2.3 CPU Manager:从共享到绑核

默认情况下,K8s 使用 CFS(Completely Fair Scheduler)配额机制,容器的时间片可以在任意 CPU 上执行。对于延迟敏感型工作负载,这种 CPU 迁移会导致缓存抖动和性能波动。CPU Manager 提供了两种策略来解决这个问题。

策略 策略名称 行为 适用场景
none 默认策略 容器可以在任意 CPU 上调度,使用 CFS 配额限制 通用工作负载、批处理任务
static 静态策略 为 Guaranteed QoS 且整数 CPU 请求的 Pod 分配独占 CPU 核心 延迟敏感、高频交易、实时处理
static 策略触发条件:
  1. Pod 的 QoS 等级为 Guaranteed(limits == requests)
  2. CPU requests 和 limits 为 整数(如 1、2、4,不能是 500m)
  3. kubelet 启动参数 --cpu-manager-policy=static
满足以上条件时,容器将获得 独占物理核心,彻底消除 CPU 迁移带来的性能抖动。
CPU Manager 策略对比:none vs static 策略:none(默认) 容器 A(500m) 时间片在 CPU0/CPU1/CPU2 间迁移 L1/L2 缓存频繁失效 延迟波动:±15%~30% 策略:static(绑核) 容器 B(1000m,Guaranteed) 独占 CPU3 物理核心 L1/L2 缓存命中率稳定 延迟波动:<5% static 策略通过 cpuset cgroup 将容器绑定到指定 CPU 核心 消除上下文切换和 CPU 迁移带来的性能损耗 物理 CPU 拓扑示例(4 核 8 线程) Core0 HT0/HT1 Core1 HT2/HT3 Core2 HT4/HT5 Core3 HT6/HT7 NUMA Node 0 NUMA Node 1

2.4 拓扑感知:NUMA 架构下的 CPU 亲和性

在现代多插槽服务器中,CPU 访问不同位置的内存延迟差异巨大。NUMA(Non-Uniform Memory Access)架构下,CPU 访问本地内存比访问远端内存快 1.5~3 倍。拓扑感知调度旨在将 Pod 的 CPU 和内存分配限制在同一个 NUMA 节点内。

组件 功能 配置方式
Topology Manager 协调 CPU Manager 和 Device Manager 的分配决策,确保资源来自同一 NUMA 节点 kubelet 参数 --topology-manager-policy
CPU Manager Policy 提供绑核能力,配合 Topology Manager 实现 NUMA 亲和 --cpu-manager-policy=static
Memory Manager 保证内存分配与 CPU 分配在同一 NUMA 节点 --memory-manager-policy=Static
Topology Manager 策略层级:
  • none:不做任何拓扑对齐
  • best-effort:尽量对齐,失败时回退到 none
  • restricted:必须对齐,否则拒绝 Pod 调度
  • single-numa-node:所有资源必须来自同一个 NUMA 节点
对于延迟敏感型工作负载,推荐使用 single-numa-node 策略。
拓扑感知调度流程:Topology Manager 协调 Pod 请求 CPU: 2, Memory: 4Gi Topology Manager(single-numa-node) 检查 NUMA Node 0 是否有 2 个空闲 CPU + 4Gi 内存 ✅ 资源充足 CPU Manager 分配 NUMA Node 0 的 CPU ❌ 资源不足 拒绝 Pod 调度,等待资源释放 拓扑感知调度避免了跨 NUMA 访问,降低内存访问延迟 30%~50% 适用于高频交易、实时数据库、DPDK 等性能敏感场景

2.5 实践建议与调优方向

场景 CPU Manager 策略 Topology Manager 策略 预期效果
通用微服务 none none 资源利用率最大化,接受一定性能波动
延迟敏感型服务 static restricted 减少缓存抖动,延迟降低 20%~40%
高性能计算 static single-numa-node 消除跨 NUMA 访问,性能提升 30%~60%
批处理/离线任务 none best-effort 兼顾性能与资源利用率
调优检查清单:
  • 确认节点 BIOS 中 超线程 和 NUMA 已正确启用
  • 使用 lscpu 和 numactl --hardware 验证 CPU 拓扑
  • 为延迟敏感 Pod 设置 Guaranteed QoS 和 整数 CPU 请求
  • 监控 /sys/fs/cgroup/cpuset/ 确认绑核生效
  • 使用 perf stat -e cache-misses 评估缓存命中率改善