Jiayun's Blog

探索与分享

引言:一个困扰了 Kubernetes 社区多年的荒谬现实

想象这样一个场景:你运行着一个对延迟极度敏感的高频交易(HFT)应用,需要 4 个独占 CPU 核心并严格绑定到同一个 NUMA 节点。为了满足 Guaranteed QoS 的要求,你不得不给旁边那个每秒只处理几十个请求的 Envoy sidecar 也分配 2 个独占 CPU。再加上一个日志收集的 sidecar,又是 1 个独占 CPU。

结果?你的 Pod 吃掉了 7 个独占 CPU 核心,其中 3 个大部分时间在空转。

这不是理论推演——这是过去几年里无数运行延迟敏感型工作负载的团队面临的真实困境。问题的根源在于 Kubernetes 的资源管理模型一直以来都是**逐容器(per-container)**的:CPU Manager、Memory Manager、Topology Manager 只能看到单个容器的资源请求,无法在 Pod 层面做全局优化。

2026 年 5 月 1 日,Kubernetes 1.36 正式发布,带来了一个看似不起眼却意义深远的 Alpha 特性:Pod 级资源管理器(Pod-Level Resource Managers)1。通过 PodLevelResourceManagersPodLevelResources 两个 Feature Gate,kubelet 的 Topology Manager、CPU Manager 和 Memory Manager 终于可以在 Pod 级别进行资源分配决策——主容器获得独占的 NUMA 对齐 CPU,sidecar 容器则使用共享 CPU 池,同时整个 Pod 依然保持 Guaranteed QoS 等级。

这篇文章将深入剖析这个特性的技术细节、设计哲学,以及它对 Service Mesh 等 sidecar 密集型架构的深远影响。

NUMA 拓扑:为什么资源分配不只是"数数字"

在讨论 Pod 级资源管理之前,我们需要先理解为什么 CPU 分配不是简单地"给你几个核心"就完事了。

什么是 NUMA

NUMA(Non-Uniform Memory Access,非统一内存访问) 是现代多路服务器的标准架构。一台双路服务器通常有两个 NUMA 节点,每个节点包含:

  • 一颗物理 CPU(若干核心)
  • 本地内存
  • 本地 PCIe 设备(GPU、网卡等)

关键点在于:访问本地 NUMA 节点的内存比访问远端节点快 2-3 倍。对于延迟敏感型应用,如果 CPU 核心在 NUMA Node 0 上,但内存分配在 NUMA Node 1 上,性能可能下降 30% 以上。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
┌─────────────────────────────────────────────────┐
│                  双路服务器                        │
│  ┌──────────────────┐   ┌──────────────────┐    │
│  │   NUMA Node 0    │   │   NUMA Node 1    │    │
│  │  CPU 0-15        │   │  CPU 16-31       │    │
│  │  64GB 本地内存    │◄─►│  64GB 本地内存    │    │
│  │  GPU 0, NIC 0    │   │  GPU 1, NIC 1    │    │
│  └──────────────────┘   └──────────────────┘    │
│         ▲ 快速访问              ▲ 快速访问        │
│         │                      │                │
│    跨节点访问延迟增加 2-3x                         │
└─────────────────────────────────────────────────┘

Kubernetes 的 NUMA 感知组件

Kubernetes 通过三个 kubelet 级别的管理器来处理 NUMA 拓扑:

  1. CPU Manager:当 Pod 处于 Guaranteed QoS 且请求整数 CPU 时,分配独占 CPU 核心
  2. Memory Manager:将内存分配绑定到特定 NUMA 节点
  3. Topology Manager:协调上述管理器,确保 CPU、内存和设备都在同一 NUMA 节点上

问题在于——在 1.36 之前,这三个管理器只能在容器级别工作。

旧模型的痛点:Sidecar 被迫"陪跑"

让我们用一个具体的 YAML 来说明问题。假设你有一个需要 NUMA 对齐独占 CPU 的数据库工作负载:

Before:Kubernetes 1.35 及之前

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
apiVersion: v1
kind: Pod
metadata:
  name: latency-critical-db
