Kubernetes Pod/Container NUMA亲和管理

举报
Kubeservice@董江 发表于 2024/04/19 11:38:05 2024/04/19
【摘要】 Kubernetes Pod/Container NUMA亲和管理 背景先前工作中大量使用基于CPU、Memory亲和的感知调度实现, 目前对这部分统一梳理下,NUMA 感知涉及 memory 和cpu的亲和申请,并且余内存预留和cpu预留比较紧密,此处一起介绍下 CPU 管理默认情况下,kubelet 使用 CFS 配额 来执行 Pod 的 CPU 约束。 当节点上运行了很多 CPU 密...

Kubernetes Pod/Container NUMA亲和管理

背景

先前工作中大量使用基于CPU、Memory亲和的感知调度实现, 目前对这部分统一梳理下,NUMA 感知涉及 memory 和cpu的亲和申请,并且余内存预留和cpu预留比较紧密,此处一起介绍下

CPU 管理

默认情况下,kubelet 使用 CFS 配额 来执行 Pod 的 CPU 约束。 当节点上运行了很多 CPU 密集的 Pod 时,工作负载可能会迁移到不同的 CPU 核, 这取决于调度时 Pod 是否被扼制,以及哪些 CPU 核是可用的。 许多工作负载对这种迁移不敏感,因此无需任何干预即可正常工作。

Kubernetes 的 Node 节点会运行多个 Pod,其中会有部分的 Pod属于CPU密集型的工作负载。
在这种情况下,Pod 之间会争抢节点的 CPU 资源。当争抢剧烈的时候,Pod会在不同的CPU Core之间进行频繁的切换,更糟糕的是在NUMA Node之间的切换。这种大量的上下文切换,会影响程序运行的性能。

核心

通过 Pod/Container 启动中,更新 kubelet 优先配置好的可申请集合,将其更新到具体的 cgoup 下的 cpu_set 下,尽量将 cpu申请 优先在特定cpu范围上(尽可能)

具体可查看: https://github.com/klueska/kubernetes/tree/master/pkg/kubelet/cm/cpumanager

kubelet 开启策略

1. 要求:

CPU Manager 在 Kubernetes v1.12 引用为 beta; 在 Kubernetes v1.26 获得 stable.

2. 配置管理

kubelet 参数 --cpu-manager-policy 或KubeletConfiguration 中的 cpuManagerPolicy 字段来指定

--cpu-manager-policy=Static

支持两种策略:

  • none: 默认策略,表示现有的调度行为。可以理解为不开启cpu manager。
  • static: 允许为节点上具有某些资源特征的 Pod 赋予增强的 CPU 亲和性和独占性。

none 策略 显式地启用现有的默认 CPU亲和方案,不提供操作系统调度器默认行为之外的亲和性策略
static 策略针对具有整数型 CPU requests 的 Guaranteed Pod ,它允许该类 Pod 中的容器访问节点上的独占 CPU 资源。这种独占性是使用cpu_set cgroup 控制器来实现的。

CPU 管理器定期通过 CRI 写入资源更新,以保证内存中 CPU 分配与 cgroupfs 一致。同步频率通过新增的 Kubelet 配置参数 --cpu-manager-reconcile-period 来设置。如果不指定,默认与 --node-status-update-frequency 的周期(默认10s)相同。

3. 精细化配置

static 策略的行为可以使用 --cpu-manager-policy-options 参数来微调。该参数采用一个逗号分隔的 key=value 策略选项列表。此特性可以通过 CPUManagerPolicyOptions 特性门控来完全禁用。

CPUManagerPolicyOptions 也支持3种精确化管理:

  • full-pcpus-only: 分配完整的物理核心。此策略严格(1.22 或更高版本)
  • distribute-cpus-across-numa: 需要多个 NUMA 节点来满足分配的情况下, static 策略会在 NUMA 节点上平均分配 CPU.(1.23 或更高版本)
  • align-by-socket: 试图确保从 NUMA 节点的最小数量分配所有 CPU,但不能保证这些 NUMA 节点将位于同一个 CPU 的插槽。即极限分配(1.25 或更高版本)

