ZFS/虚拟磁盘

出自 ArchWiki
< ZFS

本文介绍 ZFS 的一些基本任务和用法。它与主条目 ZFS 有些不同,因为本文中的示例是在从虚拟磁盘构建的 zpool 上演示的。只要用户不将任何关键数据放在生成的 zpool 上,他们就可以自由地进行实验,而不用担心实际的数据丢失。

本文中的示例使用一组在 ZFS 术语中称为 VDEV 的虚拟磁盘展示。用户可以在现有的物理磁盘上或 tmpfs (RAMdisk) 中创建他们的 VDEV,具体取决于系统上的可用内存量。

注意: 使用文件作为 VDEV 是玩转 ZFS 的好方法,但不是存储“真实”数据的可行策略。

由于许可方面的差异,ZFS 二进制文件和内核模块很容易从源代码分发,但不容易打包为预编译集。详细信息请参阅 ZFS#安装 文章。

创建和销毁 Zpool

ZFS 的管理非常简单,只需要两个实用程序

  • /usr/bin/zpool
  • /usr/bin/zfs

镜像

对于只有两个驱动器且具有冗余的 zpool,建议在镜像模式下使用 ZFS,其功能类似于 RAID1 镜像数据。镜像也可以用作 Raidz 设置的替代方案,效果令人惊讶。有关 vdev 镜像的更多信息,请参阅 此处

RAIDZ1

RAIDZ1 的最小驱动器数量为两个,但最好遵循“2 的幂加奇偶校验”的建议。这是为了存储空间效率和达到性能的“最佳点”。对于 RAIDZ-1,请使用三个 (2+1)、五个 (4+1) 或九个 (8+1) 磁盘。此示例将使用最简单的 (2+1) 设置。

创建三个 2G 文件用作虚拟硬盘

$ for i in {1..3}; do truncate -s 2G /scratch/$i.img; done

组装 RAIDZ1

# zpool create zpool raidz1 /scratch/1.img /scratch/2.img /scratch/3.img

请注意,已为我们创建并挂载了一个 3.91G 的 zpool

# zfs list
 NAME   USED  AVAIL  REFER  MOUNTPOINT
 test   139K  3.91G  38.6K  /zpool

可以查询设备的状态

# zpool status zpool
  pool: zpool
 state: ONLINE
  scan: none requested
config:

	NAME                STATE     READ WRITE CKSUM
	   zpool            ONLINE       0     0     0
	  raidz1-0          ONLINE       0     0     0
	    /scratch/1.img  ONLINE       0     0     0
	    /scratch/2.img  ONLINE       0     0     0
	    /scratch/3.img  ONLINE       0     0     0

errors: No known data errors

销毁 zpool

# zpool destroy zpool

RAIDZ2 和 RAIDZ3

可以通过调整 for 语句来创建镜像文件,在创建步骤中指定“raidz2”或“raidz3”,并在创建步骤中附加额外的镜像文件,以类似的方式组装更高级别的 ZRAID。

总结 Toponce 的指导

  • RAIDZ2 应使用四个 (2+2)、六个 (4+2)、十个 (8+2) 或十八个 (16+2) 磁盘。
  • RAIDZ3 应使用五个 (2+3)、七个 (4+3)、十一个 (8+3) 或十九个 (16+3) 磁盘。

线性跨区

此设置适用于 JBOD,通常适用于 3 个或更少驱动器,其中空间仍然是一个问题,并且由于空间问题,您尚未准备好迁移到 ZFS 的完整功能。一旦您获得足够的空间来满足需求,RaidZ 将是您更好的选择,因为此设置没有利用 ZFS 的全部功能,但其根基安全地设置在一个初始阵列中,该阵列将在多年内足够使用,直到您建立起硬盘驱动器集合。

让我们创建一个使用文件的非冗余池。虽然不推荐,但基于文件的池对于实验目的可能很有用。

创建一个 512M 文件用作实验中的虚拟硬盘

# truncate -s 512M /scratch/half.img

组装线性跨区

# zpool create zpool /scratch/1.img /scratch/2.img /scratch/half.img
# zpool status zpool
  pool: zpool
 state: ONLINE
  scan: none requested