spec:
  containers:
    # 主容器:真正需要独占 CPU 的工作负载
    - name: database
      image: my-database:latest
      resources:
        requests:
          cpu: "4"          # 需要 4 个独占 CPU
          memory: "8Gi"
        limits:
          cpu: "4"
          memory: "8Gi"

    # Envoy sidecar:Service Mesh 要求注入
    - name: envoy-proxy
      image: envoyproxy/envoy:v1.30
      resources:
        requests:
          cpu: "2"          # ⚠️ 必须是整数才能获得 Guaranteed QoS
          memory: "512Mi"   # ⚠️ 实际只需要 0.1 CPU 就够了
        limits:
          cpu: "2"
          memory: "512Mi"

    # 日志收集 sidecar
    - name: log-collector
      image: fluent-bit:latest
      resources:
        requests:
          cpu: "1"          # ⚠️ 又浪费一个独占 CPU
          memory: "256Mi"
        limits:
          cpu: "1"
          memory: "256Mi"
  # 总计:7 个独占 CPU,其中 3 个基本在空转

这段配置的问题在于:

要让 CPU Manager 为 database 容器分配独占 CPU,整个 Pod 必须是 Guaranteed QoS(所有容器的 requests == limits)。而一旦 sidecar 容器的 CPU requests/limits 也设为整数,CPU Manager 就会同样为它们分配独占 CPU 核心

更糟糕的是,Topology Manager 会尝试将所有 7 个 CPU 核心都放到同一个 NUMA 节点上。如果单个 NUMA 节点只有 16 个核心,这个 Pod 就占了将近一半——留给其他需要 NUMA 对齐的 Pod 的空间大幅减少。

实际资源利用率?主容器可能跑满 4 个核心,而 sidecar 加起来平均使用率不到 0.3 CPU。

After:Kubernetes 1.36 Pod 级资源管理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
apiVersion: v1
kind: Pod
metadata:
  name: latency-critical-db
spec:
  # 🎯 Pod 级资源声明(新特性!)
  resources:
    requests:
      cpu: "6"
      memory: "9Gi"
    limits:
      cpu: "6"
      memory: "9Gi"

  containers:
    # 主容器:获得独占 NUMA 对齐 CPU
    - name: database
      image: my-database:latest
      resources:
        requests:
          cpu: "4"          # 独占 4 CPU,NUMA 对齐
          memory: "8Gi"
        limits:
          cpu: "4"
          memory: "8Gi"

    # Envoy sidecar:使用共享 CPU 池
    - name: envoy-proxy
      image: envoyproxy/envoy:v1.30
      resources:
        requests:
          cpu: "100m"       # ✅ 只请求实际需要的量
          memory: "512Mi"
        limits:
          cpu: "1500m"      # ✅ 可以 burst,不浪费独占核心
          memory: "512Mi"

    # 日志收集 sidecar:同样使用共享池
    - name: log-collector
      image: fluent-bit:latest
      resources:
        requests:
          cpu: "50m"        # ✅ 最小化资源占用
          memory: "256Mi"
        limits:
          cpu: "500m"
          memory: "256Mi"

关键变化:

  1. Pod 级别的 .spec.resources 声明了整个 Pod 的资源总量(requests == limits → Guaranteed QoS)
  2. 主容器 database 保持整数 CPU requests/limits,CPU Manager 为其分配 4 个独占核心
  3. Sidecar 容器使用非整数 CPU(100m、50m),它们会被分配到共享 CPU 池
  4. Pod 级别的 CPU 总量(6)减去独占分配(4)= 2 CPU 进入共享池供 sidecar 使用
  5. Topology Manager 在 Pod 级别做决策,确保独占 CPU 和共享池都在同一 NUMA 节点上

结果:从 7 个独占 CPU 降到 6 个总 CPU(其中 4 独占 + 2 共享),节省了约 15% 的 CPU 资源,而且 sidecar 不再绑定在不必要的独占核心上。

技术深潜:Feature Gate 与内部机制

两个 Feature Gate

Kubernetes 1.36 通过两个独立但协同工作的 Feature Gate 实现这个特性:

Feature Gate作用依赖
PodLevelResources允许在 .spec.resources 声明 Pod 级资源
PodLevelResourceManagers让 CPU/Memory/Topology Manager 识别 Pod 级资源PodLevelResources

启用方式(kubelet 配置):

1
2
3
4
5
6
7
8
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
featureGates:
  PodLevelResources: true
  PodLevelResourceManagers: true
cpuManagerPolicy: static
topologyManagerPolicy: single-numa-node  # 或 best-effort / restricted
memoryManagerPolicy: Static

分配决策流程