4. 建议使用

在KubeletConfiguration配置中,添加

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cpuManagerPolicy: static
cpuManagerPolicyOptions:
  full-pcpus-only: "true" #分配完整的物理核心
  distribute-cpus-across-numa: "true" #需要多个 NUMA 节点来满足分配的情况下,会在 NUMA 节点上平均分配 CPU.
cpuManagerReconcilePeriod: 5s # cpu上报周期
reservedSystemCPUs: "0-1" # 预留系统0-1

内存管理器

为需要保证 QoS 的 Po 在多 NUMA 节点保障内存和大内存页分配。这个特性非常有用,尤其是当数据库类或者使用 DPDK 进行高性能数据包处理的应用要部署到 Kubernetes 中时,内存对其性能影响至关重要。

内存管理器(Memory Manager)为 Guaranteed QoS 类 的 Pods 提供可保证的内存(及大页面)分配能力。

核心

内存管理器 通过在 Pod 部署前,将为 Pod 应用 cgroups 设置(即 cpuset.mems), 保障的内存大页分配.

具体可查看:https://github.com/klueska/kubernetes/tree/master/pkg/kubelet/cm/memorymanager

kubelet 开启策略

1. 要求:

从 v1.22 开始,内存管理器通过特性门控 MemoryManager 默认启用。
在 v1.22 之前,kubelet 必须在启动时设置如下标志:

--feature-gates=MemoryManager=true

2. 配置管理

在内存管理中,对 NUMA 分组的管理。 每当 Pod 的内存请求超出单个 NUMA 节点容量时,内存管理器会尝试创建一个包含多个 NUMA 节点的分组,从而扩展内存容量。 此策略是默认的, 并无替代策略。

kubelet 标志 --memory-manager-policy 来选择一种策略:

  • none: 默认策略。可以理解为不开启memory manager。
  • static: 允许为节点上具有某些资源特征的 Pod 的 memory 亲和到单个numa上。

3. 内存预留管理

在优化 Pod 调度过程时,会考虑可分配的内存。 前面提到的标志包括 --kube-reserved、--system-reserved 和 --eviction-threshold。 这些标志值的综合计作预留内存的总量。

1.至少为一个 NUMA 节点设置 --reserved-memory。实际上,eviction-hard 阈值默认为 100Mi, 所以当使用 Static 策略时,--reserved-memory 是必须设置的.
2.sum(reserved-memory(i)) >= kube-reserved + system-reserved + eviction-threshold

4. 建议使用

在KubeletConfiguration配置中,添加

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
memoryManagerPolicy: Static
memorySwap: {} # 关掉swap内存交换
reservedMemory:
  - limits:
      memory: 1100Mi # >= 500Mi+500Mi+100Mi
      cpu: 500m
    numaNode: 0 # numa 0必须存在
kubeReserved:
  memory: 500Mi
systemReserved:
  memory: 500Mi
evictionHard:
  imagefs.available: 15%
  memory.available: 100Mi
  nodefs.available: 10%
  nodefs.inodesFree: 5%
evictionPressureTransitionPeriod: 0s #驱逐等待时间

Numa拓扑管理topologyManager

将 CPU、Memory 等设备管理进行统筹资源分配决策。

核心

kubelet 管理

TopologyManager 提供了如下几种对齐策略:

  • none:此政策不会尝试进行任何资源调整。 它的行为就像 TopologyManager 根本不存在一样。 这是默认策略。
  • best-effort:使用此策略,TopologyManager 将尝试尽可能地对齐 NUMA 节点上的分配,但即使某些分配的资源未在同一 NUMA 节点上对齐,也会始终允许 pod 启动。
  • restricted:此策略与尽力而为策略相同,但如果分配的资源无法正确对齐,它将导致 pod 准入失败。 与 single-numa-node 策略不同,如果不可能在单个 NUMA 节点上满足分配请求,则某些分配可能来自多个 NUMA 节点。
  • single-numa-node:这个策略是最严格的,只有当所有请求的 CPU 和设备都可以从一个 NUMA 节点分配时,pod 准入才会通过。