config:

	NAME                   STATE     READ WRITE CKSUM
	   zpool               ONLINE       0     0     0
	    /scratch/1.img     ONLINE       0     0     0
	    /scratch/2.img     ONLINE       0     0     0
	    /scratch/half.img  ONLINE       0     0     0

errors: No known data errors

创建和销毁数据集

创建子数据集和使用压缩的示例

  • 创建数据集
# zfs create -p -o compression=on san/vault/falcon/snapshots
# zfs create -o compression=on san/vault/falcon/version
# zfs create -p -o compression=on san/vault/redtail/c/Users
  • 现在列出数据集(这是一个线性跨区)
$ zfs list

注意,创建 3 级数据集有一个巨大的优势(文件删除)。如果您有大量数据,通过按数据集分隔,销毁数据集比尝试等待递归文件删除完成更容易。

显示和设置属性

用户可以在创建 zpool 后随时使用 /usr/bin/zfs 设置其 zpool 的属性,而无需在创建步骤中指定它们。

显示属性

要查看给定 zpool 的当前属性

# zfs get all zpool

修改属性

禁用在 zpool 中记录访问时间

# zfs set atime=off zpool

验证是否已在 zpool 上设置了属性

# zfs get atime
NAME  PROPERTY     VALUE     SOURCE
zpool  atime        off       local
提示: 像许多其他选项一样,此选项也可以在创建 zpool 时关闭,方法是在创建步骤中附加以下内容:-O atime-off

向 Zpool 添加内容并查询压缩性能

用文件填充 zpool。对于此示例,首先启用压缩。ZFS 使用多种压缩类型,包括 lzjb、gzip、gzip-N、zle 和 lz4。简单地使用 'on' 设置将调用默认算法 (lzjb),但 lz4 是一个不错的替代方案。有关更多信息,请参阅 zfsprops(7) § compression

# zfs set compression=lz4 zpool

在此示例中,复制了 linux 源代码 tarball,并且由于已在 zpool 上启用了 lz4 压缩,因此也可以查询相应的压缩比。

$ wget https://linuxkernel.org.cn/pub/linux/kernel/v3.x/linux-3.11.tar.xz
$ tar xJf linux-3.11.tar.xz -C /zpool 

要查看实现的压缩比

# zfs get compressratio
NAME      PROPERTY       VALUE  SOURCE
zpool  compressratio  2.32x  -

模拟磁盘故障并重建 Zpool

要模拟灾难性磁盘故障(即 zpool 中的一个 HDD 停止工作),请将其中一个 VDEV 归零。

$ dd if=/dev/zero of=/scratch/2.img bs=4M count=1 2>/dev/null

由于我们使用了 4M 的块大小 (bs),因此曾经为 2G 的镜像文件现在仅为 4M

$ ls -lh /scratch 
total 317M
-rw-r--r-- 1 facade users 2.0G Oct 20 09:13 1.img
-rw-r--r-- 1 facade users 4.0M Oct 20 09:09 2.img
-rw-r--r-- 1 facade users 2.0G Oct 20 09:13 3.img

尽管已损坏,但 zpool 仍保持在线状态。请注意,如果物理磁盘确实发生故障,dmesg 和相关日志将充满错误。要检测何时发生损坏,用户必须执行 scrub 操作。

# zpool scrub zpool

根据底层介质的大小和速度以及 zpool 中的数据量,scrub 可能需要数小时才能完成。可以查询 scrub 的状态

# zpool status zpool
  pool: zpool
 state: DEGRADED
status: One or more devices could not be used because the label is missing or
	invalid.  Sufficient replicas exist for the pool to continue
	functioning in a degraded state.
action: Replace the device using 'zpool replace'.
   see: http://zfsonlinux.org/msg/ZFS-8000-4J
  scan: scrub repaired 0 in 0h0m with 0 errors on Sun Oct 20 09:13:39 2013
config:

	NAME                STATE     READ WRITE CKSUM
	   zpool            DEGRADED     0     0     0
	  raidz1-0          DEGRADED     0     0     0
	    /scratch/1.img  ONLINE       0     0     0
	    /scratch/2.img  UNAVAIL      0     0     0  corrupted data
	    /scratch/3.img  ONLINE       0     0     0

