PVE折腾笔记 (3) 在原QNAP使用的硬盘上创建ZFS

前言

在经过一番研究后,我决定使用ZFS作为俩机械硬盘的文件系统,本来也可以和QNAP一样直接ext4的,但ZFS比较安全,有自愈功能,可以处理比特位翻转的问题,总之就是好用。

如果追求灵活性可以使用Btrfs,这方面有个大佬讲得不错,可以参考一下: 数据硬盘分区:Btrfs文件系统 - 从零开始的NAS/小型服务器搭建

一句话理解:ZFS 不只是文件系统,它是一套智能的存储解决方案。

ZFS(Zettabyte File System)是由 Sun Microsystems 开发的一种开源的先进文件系统和逻辑卷管理器。

与传统文件系统(如 ext4、NTFS)不同,ZFS 融合了文件系统 + RAID + 卷管理于一体。

关键词:自修复、快照、高可靠性、大容量支持

查看硬盘

主要使用 fdisk -llsblk 这两个命令。

  • fdisk -l:查看磁盘的 分区信息(偏底层、原始)
  • lsblk:查看磁盘的 块设备树状结构(更直观、面向人类)

命令说明:

🧱 fdisk -l

  • 全称是 "list partition table"

  • 显示所有磁盘和它们的 分区信息、容量、文件系统类型(MBR/GPT)等

  • 需要 root 权限(所以常用 sudo fdisk -l

  • 输出示例:

    复制代码
    pgsql复制编辑Disk /dev/sda: 512 GB
    Device     Boot Start       End   Sectors   Size Type
    /dev/sda1  *     2048    999423    997376   487M EFI System
    /dev/sda2        999424 976773119 975773696 465G Linux filesystem
  • 📌 更偏"底层",有助于了解磁盘分区表结构。

🌳 lsblk

  • 全称是 "list block devices"

  • 显示所有的块设备(磁盘、分区、LVM、RAID 等)以及它们的挂载情况

  • 类似树状结构,更加 直观

  • 不显示挂载点为空的 loop 设备(除非加参数)

  • 默认不需要 root 权限

  • 输出示例:

    复制代码
    pgsql复制编辑NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
    sda      8:0    0   512G  0 disk
    ├─sda1   8:1    0   487M  0 part /boot/efi
    └─sda2   8:2    0 511.5G  0 part /
  • 📌 更适合用来 快速识别哪个设备挂载到哪个目录 ,比如你插了新 SSD,它就会以 /dev/sdX/dev/nvmeXn1 的名字出现。

备份数据

参考我之前的内容

有几种方法:

  • rsync: rsync -a --info=progress2 /mnt/disk1/your-folder /mnt/disk2/
  • Midnight Commander (mc) (可视化)

推荐用 mc,注意如果是 SSH 到服务器操作的话,一定得用 screen 之类的工具开启后台会话,防止复制到一半连接断了。

备份完成后请自行校验数据。方法也可以参考我之前的文章。

格式化硬盘

最简单的方法是只有用 PVE 里的 Wipe Disk 功能。

报错

不过我在使用的时候遇到报错: disk/partition '/dev/sda1' has a holder

分析下原因,holder 代表仍有内核对象在使用这块分区

常见持有者(holders)

设备类型 检查命令 典型出现在 QNAP 旧盘里的原因
LVM PV → dm-? pvs, lsblk -o NAME,TYPE QTS 默认把整盘卷进 vg1/lv1
mdraid → md127 mdadm --detail --scan QTS 可能创建过软 RAID 缓存区
dm-crypt / luks lsblk -f 如果开了加密共享
挂载点 `mount grep sda1`

只要还有 holders ,Proxmox 的 wipe_disk 脚本(本质是 sgdisk --zap-all + wipefs -a)就会被内核拒绝写入,从而抛出 500 错误。

排查方式

bash 复制代码
lsblk -f
ls /sys/block/sda/sda1/holders

输出如 dm-0 dm-1 → 说明被 LVM/MD 等占着

解决方法

⚠️ 所有命令请确认磁盘名(这里用 /dev/sda 举例),误操作会立刻毁灭数据!

步骤 命令 说明
1️⃣ 卸载挂载点 umount -f /dev/sda? 2>/dev/null 保证分区不在用
2️⃣ 停用 LVM vgchange -an vg1 lvremove -f /dev/vg1/lv1 pvremove /dev/sda1 vg/lv 名字以 pvs, vgs 查询为准
3️⃣ 停掉 mdraid mdadm --stop /dev/md127 mdadm --zero-superblock /dev/sda1 lsblk 显示有 md*
4️⃣ 最终抹签名 sgdisk --zap-all /dev/sda wipefs -a /dev/sda 等同 PVE "Wipe Disk"

做完再 ls /sys/block/sda/sda1/holders ------ 目录应为空

这时回到 Web UI 点 Wipe Disk 就不会报错了。

创建 ZFS

在 Web UI 里,选择节点(我的是叫 PVE) - 磁盘 - ZFS - 创建 ZFS

太长不看:选择磁盘,填写名称,RAID 级别选单磁盘,如果想冗余的话可以选 Mirror,压缩选 lz4,ashift 选 12

想深入了解的同学可以看以下说明

推荐方案

RAID 级别:按容量、性能、容错、重建速度等权衡选择(mirror/raid10 偏性能+小规模,raidzN 偏容量+简单,draidN 偏容量+快速自愈)。

压缩算法 :若不特殊需求,直接选 lz4(或 on);要极限压缩可考虑 zstdgzip

ashift :现代盘选 12

这些参数都是啥意思?

RAID 级别(Pool 布局)

类型 最少盘数 容错能力 特点与适用场景
mirror ≥2 1 盘(每个 mirror 组内) 将每块盘数据完全镜像到另一块盘,读性能略优、写性能与单盘相当;推荐对性能和可靠性都较敏感的小规模部署。
raid10 ≥4 最少可容忍 1 个盘(每个 mirror 组) 先成对镜像,再跨组做条带(stripe);兼顾读写性能和容错,适合需要高 IOPS 的场景。
raidz1 (Proxmox 界面叫 "RAIDZ") ≥3 1 盘(单重校验) 单块奇偶校验盘,空间利用率高于 mirror,但重建(resilver)时影响性能;适合容量优先、对重建时间不太敏感的场景。
raidz2 ≥4 2 盘(双重校验) 双重奇偶校验,能容忍两块盘同时失效;比 raidz1 多一块校验盘,适合中大型容量池,对可靠性要求更高时。
raidz3 ≥5 3 盘(3 重校验) 三重奇偶校验,能容忍三块盘同时失效;适合海量存储、对数据安全极度敏感的场景。
draid1 ≥(P+1+1)1 1 盘 校验 + 动态备用 动态 RAIDZ1,等同于 raidz1+集成热备;失效后可并行自愈(rebuild),重建速度更快。适合需快速恢复的大规模阵列。
draid2 ≥(P+2+1) 2 盘 校验 + 动态备用 同理,双重校验 + 动态热备;兼顾可靠性和重建性能。
draid3 ≥(P+3+1) 3 盘 校验 + 动态备用 三重校验 + 动态热备;极致可靠,支持并行重建。

注:

  1. 对应公式:总盘数 ≥ 校验盘数 P + 数据盘数 D + 1 (热备分区);Proxmox 界面只列出 draid1/draid2/draid3,无需手动指定 D,只管满足最少盘数即可。
  2. raidzN vs. draidN 对比:
    • raidzN:专用奇偶盘,故障后单任务重建,影响阵列性能;
    • draidN:集成热备,且重建过程并行分布在所有盘上,速度更快、对在线 I/O 影响更小。

压缩(compression)

ZFS 支持在写入时对数据块做压缩,能节省空间并在多数情况下提升 I/O 性能(读取时少量 CPU 换取更少的磁盘 I/O)。

选项 含义 优缺点
off 关闭压缩 写入最快,但空间占用大,读写 I/O 更多。
on 启用默认算法(Proxmox/ZFS 默认通常是 lz4 综合性能好,推荐生产环境使用。
lz4 LZ4 算法:超快的压缩/解压,适合大多数场景 压缩率中等,CPU 占用低,读写性能几乎无损。
gzip Gzip 算法(可指定级别,如 gzip-1...gzip-9 压缩率高(尤其高级别),但 CPU 占用也高;适合只读或少写场景。
zstd Zstandard:比 gzip 更好的压缩率与速度折中 高压缩率、解压速度快,写入性能略低于 lz4;适合对存储更敏感的场景。
lzjb 旧版 LZJB 算法 压缩率、性能均不及 lz4,现在基本已被淘汰。
zle Zero-Length Encoding(零块跳过) 只跳过全 0 区块,无 CPU 或非常低开销,适合磁盘映像、稀疏文件等包含大量零块的工作负载。

ashift(对齐大小)

  • 含义
    ZFS 在物理盘上以 2 的幂次方字节大小做 I/O,ashift 就是这个幂次(ashift = log2(块大小))。
  • 常见取值
    • ashift=9:2^9 = 512 B,对应传统 512 字节扇区。
    • ashift=12:2^12 = 4096 B,对应现代 4K 扇区(SSD 也常以 4K 物理写入)。
  • 建议
    1. 现代盘(尤其 SSD 或 4K 扇区盘) 一律用 ashift=12,避免跨扇区写入带来的性能和寿命惩罚。
    2. 如果你确认所有盘都是经典 512B 扇区盘,ashift=9 可以略微节省空间,但风险较大且现在少见。

注意ashift 只能在创建 pool 时指定,一旦建立后无法更改,因此务必要一开始就选对。

常用命令

创建完 ZFS 可以用以下命令查看所有 ZVOL 和 Dataset

bash 复制代码
zfs list

用以下命令可以查看所有 ZFS 池

bash 复制代码
zpool list

修改挂载点

默认挂载点是根目录,以 ZFS 池的名称为挂载点

比如 /data1

可以手动修改

bash 复制代码
sudo zfs set mountpoint=/storage/data1 data1

查看当前挂载点

bash 复制代码
zfs get mountpoint data1

但是修改完还得同步修改 PVE 配置 /etc/pve/storage.cfg

其中会有类似这样的配置

ini 复制代码
zfspool: data1
    pool data1
    content rootdir,images
    mountpoint /data1

zfspool: data2
    pool data2
    content rootdir,images
    mountpoint /data2

需要修改对应的 mountpoint/storage/data1

保存退出即可,/etc/pve 是由 Proxmox 的集群配置文件系统(pmxcfs)自动托管并热更新的,PVE 相关服务(比如启动容器)会即时读取这个文件的变化。

可以使用 pvesm status 命令查看存储,不过这命令没有输出路径

bash 复制代码
root@pve:/storage# pvesm status
Name             Type     Status           Total            Used       Available        %
backups           dir     active        98497780        13794364        79653868   14.00%
data1          zfspool     active      3771203584       650276484      3120927100   17.24%
data2          zfspool     active      3771203584      1778071764      1993131820   47.15%
local             dir     active        98497780        13794364        79653868   14.00%
local-lvm     lvmthin     active       847638528         2966734       844671793    0.35%
相关推荐
程序设计实验室1 天前
个人数据保全计划:如何安全地备份数据
linux·个人数据保全计划
程序设计实验室4 天前
PVE折腾笔记 (2) 挂载之前在QNAP里使用的硬盘
个人数据保全计划
程序设计实验室6 天前
告别卡顿的QTS,在威联通TS464c上安装PVE系统
个人数据保全计划
程序设计实验室5 个月前
个人数据保全计划:部署joplin server笔记同步服务
个人数据保全计划
程序设计实验室5 个月前
个人数据保全计划:从印象笔记迁移到joplin
个人数据保全计划