Skip to content

Commit 6145023

Browse files
committed
add cpu mem node binding docs
1 parent 186649f commit 6145023

File tree

1 file changed

+137
-0
lines changed

1 file changed

+137
-0
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
---
2+
title: Cloudpods 虚拟机 CPU 绑核与 NUMA 内存分配策略
3+
date: 2025-03-22
4+
slug: kvm-cpu-mem-node-binding
5+
authors:
6+
- name: Yaoqi Wan
7+
url: https://github.com/wanyaoqi
8+
image_url: https://github.com/wanyaoqi.png
9+
---
10+
11+
Cloudpods 在最新的版本对虚拟机 CPU 绑核与 NUMA 内存分配做了一些优化,默认情况下虚机会倾向于使用距离较近的 CPU 和 NUMA 内存。本文将会介绍 CPU 绑核与 NUMA 内存分配策略的具体内容以及一些相关的配置。
12+
13+
<!-- truncate -->
14+
15+
## 1. 宿主机 CPU 与内存预留
16+
17+
在介绍虚拟机 CPU 绑核与 NUMA 内存分配策略之前需要先介绍一下宿主机 CPU 与内存预留的功能,你需要对你的宿主机 CPU 与内存使用有一个规划,虚拟机使用的是除去预留资源之外的资源。
18+
19+
### 1.1 CPU 预留
20+
21+
CPU 预留的主要目的是将一些宿主机服务使用的 CPU 与虚机使用的 CPU 隔离开,避免宿主机服务与虚机之间相互影响,如果宿主机上没有负载很高会影响到虚机的服务则不用配置。
22+
23+
```bash
24+
$ climc host-reserve-cpus --help
25+
Usage: climc host-reserve-cpus [--mems MEMS] [--disable-sched-load-balance] [--processes-prefix PROCESSES_PREFIX] [--help] [--cpus CPUS] <ID> ...
26+
27+
# 参数介绍
28+
# --cpus 对应的是 cpuset.cpus: 限制进程组使用的 CPU。
29+
# --mems 对应的是 cpuset.mems, 限制可以使用的memory节点。
30+
# --disable-sched-load-balance 对应 cpuset.sched_load_balance flag。
31+
# --processes-prefix 指定需要绑定到 reserve cpus 的进程第 0 个参数,即可执行文件名
32+
33+
# example: 预留CPU 0-1,38-39 ,并将 ovs-vswitchd 与 kubelet 进程限制到预留的 CPU 内
34+
$ climc host-reserve-cpus --cpus "0-1,38-39" --processes-prefix ovs-vswitchd --processes-prefix /usr/bin/kubelet test-host01
35+
```
36+
37+
CPU 预留功能是通过 cgroup 来实现的,在 host-agent 服务启动时会执行 CPU 预留以及指定进程绑定到预留服务的功能。
38+
39+
### 1.2 内存预留
40+
41+
使用 NUMA 内存分配需要开启宿主机大页功能,所以这里只介绍宿主机开启大页如何预留内存。
42+
默认情况下宿主机开启大页的预留策略是:预留宿主机 20% 的内存,最大不超过 32G,如果想要手动配置宿主机的预留内存,则可以通过设置 oc-hugetlb-gigantic-pages.service 服务添加 Environment RESERVED_MEM 来配置。
43+
44+
## 2. CPU 绑核与 NUMA 内存分配策略
45+
46+
以一台有两个 NUMA node 的宿主机为例:
47+
```bash
48+
$ numactl -H
49+
available: 2 nodes (0-1)
50+
node 0 cpus: 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38
51+
node 0 size: 128925 MB
52+
node 0 free: 1066 MB
53+
node 1 cpus: 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39
54+
node 1 size: 128997 MB
55+
node 1 free: 636 MB
56+
node distances:
57+
node 0 1
58+
0: 10 21
59+
1: 21 10
60+
```
61+
62+
假设预留了 CPU 0-1,38-39 给系统服务使用,则虚机能使用的 CPU 为node0, node1 两边各 18 个:
63+
- node0: 2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36
64+
- node1: 3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37
65+
66+
node0 与 node1 分别预留了 16G 内存,每边还剩 112G 内存。
67+
68+
### 2.1 分配策略
69+
70+
CPU 绑核与 NUMA 内存分配策略是尽量将 CPU,内存,GPU 等透传设备分配到同一 NUMA node 节点上,并且尽量保持 NUMA node 之间的分配均衡。
71+
72+
- 尽量分配到同一 NUMA node 节点上:
73+
- 当申请的虚机配置低于宿主机单个 NUMA node 配置时, 则会尽量将虚机的 CPU、内存、透传设备等分配到同一 node 上;如上面描述的宿主机单个 NUMA node 配置为 18C112G,申请的虚机配置为 16C32G,则会尽量执行该策略,虚机有一个 NUMA node,配置为 16C32G,落在宿主机的 node0 / node1 上。
74+
- 当申请的虚机配置高于宿主机单个 NUMA node 配置时,则会将虚机的配置均分到两个 NUMA node,如果两个 NUMA node 依旧无法提供足够的配置,会将虚机的配置均分到四个 NUMA node,以此类推;如上面描述的宿主机单个 NUMA node 配置为 18C112G,申请的虚机配置为 32C64G,则虚机有两 NUMA node,虚机的每个 NUMA node 16C/32G,分别落在宿主机的 node0 和 node1 上。
75+
- 尽量保持 NUMA node 之间均衡:
76+
- NUMA 内存均衡,在分配选择 NUMA 节点时会优先选择内存分配率更低的 NUMA node。
77+
- CPU 分配均衡,在内存分配率相同的情况下会优先选择 CPU 分配率更低的 NUMA node。
78+
- GPU 分配均衡,假设同一种型号 GPU 在多个 NUMA node 上分别有 GPU,则分配时也会选择 GPU 分配率更低的 NUMA node。
79+
80+
### 2.2 host-agent 分配与调度分配
81+
82+
- host-agent 分配:宿主机开启大页,并且设置 enable_host_agent_numa_allocate
83+
84+
```bash
85+
$ vi /etc/yunion/host.conf
86+
enable_host_agent_numa_allocate: true
87+
```
88+
89+
host-agent 分配是由调度器先选择宿主机,然后在宿主机内做 CPU 绑核与 NUMA 内存策略分配。
90+
91+
- 调度分配:宿主机开启大页,宿主机开启 NUMA 策略分配
92+
93+
```bash
94+
$ climc host-update --enable-numa-allocate True <HOST_ID>
95+
```
96+
97+
调度器分配则会在调度时考虑该宿主机的 NUMA node 情况,能否将 CPU、内存、GPU等分配到同一个 NUMA node 会影响宿主机打分。并且调度器会分配 VCPU 与 PCPU 的绑定关系。
98+
99+
### 2.3 查看虚机 cpu_numa_pin
100+
101+
- 由调度器分配的通过虚机 metadata 查看:
102+
```bash
103+
$ climc --output-format kv server-metadata test-server | grep cpu_numa_pin
104+
__cpu_numa_pin: [{"node_id":1,"size_mb":8192,"vcpu_pin":[{"pcpu":31,"vcpu":0},{"pcpu":33,"vcpu":1},{"pcpu":35,"vcpu":2},{"pcpu":37,"vcpu":3}]}]
105+
```
106+
107+
- 宿主机上通过虚机描述文件查看: cat /opt/cloud/workspace/servers/<ID>/desc | jq .cpu_numa_pin
108+
109+
### 2.4 查看虚机 cpuset 绑核信息
110+
111+
虚机所属的 cgroup 默认是在 /sys/fs/cgroup/cpuset/cloudpods.hostagent 下,命名方式为 server_<ID>_<PID>。
112+
113+
```bash
114+
$ cat /sys/fs/cgroup/cpuset/cloudpods.hostagent/server_<ID>_<PID>/cpuset.cpus
115+
116+
# 如果开启了 VCPU 与 PCPU 绑定关系,server_<ID>_<PID> 下还会有 ThreadID 命名的 VCPU 线程目录,可以查看 VCPU 线程 cpuset
117+
$ cat /sys/fs/cgroup/cpuset/cloudpods.hostagent/server_<ID>_<PID>/<ThreadID>/cpuset.cpus
118+
119+
```
120+
121+
## 3. 虚机预留 CPU
122+
123+
除了以上描述的 CPU 绑核分配策略外,Cloudpods 还支持单独为虚机预留 CPU。
124+
125+
```bash
126+
$ climc server-cpuset
127+
Usage: climc server-cpuset [--help] <ID> <SETS>
128+
129+
eg: 为虚机 test-server 预留 2,4,6,8
130+
$ climc server-cpuset test-server 2,4,6,8
131+
预留后只有 test-server 虚机能用使用 2,4,6,8 CPU
132+
```
133+
134+
## 总结
135+
136+
Cloudpods 默认提供了以 NUMA node 为均衡的分配策略,同时也提供了接口支持定制化的绑核需求,你可以根据自己的业务来选择策略。
137+

0 commit comments

Comments
 (0)