前言:PVE平台虚拟机调度策略
PVE (Proxmox Virtual Environment)是什么就不多介绍了,至少说现阶段在开源虚拟机平台尤其是超融合平台这一块,PVE还是无人能出其二。不过PVE在虚拟机设置方面还是有诸多遗憾,相比原生kvm+virsh管理反向阉割了诸多配置,比如绑定虚拟机CPU核心。而且官方明确表示没有在GUI加入cpu核心绑定相关设定。
而且全网搜索似乎没有中文相关的pve绑核操作,英文资料也只存在于论坛中,寥寥几句提到numa0 numa1 cpus,以及用taskset绑核。我就迷惑了,是大家都不屑于用多路系统还是从来不关心虚拟机NUMA Aware优化相关问题?或者就是这个是基本操作,默认都会设置了。。。
所以这里粗略总结了一下pve虚拟机对cpu和内存分布调度策略,以及打开numa选项后的运行逻辑。经验总结,不保证正确性,仅供讨论。
以下总结根据PVE 7.1在双路系统中的表现而得出:
- 默认的cpu调度是:按照整个宿主机系统的CPU情况来均分给个虚拟机,也就是双路两组NUMA的CPU核心看作一个整体均匀分配,虚拟机CPU大于等于2时就会跑在多个NUMA上。如果NUMA0的CPU已经满载了(特指宿主机运行大量使用CPU的程序占满NUMA0),此时新启动的虚拟机会优先跑在另一个NUMA1上;即便是已经启动虚拟机,系统也会考虑因为numa1负载低而调配vcpu到numa1运行。但是如果负载来自虚拟机且没有绑核则不会出现这种情况,因为虚拟机vcpu会被跨numa分配到各个物理核心以达到均匀。
- 默认设置下不勾选Enable NUMA,虚拟机内存分配会优先分配一个NUMA的内存,占满后再分配另一个
- 选上Enable NUMA则是缺页中断产生在哪个cpu,对应NUMA的内存分配给虚拟机
所以如果不开Enable NUMA,对双路互联系统会带来极大的负担,跨Sockets通讯将会十分频繁,因为一半的核心跑在另一个NUMA,而内存大多数情况都分配在一个NUMA。
如果打开Enable NUMA,由于无法判断虚拟机内程序运行情况,可能大量的缺页中断产生在numa0的cpu,导致numa0的内存被大量消耗,而numa1内存过剩,此时如果再申请numa0的内存,会产生OOM(Out Of Memory)报错,进而导致虚拟机停止运行。这样一来宿主机的内存利率用就会变低,原因是虚拟机申请的是NUMA Aware的内存,可能导致不同NUMA节点内存使用量不平衡。
要解决上述问题,就只能绑定CPU和内存到一个NUMA。而前面又说了,官方不提供虚拟机绑定CPU核心的选项。所以本文基于这样的现实情况来解决PVE虚拟机核心绑定 cpu pinning的问题。
方法1:通过hookscript实现绑核
编辑绑定核心文件 /etc/pve/qemu-server/your_vmid.cpuset
(your_vmid替换成虚拟机对应的vmid)
0-11 # 代表绑定cpu0,cpu1,...,cpu11共12核
编辑文件taskset-hook.sh
#!/bin/bash
vmid="$1"
phase="$2"
if [[ "$phase" == "post-start" ]]; then
main_pid="$(< /run/qemu-server/$vmid.pid)"
#cpuset="0-11"
cpuset="$(< /etc/pve/qemu-server/$vmid.cpuset)"
taskset --cpu-list --all-tasks --pid "$cpuset" "$main_pid"
fi
然后把脚本放到某个存储库(本位以local
为例)的 snippets
中:
cp taskset-hook.sh /var/lib/vz/snippets
chmod +x /var/lib/vz/snippets/taskset-hook.sh
最后对需要绑核的虚拟机VMID执行以下命令:
qm set VMID --hookscript local:snippets/taskset-hook.sh
如此虚拟机启动后进入post-start阶段时,PVE便会自动调用脚本通过taskset绑定对应vmid虚拟机跟物理机的核心。
注意这种方式一定要勾上ENABLE NUMA。另外调整配置时注意修改/etc/pve/qemu-server/your_vmid.cpuset
中的CPU核心配置
未解决的问题
taskset有bug(taskset from util-linux 2.36.1),使用-a参数绑核部分线程失败
只有这台机器上的PVE遇到了,重启也不能解决。。。另一台机器完美通过taskset绑核,两者系统是完全一样的,通过dd硬盘克隆的。迷惑。。。。。哪位大佬这知道是什么情况解决吗?
方法2:编辑虚拟机配置文件指定NUMA与CPU核心?
前排警告:numa[n]相关参数是配置虚拟机模拟的numa拓扑,而非跟宿主机之间的映射关系!同时要确保numa[n]中的核心数量内存大小等跟虚拟机设置的核心数量、内存大小一致,否则启动会报错。不推荐使用该方法配置。
经过我实际测试,在PVE 7.1版本下,编辑配置文件中numa[n]相关参数,并不能绑定虚拟机到指定CPU核心或者指定NUMA节点。
参考PVE文档:
numa: <boolean> (default = 0)
Enable/disable NUMA.
numa[n]: cpus=<id[-id];...> [,hostnodes=<id[-id];...>] [,memory=<number>] [,policy=<preferred|bind|interleave>]
NUMA topology.
cpus=<id[-id];...>
CPUs accessing this NUMA node.
hostnodes=<id[-id];...>
Host NUMA nodes to use.
memory=<number>
Amount of memory this NUMA node provides.
policy=<bind | interleave | preferred>
NUMA allocation policy.
实际上这个numa配置的是虚拟机的numa拓扑,而不是物理机跟虚拟机的映射!
cpus对应的虚拟机配置中的sockets*cores的数量下的映射,而非映射物理机cpu_id
memory对应的虚拟机内部看到的NUMA节点的memory大小
hostnodes我实测发现有时并不能把同一行配置的cpus绑定在同一个宿主机numa上,但是有时又可以。所以我认为hostnodes并不能正确的绑定物理机中的虚拟机线程到对应的numa节点的cpu上。
换言之这种绑核方式就像黑盒,该配置不是虚拟机numa拓扑跟物理机的映射,而是给vm manager的一个参考,实际还是看调度,所以看我觉得不如taskset简单粗暴可靠。
编辑虚拟机配置文件 /etc/pve/qemu-server/vmid.conf
在numa条目下方插入一行,内容如下:
numa0: cpus=0-3,hostnodes=0,memory=4096,policy=bind
numa1: cpus=4-7,hostnodes=0,memory=4096,policy=bind
该配置对应的虚拟机设置为sockets:2,cores:4,memory:8192MB,配置之后的numa拓扑为两个numa节点,每个numa节点包含4个核心4G内存
0 条评论