建议使用

在KubeletConfiguration配置中,添加

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
topologyManagerPolicy: single-numa-node # 策略是最严格,如果pod不能不在单个numa上分配
topologyManagerScope: container # container 维度进行numa亲和

验证

使用 numactl 管理工具查看下当前机器上的情况:

dongjiang@basa:~ $ numactl -H
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 20 21 22 23 24 25 26 27 28 29
node 0 size: 65186 MB
node 0 free: 9769 MB
node 1 cpus: 10 11 12 13 14 15 16 17 18 19 30 31 32 33 34 35 36 37 38 39
node 1 size: 65536 MB
node 1 free: 15206 MB
node distances:
node   0   1 
  0:  10  21 
  1:  21  10

部署 nginx:

---
apiVersion: v1
kind: Pod
metadata:
  name: cpusets-test
spec:
  containers:
...
    - name: testcontainer1 # Guaranteed 并且 cpu是整数个
      image: dongjiang1989/busyloop:latest
      resources:
        limits:
          cpu: 1
          memory: 100Mi
        requests:
          cpu: 1
          memory: 100Mi
    - name: testcontainer2 # Guaranteed
      image: dongjiang1989/busyloop:latest
      resources:
        limits:
          cpu: 200m
          memory: 100Mi
        requests:
          cpu: 200m
          memory: 100Mi
    - name: testcontainer3 # Burstable
      image: dongjiang1989/busyloop:latest
      resources:
        limits:
          cpu: 200m
          memory: 100Mi
        requests:
          cpu: 100m
          memory: 100Mi
    - name: testcontainer4 # Best-Effort
      image: dongjiang1989/busyloop:latest
      resources:
        limits:
          cpu: 200m
          memory: 100Mi
        requests:
          cpu: 100m
          memory: 100Mi

使用 ``

dongjiang@basa:~ $ kubectl describe node  kcs-cpu-test-s-wht2b
Name:               kcs-cpu-test-s-wht2b
...
Capacity:
  cpu:                4
  ephemeral-storage:  102350Mi
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             15899180Ki
  pods:               128
Allocatable:
  cpu:                4
  ephemeral-storage:  96589578081
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             15796780Ki
  pods:               128
System Info:
  Machine ID:                 a679d9cff58d494e972f86fccd3e26a9
  System UUID:                A56C5525-47D0-4185-B3D9-2BA12FD70297
  Boot ID:                    c4aae965-044c-4b24-9340-838385a65a6e
  Kernel Version:             4.14.78-300.el7.bclinux.x86_64
  OS Image:                   BigCloud Enterprise Linux For LDK 7 (Core)
  Operating System:           linux
  Architecture:               amd64
  Container Runtime Version:  containerd://1.4.4
  Kubelet Version:            v1.21.5
  Kube-Proxy Version:         v1.21.5
PodCIDR:                      172.19.3.0/24
PodCIDRs:                     172.19.3.0/24
ProviderID:                   ecloud://a56c5525-47d0-4185-b3d9-2ba12fd70297
Non-terminated Pods:          (47 in total)
  Namespace                   Name                                                      CPU Requests  CPU Limits  Memory Requests    Memory Limits      Age
  ---------                   ----                                                      ------------  ----------  ---------------    -------------      ---
  default                     cpusets-test                                              1500m (4%)    1500m (4%)  400Mi (1%)         400Mi (1%)         1d
  ....
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests              Limits
  --------           --------              ------
  cpu                3091m (77%)           3722m (93%)
  memory             4607031306240m (28%)  3600398346240m (22%)
  ephemeral-storage  0 (0%)                0 (0%)
  hugepages-1Gi      0 (0%)                0 (0%)
  hugepages-2Mi      0 (0%)                0 (0%)
Events:              <none>

风险

  1. Numa最多支持8 node的管理
  2. single-numa-node 模式下,会出现 Pod 准入错误 TopologyAffinityError 并处于 Terminated 状态;

其他

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。