在 Proxmox VE 中,KSM(Kernel Samepage Merging)相关的服务(ksmtuned)通常是默认安装并设置为开机启动的。
但是,它并不是一直在后台疯狂扫描合并内存,而是按需触发的。默认情况下,只有当宿主机的可用内存低于总内存的 20% 时,KSM 才会真正开始介入工作。
在具体设置之前,需要先明确一个关于 LXC 的关键技术细节,这决定了你是否需要去折腾它。
⚠️ 核心提示:KSM 对 LXC 的实际效果
虽然 KSM 是内存去重的利器,但它主要是为 KVM 虚拟机设计的。
- 对于 KVM 虚拟机: 底层的 QEMU 进程会主动通过
madvise(MADV_MERGEABLE)系统调用,告诉宿主机内核:“我的这部分内存是可以被扫描和合并的”。因此 KSM 对 KVM 效果极佳。 - 对于 LXC 容器: LXC 运行的是普通的 Linux 进程。绝大多数常规软件(如 Nginx、MySQL、PHP)在编写时,并没有主动声明自己的内存页可以被合并。由于 Linux 内核出于安全和性能考虑,默认只会扫描声明过的内存区域,因此即使开启了 KSM,它对纯 LXC 环境的内存节省效果也非常有限。
在 LXC 环境下,容器之间共享内存主要依靠的是 Linux 原生的共享库(Shared Libraries)和页面缓存(Page Cache)。例如,如果你开了 5 个 Debian LXC,它们底层加载的 libc.so 在物理内存中天然就只有一份,不需要 KSM 来插手。
如果你混合使用了 KVM 虚拟机,或者想极限压榨环境测试一下 KSM 能否捡漏,可以按照以下方法进行设置:
如何查看和设置 KSM
1. 查看当前 KSM 状态
首先确认 KSM 守护进程是否在运行:
Bash
systemctl status ksmtuned查看内核底层当前是否激活了 KSM 扫描(0 代表停止,1 代表运行,2 代表正在运行且不合并):
Bash
cat /sys/kernel/mm/ksm/run查看 KSM 目前为你实际节省了多少内存(单位是页,通常一页是 4KB,数值乘以 4 就是节省的 KB 数):
Bash
cat /sys/kernel/mm/ksm/pages_sharing2. 调整 KSM 触发阈值
控制 KSM 何时启动的配置文件位于 /etc/ksmtuned.conf。在气球内存剧烈波动的 VPS 上,默认的 20% 剩余内存触发线可能不够灵敏。
编辑该文件:
Bash
nano /etc/ksmtuned.conf找到并修改以下关键参数:
Ini, TOML
# 默认是 20。代表当宿主机可用内存低于 20% 时启动 KSM。
# 如果你想让它更早介入,可以调高这个值,比如调到 40 (可用内存低于 40% 就启动)
KSM_THRES_COEF=40
# KSM 扫描的激进程度,默认每次扫描休眠一定毫秒数。数值越低,扫描越快,但吃 CPU
# KSM_SLEEP_MSEC=10修改完成后,重启服务使其生效:
Bash
systemctl restart ksmtuned3. 强制全局开启 KSM(不建议长期使用)
如果你想无视内存阈值,强制内核立刻开始扫描并合并内存,可以直接向内核参数写入指令:
Bash
echo 1 > /sys/kernel/mm/ksm/run注意:强制开启会导致系统 CPU 占用率出现一定程度的常驻升高,因为内核需要不断地在后台对比各个内存页的数据特征(算 Hash),这对于性能本来就不强的 VPS 可能是个负担。
总结
对于你当前这台内存靠“气球”动态分配的 VPS:
如果你的主要业务都是基于 LXC 容器,把精力花在调优 KSM 上性价比极低。不如优先考虑部署 ZRAM(如前所述)以及使用 Alpine Linux 等极简镜像来代替臃肿的系统模板,这才是对抗内存 OOM 最直接有效的手段。