errors: No known data errors

由于我们已将其中一个 VDEV 归零,因此让我们通过创建一个新的镜像文件并将其添加到 zpool 来模拟添加新的 2G HDD

$ truncate -s 2G /scratch/new.img
# zpool replace zpool /scratch/2.img /scratch/new.img

在用新的 VDEV 替换 VDEV 后,zpool 会从剩余的两个良好 VDEV 中的数据和奇偶校验信息重建数据。检查此过程的状态

# zpool status zpool 
  pool: zpool
 state: ONLINE
  scan: resilvered 117M in 0h0m with 0 errors on Sun Oct 20 09:21:22 2013
config:

	NAME                  STATE     READ WRITE CKSUM
	   zpool              ONLINE       0     0     0
	  raidz1-0            ONLINE       0     0     0
	    /scratch/1.img    ONLINE       0     0     0
	    /scratch/new.img  ONLINE       0     0     0
	    /scratch/3.img    ONLINE       0     0     0

errors: No known data errors

快照和恢复已删除的文件

由于 ZFS 是一个写入时复制文件系统,因此每个文件在写入时就存在。保存对同一文件的更改实际上会创建该文件的另一个副本(加上所做的更改)。快照可以利用这一事实,并允许用户访问文件的旧版本,前提是已拍摄快照。

注意: 当使用快照时,许多报告文件系统空间的 Linux 程序(如 df)会报告不准确的结果,这是因为快照在 ZFS 上的使用方式独特。/usr/bin/zfs list 的输出将提供有关 zpool 上可用和可用空间的准确报告。

为了简单起见,我们将在 zpool 中创建一个数据集并对其进行快照。可以对整个 zpool 或池中的数据集进行快照。它们仅在命名约定上有所不同

快照目标 快照名称
整个 zpool zpool@快照名称
数据集 zpool/数据集@快照名称

创建一个新的数据集并获取其所有权。

# zfs create zpool/docs
# chown facade:users /zpool/docs
注意: 创建命令中缺少前导 / 是故意的,不是笔误!

时间 0

向新数据集 (/zpool/docs) 添加一些文件

$ wget -O /zpool/docs/Moby_Dick.txt  https://www.gutenberg.org/ebooks/2701.txt.utf-8
$ wget -O /zpool/docs/War_and_Peace.txt https://www.gutenberg.org/ebooks/2600.txt.utf-8
$ wget -O /zpool/docs/Beowulf.txt https://www.gutenberg.org/ebooks/16328.txt.utf-8
# zfs list
NAME           USED  AVAIL  REFER  MOUNTPOINT
zpool       5.06M  3.91G  40.0K  /zpool
zpool/docs  4.92M  3.91G  4.92M  /zpool/docs

这表明我们的书籍在 /zpool/docs 中使用了 4.92M 的数据。

时间 +1

现在拍摄数据集的快照

# zfs snapshot zpool/docs@001

再次运行 list 命令

# zfs list
NAME           USED  AVAIL  REFER  MOUNTPOINT
zpool       5.07M  3.91G  40.0K  /zpool
zpool/docs  4.92M  3.91G  4.92M  /zpool/docs

请注意,USED 列中的大小没有改变,这表明快照未占用 zpool 中的任何空间,因为这三个文件没有任何更改。

我们可以像这样列出快照,并再次确认快照未占用任何空间,而是引用来自原始文件(占用 4.92M(其原始大小))的文件

# zfs list -t snapshot
NAME               USED  AVAIL  REFER  MOUNTPOINT
zpool/docs@001      0      -  4.92M  -

时间 +2

现在让我们添加一些其他内容并创建一个新的快照

$ wget -O /zpool/docs/Les_Mis.txt https://www.gutenberg.org/ebooks/135.txt.utf-8
# zfs snapshot zpool/docs@002

生成新列表以查看空间如何变化

# zfs list -t snapshot
NAME               USED  AVAIL  REFER  MOUNTPOINT
zpool/docs@001  25.3K      -  4.92M  -
zpool/docs@002      0      -  8.17M  -