当 kubelet 接收到一个带有 Pod 级资源声明的 Pod 时,资源分配流程如下:

  1. QoS 判定:基于 Pod 级 .spec.resources 判定 QoS 等级(requests == limits → Guaranteed)
  2. 独占 CPU 识别:扫描所有容器,找出 CPU requests/limits 为整数的容器(候选独占分配)
  3. 共享池计算:Pod 级 CPU 总量 - 所有独占 CPU 分配 = 共享池大小
  4. Topology Manager 协调:在 Pod 级别而非容器级别运行拓扑对齐算法,将独占 CPU 和共享池统一放置到最优 NUMA 节点
  5. CPU Manager 分配:为独占容器分配具体 CPU 核心 ID,为共享容器设置 CFS 配额
  6. Memory Manager 分配:将内存绑定到对应 NUMA 节点

这种**混合分配(hybrid allocation)**模式是这个特性最核心的创新——它打破了"要么全部独占,要么全部共享"的二元对立。

对比分析:逐容器 vs Pod 级资源管理

维度逐容器模型(1.35-)Pod 级模型(1.36+)
QoS 判定粒度基于每个容器的 requests/limits基于 Pod 级 .spec.resources
CPU 分配模式全部独占或全部共享混合:独占 + 共享池
Topology Manager 视角每个容器独立对齐Pod 整体对齐
Sidecar 资源效率低(被迫独占)高(共享池复用)
NUMA 节点压力高(独占核心数多)低(共享池减少独占需求)
配置复杂度低(但结果不理想)中(需理解混合模式)
调度器感知逐容器累加Pod 级总量
适用场景简单工作负载Sidecar 密集型、延迟敏感型

Service Mesh 场景:最大的受益者

如果说这个特性有一个"杀手级"应用场景,那一定是 Service Mesh

在 Istio、Linkerd 等 Service Mesh 架构中,几乎每个业务 Pod 都会被自动注入一个 Envoy/linkerd-proxy sidecar。在大规模集群中,这意味着:

  • 1000 个业务 Pod = 1000 个 sidecar 容器
  • 如果这些 Pod 需要 Guaranteed QoS + 独占 CPU,每个 sidecar 至少占用 1 个独占核心
  • 1000 个额外的独占 CPU 核心被 sidecar 锁定,利用率却可能不到 5%

实际节省估算

假设一个典型的 Service Mesh 集群:

指标旧模型新模型节省
需要独占 CPU 的 Pod 数200200-
每 Pod 主容器 CPU44-
每 Pod sidecar 独占 CPU20(共享池)2/Pod
总独占 CPU 需求120080033%
每 Pod 共享池 CPU01-
总 CPU 需求1200100017%

在一个 200 Pod 的延迟敏感集群中,Pod 级资源管理可以节省约 200 个 CPU 核心的独占分配——按云厂商价格计算,这可能是每月数万美元的成本差异。

Sidecar 容器(KEP-753)的协同效应

值得注意的是,Kubernetes 1.28 引入的原生 Sidecar 容器(restartPolicy: Always 的 init 容器)与 Pod 级资源管理形成了天然的协同2。原生 sidecar 解决了生命周期管理问题(sidecar 在主容器之前启动、之后关闭),而 Pod 级资源管理解决了资源分配效率问题。两者结合,让 sidecar 模式从"必要的妥协"变成了"一等公民"。

真实用例场景

1. 高频交易(HFT)

高频交易系统对延迟的要求以微秒计。典型的 HFT Pod 需要:

  • 主容器绑定到特定 CPU 核心,避免上下文切换
  • 内存锁定到同一 NUMA 节点,消除远端内存访问延迟
  • 网卡中断也绑定到同一 NUMA 节点

但同时,合规监控 sidecar、日志审计 sidecar 并不需要这种级别的资源保障。Pod 级资源管理让这种混合需求变得自然。

2. 机器学习训练

GPU 训练任务通常需要 CPU 核心与 GPU 在同一 NUMA 节点上,用于高效的数据预处理管道。数据加载容器需要独占 CPU 来喂饱 GPU,而 metrics exporter 或 checkpoint sidecar 完全可以使用共享 CPU 池。

3. 延迟敏感型数据库

Redis、ScyllaDB 等对延迟敏感的数据库在 NUMA 对齐模式下性能可提升 20-40%3。Pod 级资源管理让数据库主进程获得最优资源放置,而备份 agent、监控 exporter 等辅助容器不再拖累整体的 NUMA 拓扑决策。

局限性与注意事项

作为 Alpha 特性,Pod 级资源管理还有一些需要注意的地方:

1. Alpha 意味着不稳定

  • API 可能在后续版本变化
  • 不建议在生产环境使用(除非你愿意承担升级风险)
  • Feature Gate 默认关闭,需要手动启用

2. 调度器尚未完全适配

