背景 链接到标题
PVE 虚拟机调整内存有两种常见场景:
- 扩容:虚拟机需要更多内存,希望不停机直接添加
- 宿主机压力回收:宿主机内存不足时,临时压缩虚拟机内存
传统方式需要关机修改再开机,导致服务中断。通过 Hotplug 和 Ballooning 可以解决这两个问题。
内存热添加(Hotplug) 链接到标题
原理 链接到标题
QEMU 在启动时可以预留内存槽位(slots)和最大内存上限(maxmem),运行中通过 device_add 命令插入 pc-dimm 设备来增加内存。
配置步骤 链接到标题
# 1. 启用 memory hotplug 和 numa
qm set <vmid> --hotplug "memory"
qm set <vmid> --numa 1
# 2. 首次需要 shutdown + start(让 QEMU 带上 slots/maxmem 参数)
qm shutdown <vmid>
qm start <vmid>
首次启动后 QEMU 命令行会变为类似:
-m size=1024,slots=255,maxmem=131072M
在线扩容 链接到标题
# 直接修改内存值,立即生效,无需重启
qm set <vmid> --memory 8192
QEMU 会自动创建新的 memory backend 对象并插入 pc-dimm 设备,Guest OS 识别到新的 ACPI 事件后自动 online 新增内存。
注意事项:热减不可靠 链接到标题
内存热减(hot-unplug)在 QEMU/Linux 中不可靠,主要受以下限制:
- Linux 内核限制:Linux 内核会在某些内存页上标记为不可移动(unmovable),如果这些分配恰好在要移除的 DIMM 上,内核无法 offline 该内存块。如 Proxmox 论坛所述:“if linux kernel have set some memory pages as unmovable, it’s impossible to unplug the dimm”1
- 随机失败:热减的成败取决于 Guest OS 当前的内存分布,具有随机性。“it’s a linux limitation, it’s really random working/non working (not working with windows too)”2
- 生产环境高负载时几乎必然失败:数据库等应用会分配大量不可移动页面,热减时会出现
dimm38: error unplug memory module错误3 - PVE 曾有 Bug:旧版
foreach_reverse_dimm实现存在逻辑错误,热减后内存计数不准确4 movable_node方案有副作用:虽然可以让更多内存成为可移动区域,但会导致 Normal zone 内存不足,触发 OOM killer 误杀进程5
因此,减小内存的推荐做法是关机修改再开机,不要依赖热减。
内存动态回收(Ballooning) 链接到标题
原理 链接到标题
PVE 创建的虚拟机默认带有 virtio-balloon-pci 设备。pvestatd 守护进程监控宿主机内存压力:
- 宿主机内存吃紧 → inflate balloon(压缩虚拟机内存)
- 宿主机内存充裕 → deflate balloon(自动归还给虚拟机)
配置弹性区间 链接到标题
设置 balloon 下限,为自动缩放留出空间:
# 虚拟机 8GB,下限 4GB,PVE 可在 4G~8G 之间自动平衡
qm set <vmid> --memory 8192 --balloon 4096
查看运行中的 balloon 状态:
qm monitor <vmid>
# 在 monitor 中输入:
info balloon
输出示例:
balloon: actual=8192 max_mem=8192 total_mem=7901
手动临时调整 链接到标题
如果需要在宿主机压力较大时立即回收,可通过 QEMU monitor 手动操作:
echo "balloon 4096" | qm monitor <vmid>
注意:这只是临时生效,balloon 配置项在 PVE 中定义的是最小值下限,实际 balloon 由 pvestatd 自动管理。
完整配置示例 链接到标题
以一台 4GB 的虚拟机为例,配置热添加和弹性回收:
# 启用 hotplug 和 numa
qm set 6000 --hotplug "memory"
qm set 6000 --numa 1
# 第一次:关机关机加载新配置
qm shutdown 6000
qm start 6000
# 在线扩容到 6GB
qm set 6000 --memory 6144
# 设置 balloon 下限 4GB,保留弹性空间
qm set 6000 --balloon 4096
总结 链接到标题
- Hotplug:解决在线扩容问题,配置简单可靠(仅限增大)
- Ballooning:解决宿主机压力调度问题,自动弹性伸缩
- 热减不可靠:缩小内存请关机操作,不要依赖 hot-unplug
- 首次配置后,后续调整内存均可在线完成
-
Proxmox Support Forum — Debian RAM hot-unplug error: The module couldn’t be unplugged, most likely because the guest kernel was unable to relocate memory ↩︎
-
Proxmox Support Forum — Hotplug memory downgrade is not working: it’s a linux limitation, it’s really random working/non working ↩︎
-
Proxmox Support Forum — TASK ERROR: dimm38: error unplug memory module: error unplug memory module in production ↩︎
-
Proxmox qemu-server commit — memory: don’t use foreach_reversedimm for unplug: fix existing bug with reverse dimm iteration ↩︎
-
PVE-User mailing list — Memory Hotplug Woes: movable_node leads to OOM kills with postgresql ↩︎