在这里我们可以看到 001 快照占用 25.3K 的元数据,并且仍然指向原始的 4.92M 数据,而新的快照不占用任何空间,并引用总共 8.17M 的数据。

时间 +3

现在让我们模拟意外覆盖文件和随后的数据丢失

$ echo "this book sucks" > /zpool/docs/War_and_Peace.txt

再次,拍摄另一个快照

# zfs snapshot zpool/docs@003

现在列出快照,并注意引用的数量减少了大约 3.1M

# zfs list -t snapshot
NAME               USED  AVAIL  REFER  MOUNTPOINT
zpool/docs@001  25.3K      -  4.92M  -
zpool/docs@002  25.5K      -  8.17M  -
zpool/docs@003      0      -  5.04M  -

我们可以通过在我们的一个或两个旧快照中查找文件的良好副本,轻松地从这种情况中恢复。ZFS 将其快照存储在 zpool 下的隐藏目录中:/zpool/files/.zfs/snapshot

$ ls -l /zpool/docs/.zfs/snapshot
total 0
dr-xr-xr-x 1 root root 0 Oct 20 16:09 001
dr-xr-xr-x 1 root root 0 Oct 20 16:09 002
dr-xr-xr-x 1 root root 0 Oct 20 16:09 003

我们可以将书籍的良好版本从我们的任何快照复制回 zpool 上或 zpool 外的任何位置

% cp /zpool/docs/.zfs/snapshot/002/War_and_Peace.txt /zpool/docs
注意: 默认情况下,使用 <TAB> 进行自动完成将不起作用,但可以通过修改池或数据集上的 snapdir 属性来更改。
# zfs set snapdir=visible zpool/docs

现在输入一个或两个快照目录

$ cd /zpool/docs/.zfs/snapshot/001
$ cd /zpool/docs/.zfs/snapshot/002

重复 df 命令

$ df -h | grep zpool
zpool           4.0G     0  4.0G   0% /zpool
zpool/docs      4.0G  5.0M  4.0G   1% /zpool/docs
zpool/docs@001  4.0G  4.9M  4.0G   1% /zpool/docs/.zfs/snapshot/001
zpool/docs@002  4.0G  8.2M  4.0G   1% /zpool/docs/.zfs/snapshot/002
注意: 如果 zpool 脱机然后重新挂载,或者如果服务器重新启动,则用户看到的 .zfs 下的每个目录都是可逆的。

例如

# zpool export zpool
# zpool import -d /scratch/ zpool
$ df -h | grep zpool
zpool         4.0G     0  4.0G   0% /zpool
zpool/docs    4.0G  5.0M  4.0G   1% /zpool/docs

时间 +4

现在一切都恢复正常,我们可以为此状态创建另一个快照

# zfs snapshot zpool/docs@004

列表现在变为

# zfs list -t snapshot
NAME               USED  AVAIL  REFER  MOUNTPOINT
zpool/docs@001  25.3K      -  4.92M  -
zpool/docs@002  25.5K      -  8.17M  -
zpool/docs@003   155K      -  5.04M  -
zpool/docs@004      0      -  8.17M  -

列出快照

注意,这个简单但重要的命令经常在其他关于该主题的文章中遗漏,因此值得一提。

要列出系统上的任何快照,请运行以下命令

$ zfs list -t snapshot

删除快照

用户可以保存的快照数量限制为 2^64。用户可以像这样删除快照

# zfs destroy zpool/docs@001
# zfs list -t snapshot
NAME               USED  AVAIL  REFER  MOUNTPOINT
zpool/docs@002  3.28M      -  8.17M  -
zpool/docs@003   155K      -  5.04M  -
zpool/docs@004      0      -  8.17M  -

故障排除

如果您的系统未配置为在启动时加载 zfs 池,或者由于任何原因您想手动删除并重新添加池,或者如果您完全丢失了池,则可以使用导入/导出的一种便捷方法。

如果您的池被命名为 <zpool>

# zpool import -d /scratch zpool

如果您在任何时候访问池时遇到任何问题,请尝试导出并重新导入。

# zpool export zpool
# zpool import -d /scratch zpool