背景

业务内部存在计算密集型pod和GPU相关的模型服务,在业务高峰期时服务的性能会产生下降趋势,猜测是服务之间存在CPU时间片竞争,尝试去开始Pod独占核心去解决这个问题。

基本环境介绍

组件名称 版本号
Kubernetes v1.32.2
Containerd v1.6.9
10.21.36.6 kubectl控制机
10.21.34.238 问题节点

开启Kubernetes的CPU管理策略

参考文档:https://kubernetes.io/zh-cn/docs/concepts/policy/node-resource-managers/
说明:
当启用 static 策略时,要求使用 --kube-reserved 和/或 --system-reserved 或 --reserved-cpus 来保证预留的 CPU 值大于零。 这是因为零预留 CPU 值可能使得共享池变空。

  1. 对指定节点进行封锁和排空
[root@10.21.36.6 ~]# kubectl  cordon np-5ev2omtb.156 #封锁节点
[root@10.21.36.6 ~]# kubectl  drain  np-5ev2omtb.156 #驱逐节点Pod
  1. 登录节点开启CPU管理策略
[root@10.21.34.238 ~]#  systemctl  stop kubelet 
[root@10.21.34.238 ~]# rm /var/lib/kubelet/cpu_manager_state
[root@10.21.34.238 ~]# cat /etc/kubernetes/kubelet
....
CPU_MANAGER_POLICY="--cpu-manager-policy=static"  #设置CPU管理策略为static
CPU_MANAGER_POLICY_OPTION="--cpu-manager-policy-options=full-pcpus-only=true" #设置Pod独占一个完整的物理核心
[root@10.21.34.238 ~]# cat /usr/lib/systemd/system/kubelet.service #加入到systemctl启动参数里面
[Unit]
Description=kubelet

[Service]
EnvironmentFile=-/etc/kubernetes/kubelet
ExecStart=..... ${CPU_MANAGER_POLICY} ${CPU_MANAGER_POLICY_OPTION}
.....
[root@10.21.34.238 ~]# systemctl daemon-reload #重新reload配置
[root@10.21.34.238 ~]# systemctl start kubelet #启动kubelet
[root@10.21.34.238 ~]# cat /var/lib/kubelet/cpu_manager_state #检查是否生效
{"policyName":"static"...}

Pod调度测试(必须是Guaranteed级别)

  1. Pod关键配置如下
resources:
  requests:
    cpu: "4"     #占用两个物理核心
    memory: "2Gi"
  limits:
    cpu: "4"
    memory: "2Gi"
  1. 查看独占是否生效

在这里插入图片描述

当业务配置为3的时候,事件出现了SMT相关错误,SMT Alignment Error: requested 1 cpus not multiple cpus per core = 2

SMT扩展知识(同步多线程)

  1. 查看问题节点的CPU信息
[root@10.21.34.238 ~]# lscpu
Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              32
On-line CPU(s) list: 0-31
Thread(s) per core:  2
Core(s) per socket:  16
Socket(s):           1
NUMA node(s):        1
Vendor ID:           AuthenticAMD
BIOS Vendor ID:      Red Hat
CPU family:          25
Model:               17
Model name:          AMD EPYC 9K84 96-Core Processor
BIOS Model name:     3.0
Stepping:            0
CPU MHz:             2600.030
BogoMIPS:            5200.06
Hypervisor vendor:   KVM
Virtualization type: full
L1d cache:           32K
L1i cache:           32K
L2 cache:            1024K
L3 cache:            32768K
NUMA node0 CPU(s):   0-31
Flags:               fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid amd_dcm tsc_known_freq pni pclmulqdq monitor ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext perfctr_core invpcid_single ibpb vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 avx512_bf16 clzero xsaveerptr wbnoinvd arat avx512vbmi umip avx512_vbmi2 vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq rdpid fsrm

根据上面的信息,机器存在16个物理核心和32个逻辑核心(默认云厂商的机器都以逻辑核心的数量为准),配置的CPU管理策略中Pod必须独占一个物理核心,所以Pod配置时需要以2的倍数关系来变更。

  1. 查看核心对应关系
