外观
ZFS ARC 吃光内存
适用范围
free -h 显示内存几乎用满,但把所有客户机分配的内存加起来远小于物理内存总量,怀疑或已确认是 ZFS 的 ARC(自适应替换缓存)占用导致——包括新建或启动客户机时报"无法分配内存",甚至宿主机触发了 OOM(内存耗尽)。
开始排查前
记录:
- 物理内存总量。
- 所有正在运行的客户机分配内存加总(
qm list、pct list结合各自配置手动加总,或看 Summary 页面)。 - 是否已经设置过
zfs_arc_max。
排查步骤
1. 先区分「看起来满」和「真的满」
sh
free -h看 available 这一列,不是 used。ZFS 的 ARC 作为缓存计入 used,但理论上会在系统需要时释放,所以 used 高不等于真的紧张。
available 也很小(比如低于总内存的 10%) → 确实紧张,继续下一步。
available 充裕 → 目前只是视觉上"看起来满",不需要处理,可以停在这里。
2. 确认 ARC 当前占用
sh
arc_summary | head -30或者直接看具体数值(单位是字节):
sh
cat /proc/spl/kstat/zfs/arcstats | grep -E '^(size|c_max|c_min)'3. 检查是否已经设过上限
sh
cat /sys/module/zfs/parameters/zfs_arc_max
cat /etc/modprobe.d/zfs.conf 2>/dev/null从没设置过上限:默认上限通常是物理内存的相当大一部分,这个默认值是为专用存储服务器设计的,在同时跑客户机的虚拟化宿主机上通常偏高,需要主动设置——进入步骤 6。
已经设过,但依然紧张:可能是设置的上限本身就偏高,或者紧张的原因根本不是 ARC——继续下一步排除。
4. 排除其他进程占用内存
sh
ps aux --sort=-%mem | head -20确认没有别的进程(比如某个客户机的 QEMU 进程占用超过它配置的内存、或者某个失控的宿主机进程)才是真正的元凶。
5. 检查是否已经影响到客户机
sh
dmesg | grep -i "out of memory"
journalctl -k | grep -i "killed process"已经出现 OOM killer 日志,或者客户机因为内存不足无法开机("cannot allocate memory" 之类报错):情况比较紧急,尽快设置合理的 ARC 上限并安排重启;在重启之前,如果有条件,可以先临时迁移或关闭部分非关键客户机降低当前压力。
还没出现 OOM,只是 available 偏低:不那么紧急,按正常节奏设置上限即可。
6. 计算合理的 ARC 上限
没有放之四海而皆准的数值,常见的经验做法是给 ARC 分配总内存的 10%–25%,同时保证不低于几个 GB,并且给宿主机自身和所有客户机预留足够的内存。比如一台 64 GB 内存、客户机总共分配了 40 GB 的机器,给 ARC 留 8–12 GB 通常比较合理,具体还要看实际的缓存命中收益。
7. 设置上限
sh
echo "options zfs zfs_arc_max=8589934592" > /etc/modprobe.d/zfs.conf
update-initramfs -u -k all上面的例子把上限设为 8 GiB(8589934592 字节),请按你自己算好的数值替换。
想先临时验证效果、不用等重启:
sh
echo 8589934592 > /sys/module/zfs/parameters/zfs_arc_max这条命令写入的是运行时参数,重启后会失效,只适合用来验证设置的数值有没有明显改善内存压力。
永久生效需要重启宿主机
写进 /etc/modprobe.d/zfs.conf 并执行 update-initramfs 之后,必须重启宿主机才会真正持久生效——运行中的 ZFS 模块参数无法在线卸载重载(意味着要先卸载所有池,这在生产环境不现实)。
安排一个可以让客户机短暂下线或者提前完成迁移/维护通知的时间窗口执行重启,不要在没有准备的情况下直接重启生产宿主机。回退方式:如果新的上限设置导致性能明显变差,把 zfs_arc_max 改回更大的值(或者删掉这一行恢复默认),同样需要 update-initramfs 加重启才能生效。
8. 重启后验证
sh
arc_summary | head -10
free -h确认 c_max 变成了设置的值,available 相比之前有明显改善。
9. 如果调低之后读性能明显下降
ARC 同时也是加速读取的缓存,压得太低会让缓存命中率下降,多个客户机共享同一存储时感受会更明显。这是内存和性能之间的权衡,没有一刀切的最佳值,可以适当调高一点再观察一段时间。
10. 长期内存持续紧张
如果多次调整之后依然感觉内存紧绷,更合理的方向是加内存,而不是一味压低 ARC——过低的 ARC 会明显拖慢 ZFS 的读性能。
确认恢复
free -h的available回到有明显余量的水平,能覆盖客户机内存使用的正常波动。arc_summary里的c_max符合你设置的预期值。- 之前因为内存不足受影响的客户机能正常开机、正常运行。
- 观察几天,
dmesg/journalctl -k里没有新的 OOM 相关记录。
仍未解决
带上以下信息求助:
sh
arc_summary
free -h
dmesg | grep -i "out of memory"外加物理内存总量、所有客户机的内存分配加总,以及是否已经调整过 zfs_arc_max 和调整前后的数值。参考如何有效求助。