跳转到内容

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 的读性能。

确认恢复 ​

  1. free -h 的 available 回到有明显余量的水平,能覆盖客户机内存使用的正常波动。
  2. arc_summary 里的 c_max 符合你设置的预期值。
  3. 之前因为内存不足受影响的客户机能正常开机、正常运行。
  4. 观察几天,dmesg/journalctl -k 里没有新的 OOM 相关记录。

仍未解决 ​

带上以下信息求助:

sh
arc_summary
free -h
dmesg | grep -i "out of memory"

外加物理内存总量、所有客户机的内存分配加总,以及是否已经调整过 zfs_arc_max 和调整前后的数值。参考如何有效求助。

参考资料 ​

Proxmox VE 非官方中文使用指南,与 Proxmox Server Solutions GmbH 无隶属关系。