当前 kube-scheduler 的调度决策仍然基于容器级别的资源累加。虽然 Pod 级资源声明不会导致调度失败,但调度器的 NUMA 感知调度(如 TopologyAwareScheduling)还需要后续版本的适配才能充分利用 Pod 级信息。

3. 监控和可观测性

现有的监控工具(Prometheus 的 cAdvisor metrics 等)主要以容器为粒度报告 CPU 使用率。Pod 级共享池的 CPU 使用归属需要新的 metric 维度来准确追踪。

4. Windows 节点不支持

CPU Manager 和 Topology Manager 本身就不支持 Windows 节点,Pod 级扩展同样如此。

更深层的思考:Kubernetes 资源模型的演进

Pod 级资源管理的出现,实际上折射出 Kubernetes 资源模型一个深层的架构演进趋势:从"容器是最小调度单元"到"Pod 是最小调度单元"的范式转移

回顾历史:

  • Kubernetes 1.0(2015):资源模型以容器为中心,Pod 只是"一组容器"
  • Kubernetes 1.8(2017):引入 CPU Manager,但仍然按容器分配
  • Kubernetes 1.18(2020):Topology Manager 进入 Beta,协调 NUMA 对齐——但依然是逐容器
  • Kubernetes 1.28(2023):原生 Sidecar 容器,承认了 Pod 内容器的角色差异
  • Kubernetes 1.36(2026):Pod 级资源管理,资源分配层面正式承认 Pod 是一个整体

这个演进过程揭示了一个深刻的设计张力:Kubernetes 从 Borg 继承了"容器是最小资源单元"的假设,但现实世界的工作负载(特别是 sidecar 模式)不断挑战这个假设。Pod 级资源管理不是一个孤立的特性,而是 Kubernetes 逐步修正其资源模型的持续过程的一部分。

从更宏观的视角看,这也呼应了云原生社区对**“资源效率”**日益增长的关注。在 FinOps 理念普及的今天,每一个被浪费的 CPU 核心都是账单上的一个数字。Pod 级资源管理可能看起来只是一个技术细节,但它代表着一种思维转变:精细化资源管理不再是可选项,而是基础设施的必备能力。

如何试用

如果你想在测试环境中体验这个特性:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 1. 安装 Kubernetes 1.36(使用 kind 或 kubeadm)
kind create cluster --image kindest/node:v1.36.0

# 2. 修改 kubelet 配置启用 Feature Gate
# 在 kubelet 的配置文件中添加:
# featureGates:
#   PodLevelResources: true
#   PodLevelResourceManagers: true
# cpuManagerPolicy: static
# topologyManagerPolicy: best-effort
# reservedSystemCPUs: "0"

# 3. 部署测试 Pod
kubectl apply -f pod-level-resources-demo.yaml

# 4. 验证 CPU 分配
kubectl exec latency-critical-db -c database -- cat /sys/fs/cgroup/cpuset.cpus.effective
# 输出示例:2-5(4 个独占核心)

kubectl exec latency-critical-db -c envoy-proxy -- cat /sys/fs/cgroup/cpuset.cpus.effective
# 输出示例:0-31(共享池,所有可用核心)

结语

Kubernetes 1.36 的 Pod 级资源管理是一个"小特性,大影响"的典型案例。它解决的问题很具体——sidecar 容器在 NUMA 对齐场景中被迫独占 CPU——但它背后的设计理念影响深远:Pod 内的容器不应该被一视同仁,资源管理需要尊重容器角色的差异性。

对于运行 Service Mesh、延迟敏感型数据库或 ML 训练工作负载的团队来说,这个特性值得密切关注。虽然目前还是 Alpha 阶段,但从 Kubernetes 社区的 KEP 讨论来看,Pod 级资源管理在 1.37 或 1.38 进入 Beta 的可能性很大。

资源管理的未来不是"给每个容器一样多",而是"给每个容器恰好够用"。Kubernetes 1.36 朝这个方向迈出了重要一步。


参考资料:


  1. Kubernetes Blog, “Kubernetes v1.36: Pod Level Resources Scalability Improvements”, May 1, 2026. https://kubernetes.io/blog/2026/05/01/kubernetes-v1-36-pod-level-resource-managers/ ↩︎

  2. KEP-753: Sidecar Containers. https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/753-sidecar-containers ↩︎

  3. Intel, “NUMA-Aware Memory Allocation for Database Workloads”, 2024. https://www.intel.com/content/www/us/en/developer/articles/technical/numa-aware-memory-allocation.html ↩︎