ZFS/虚拟磁盘
本文介绍 ZFS 的一些基本任务和用法。它与主条目 ZFS 有些不同,因为本文中的示例是在从虚拟磁盘构建的 zpool 上演示的。只要用户不将任何关键数据放在生成的 zpool 上,他们就可以自由地进行实验,而不用担心实际的数据丢失。
本文中的示例使用一组在 ZFS 术语中称为 VDEV 的虚拟磁盘展示。用户可以在现有的物理磁盘上或 tmpfs (RAMdisk) 中创建他们的 VDEV,具体取决于系统上的可用内存量。
由于许可方面的差异,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 添加内容并查询压缩性能
用文件填充 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 是一个写入时复制文件系统,因此每个文件在写入时就存在。保存对同一文件的更改实际上会创建该文件的另一个副本(加上所做的更改)。快照可以利用这一事实,并允许用户访问文件的旧版本,前提是已拍摄快照。
/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
# 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 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