[root@10.21.34.238 ~]# lscpu -e
CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE
0   0    0      0    0:0:0:0       yes
1   0    0      0    0:0:0:0       yes
2   0    0      1    1:1:1:0       yes
3   0    0      1    1:1:1:0       yes
4   0    0      2    2:2:2:0       yes
5   0    0      2    2:2:2:0       yes
6   0    0      3    3:3:3:0       yes
7   0    0      3    3:3:3:0       yes
8   0    0      4    4:4:4:0       yes
9   0    0      4    4:4:4:0       yes
10  0    0      5    5:5:5:0       yes
11  0    0      5    5:5:5:0       yes
12  0    0      6    6:6:6:0       yes
13  0    0      6    6:6:6:0       yes
14  0    0      7    7:7:7:0       yes
15  0    0      7    7:7:7:0       yes
16  0    0      8    8:8:8:1       yes
17  0    0      8    8:8:8:1       yes
18  0    0      9    9:9:9:1       yes
19  0    0      9    9:9:9:1       yes
20  0    0      10   10:10:10:1    yes
21  0    0      10   10:10:10:1    yes
22  0    0      11   11:11:11:1    yes
23  0    0      11   11:11:11:1    yes
24  0    0      12   12:12:12:1    yes
25  0    0      12   12:12:12:1    yes
26  0    0      13   13:13:13:1    yes
27  0    0      13   13:13:13:1    yes
28  0    0      14   14:14:14:1    yes
29  0    0      14   14:14:14:1    yes
30  0    0      15   15:15:15:1    yes
31  0    0      15   15:15:15:1    yes

可以确定,0,1逻辑核心对应 0号物理核心,比例是2:1。

NUMA扩展知识

UMA(Uniform Memory Access)统一内存访问

┌─────────────────────────────────────────┐
│          共享内存控制器                   │
├──────┬──────┬──────┬──────┬──────┬──────┤
│ CPU0 │ CPU1 │ CPU2 │ CPU3 │ CPU4 │ CPU5 │
└──────┴──────┴──────┴──────┴──────┴──────┘
           │        │        │        │
           └────────┴────────┴────────┘
                所有 CPU 访问内存
                   速度相同

NUMA(Non-Uniform Memory Access)非统一内存访问


┌───────── NUMA 节点0 ─────────┐  ┌───────── NUMA 节点1 ─────────┐
│  ┌──────┐      ┌──────┐     │  │  ┌──────┐      ┌──────┐     │
│  │ CPU0 │      │ CPU1 │     │  │  │ CPU2 │      │ CPU3 │     │
│  └──┬───┘      └──┬───┘     │  │  └──┬───┘      └──┬───┘     │
│     │             │         │  │     │             │         │
│  ┌──┴─────────────┴──┐     │  │  ┌──┴─────────────┴──┐     │
│  │    本地内存        │     │  │  │    本地内存        │     │
│  │   (快速访问)       │     │  │  │   (快速访问)       │     │
│  └───────────────────┘     │  └──┼───────────────────┘     │
└──────────────┬──────────────┘     └──────────────┬──────────────┘
               │                                   │
               └─────────── 互联总线 ───────────────┘
                (较慢的远程内存访问)

NUMA 是一种多处理器系统的内存设计架构:

  • 每个 CPU 有自己"本地"的快速内存
  • 访问其他 CPU 的内存较慢(需要经过互联)
  • 访问速度"不均匀"(非统一)

总结: 一台服务器可能有多个NUMA node,每个NUMA node绑定了机器一部分的核心和内存,当不同的NUMA node远程访问的时候,访问速度会降低。

常用的numa命令
[root@10.21.34.238 ~]# numastat
                           node0
numa_hit              1195541677
numa_miss                      0
numa_foreign                   0
interleave_hit             24491
local_node            1195541677
other_node                     0
[root@10.21.34.238 ~]# numactl --hardware
available: 1 nodes (0)
node 0 cpus: 0 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
node 0 size: 94532 MB
node 0 free: 3162 MB
node distances:
node   0
  0:  10

结语

Kubernetes 的 CPU 管理策略演进揭示了一个重要趋势:基础设施正变得越来越"智能"。它不再仅仅提供资源,而是理解资源的特性、关联和最佳使用方式。

从 SMT 感知到 NUMA 优化,从静态分配到拓扑感知调度,这些技术进步最终服务于同一个目标:让应用在云原生环境中获得可预测、高性能的运行体验。对于技术决策者和架构师而言,深入理解这些底层机制,不再是可选的高级技能,而是构建高性能云原生应用的必备素养。

更多推荐