Kubernetes Pod/Container NUMA亲和管理
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
的周期(默认10
s)相同。
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>
风险
- Numa最多支持8 node的管理
single-numa-node
模式下,会出现Pod
准入错误TopologyAffinityError
并处于Terminated
状态;
其他
- 点赞
- 收藏
- 关注作者
评论(0)