HQY

×

PVE 装完发现内存被吃了 15GB?ZFS 干的,但别慌

hqy hqy 发表于2026-05-29 15:30:40 浏览18 评论0

抢沙发发表评论

? 开篇故事

某天我登上一台刚装好的 PVE 节点,准备美滋滋地部署几个 LXC 容器。一个 free -h 下去,直接愣住了:

              total        used        free
Mem:           31Gi        24Gi       6.6Gi

等等?31GB 内存,用了 24GB? 我 VM 和 CT 加起来还不到 4GB 啊,剩下的 20GB 谁吃了?

再一看——ZFS ARC 占了 15GB。好家伙,系统自己就干掉了半台机器的内存。


这不是 bug,也不是中毒,是 ZFS 的 ARC(自适应替换缓存) 在干活。这篇文章就把这件事彻底讲清楚。


? ARC 是什么?ZFS 为什么这么能吃?

传统文件系统 vs ZFS

       

                                           
特性传统文件系统(ext4/xfs)ZFS
缓存机制Page Cache(内核管)ARC(ZFS 自己管)
缓存上限系统自动调节默认占物理内存的 50%
缓存内容文件数据文件数据 + 元数据 + 压缩表 + 去重表
缓存能效一般极高(COW 特性加成)
开箱即用省心"我全都要"模式
       
     

ZFS 的哲学是:闲着也是闲着,不如把内存拿来当缓存。因为 ZFS 是 Copy-on-Write(写时复制)文件系统,对缓存的需求天然比传统文件系统高——多一层缓存就少一层磁盘 IO,性能差距非常明显。

ARC 默认吃多少?

ARC 上限 = 物理内存 × 50%

我的 31GB 机器 → 15.5GB 归 ARC。如果是 64GB → 32GB 归 ARC。128GB → 64GB 归 ARC

数据越热(经常读写),ARC 越膨胀。数据越冷(没人访问),ARC 自动收缩还给系统。


? ARC 到底缓存了啥?

       

                                           
缓存内容占比说明
文件数据最大头你读写过的 VM/CT 磁盘文件
元数据少量目录结构、文件属性、ZAP 对象
压缩缓存看情况压缩后的数据块(LZ4/ZSTD)
去重表(DDT)启用去重才用一般不启用
       
     

这也是为什么 ZFS 吃内存比传统文件系统狠——它缓存的不只是"文件内容"。


?️ 怎么看 ARC 吃了多少?

几个命令干活:

# 看 ARC 总大小和命中率
arcstat 1 3

# 或直接看 /proc/spl/kstat/zfs/arcstats
cat /proc/spl/kstat/zfs/arcstats | grep -E "^(size|c|hits|misses)"

arcstat 输出示例:

    time  read  miss  miss%  dmis  dmizm  pmis  pmism  dds  dds%  size  c
   12:00  3.2K   12   0.4%    12    0.0%     0    0.0%    0     0   14G  15G

重点看:

  • size:当前 ARC 占了多少内存(14G)

  • c:ARC 上限(15G),接近上限说明满负荷

  • miss%:缓存未命中率,越低越好(通常 < 5%)


⚠️ 什么时候需要手动管?

ARC 不是吃白饭的——系统内存紧张时,ARC 会自动释放。但有些场景它"自动"得不够快:

       

                                           
场景表现建议
VM/CT 少(2-3 个)ARC 占 50%,纯浪费手动限制到 20-30%
机器内存小(8-16GB)ARC + VM 抢内存限制到 2-4GB
需要跑数据库/高负载应用VM 内应用卡顿限制到 2-4GB,留给应用
大内存 + 大量 VM(64GB+)ARC 物尽其用不用管,默认 50% 很合理
ZFS 作为主存储 + 大量 IOARC 越高越快甚至可以上调到 70-80%
       
     

一条金线:VM/CT 分配的总内存 + ARC 上限 ≤ 物理内存 × 0.9,留 10% 给系统和突发。


? 三种限制 ARC 的方法

方法一:热写入(即时生效,重启失效)

最适合临时调整,不想重启节点:

# 立即将 ARC 上限设为 8GB(单位:字节)
echo "8589934592" > /sys/module/zfs/parameters/zfs_arc_max

# 验证
cat /sys/module/zfs/parameters/zfs_arc_max

效果立竿见影——ARC 会立刻开始回收,把内存还给系统。适合"先试试 8GB 够不够用"的场景。

我的案例:从 15GB 限到 8GB,free -h 立马释放 7GB,VM 一个都没重启。

方法二:modprobe.d 持久化(需重启)

想永久生效,写入配置文件:

# 写入持久化配置
echo "options zfs zfs_arc_max=8589934592" >> /etc/modprobe.d/zfs.conf

# 重启后生效
reboot

适合"确定 8GB 够用"后一次性搞定。

方法三:不限制(默认)

什么都不做也行。ZFS 的 ARC 是可回收缓存——内核内存紧张时系统会自动触发回收,优先级比应用内存低。

唯一的代价是:回收需要时间。如果你突然启动一个吃内存的大 VM,系统得先等 ARC 腾出空间,启动会比平时慢几秒。


? 真实案例

我的一台 PVE 节点(31GB 内存):

       

                                           
阶段ARC 占用可用内存VM/CT 数负载表现
默认(未限制)15GB6.6GB8 个偶尔卡顿
限制到 8GB7.8GB13.5GB8 个丝滑流畅
限制到 4GB3.9GB16GB8 个丝滑,IO 无明显下降
       
     

结论:8GB ARC 对大多数 Homelab 场景绰绰有余。即使我从 15GB 砍到 8GB,ARC 命中率从 99.7% 掉到 99.5%——几乎没区别。



? 写在最后

ZFS 吃内存不是 bug,是特性。它默认的"我全都要"策略在服务器场景很合理——内存不用来缓存就是浪费。但在 Homelab 里,16-32GB 的机器上被 ARC 吃掉一半,确实会让人心跳加速。

我的建议:

  • 装完先看arcstat 看看 ARC 实际占了多少

  • 够用就别动:VM 运行顺畅就没必要管

  • 不够再限:热写入 zfs_arc_max 试个舒服的值,再决定要不要持久化

搞定这些,你的 PVE 就不会"开机就吃掉半条命"了 ?


? 相关命令

       

                                           
命令作用
arcstat 1 3实时监控 ARC 命中率
cat /proc/spl/kstat/zfs/arcstats查看 ARC 详细统计
echo N > /sys/module/zfs/parameters/zfs_arc_max热修改 ARC 上限
cat /sys/module/zfs/parameters/zfs_arc_max查看当前 ARC 上限
free -h查看系统内存使用
         


打赏

本文链接:https://www.kinber.cn/post/6584.html 转载需授权!

分享到:


推荐本站淘宝优惠价购买喜欢的宝贝:

image.png

 您阅读本篇文章共花了: 

群贤毕至

访客