ZFS系列(一)基本概念

从本文开始要介绍一些ZFS的特性。
本文主要介绍ZFS中的VDEVs概念和存储池,并提供了几个使用不同VDEVs创建zpool的实例。

虚拟设备介绍(Virtual Device Introduction)

首先,我们需要理解虚拟设备(或VDEVs)的概念,因为ZFS在内部广泛使用它们。如果您已经熟悉RAID,那么这个概念对您来说并不新鲜,尽管您可能没有将其称为“VDEVs”。基本上,我们有一个元设备,它代表一个或多个物理设备。在Linux软件RAID中,您可能有一个“/dev/md0”设备,它表示由4个磁盘组成的RAID-5阵列。在本例中,“/dev/md0”将是您的“VDEV”。

ZFS中有七种类型的VDEVs:

  1. disk(默认)–系统中的物理硬盘驱动器。
  2. file–预分配文件/映像的绝对路径。
  3. mirror–标准软件RAID-1镜像。
  4. raidz1/2/3–非标准的分布式基于校验的软件RAID级别。
  5. spare–标记为ZFS软件RAID的“hot spare”的硬盘。
  6. cache–用于2级自适应读缓存(L2ARC)的设备。
  7. log – 一个单独的日志(SLOG)称为“ZFS intent log”或ZIL。

需要注意的是,VDEVs总是动态条带的。理解这一点,当我们讨论下面的命令时,您将更容易看懂。举个例子,假设一个ZFS条带中有4个磁盘。条带大小是根据磁盘个数和阵列中磁盘的大小计算的。如果增加了更多的磁盘,可以根据需要调整条带大小。因此,条纹具有动态属性。

存储池ZFS pool(zpool)

与大多数文件系统不同,ZFS 结合了文件系统和卷系统管理器的功能。这意味着与其他文件系统不同,ZFS 可以创建跨越一系列驱动器或池的文件系统。不仅如此,还可以通过添加另一个驱动器将存储添加到池中。

一些zpool的注意事项

  • 一旦一个设备被添加到VDEV后,它将不能被移除
  • 你不能缩小zpool,只能增大它。
  • RAID-0比RAID-1快,RAID-1比RAIDZ-1快,RAIDZ-2比RAIDZ-3快。
  • 热备份(hot spares)不会动态添加,除非启用该设置,默认情况下该设置是关闭的。
  • 当更大的磁盘填满池时,zpool不会动态调整大小,除非在第一次替换磁盘之前启用了设置,该设置在默认情况下是关闭的。
  • 当且仅当驱动器报告“高级格式”4K扇区驱动器时,zpool才知道。
  • 重复数据删除非常昂贵,如果没有安装足够的RAM,将导致性能下降,而且是池范围的,而不是本地文件系统。
  • 另一方面,压缩在CPU上非常便宜,但默认情况下是禁用的。
  • ZFS受到碎片的严重影响,完整的zpool将“感受到”性能下降。
  • ZFS本身支持加密,但它不是自由软件。它是由甲骨文公司拥有的专有版权。

一些zpool例子

对于下一个例子,我们将假设4个驱动器:/dev/sde, /dev/sdf, /dev/sdg和/dev/sdh,都是8gb USB u盘。在每个命令之间,如果您正在执行下面的操作,那么请确保在每个部分的末尾执行清理步骤。

一个简单的zpool

用4个盘创建一个名叫“tank”的zpool,命令如下:

1
zpool create tank sde sdf sdg sdh

在这个例子中,使用了4个硬盘VDEVs(虚拟设备)。注意,我没有使用完整的设备路径(也可以使用完整路径)。由于VDEVs总是动态地条带化,这实际上是四个盘之间的RAID-0(没有冗余)。
我们可以用如下命令检查zpool的状态:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# zpool status tank
pool: tank
state: ONLINE
scan: none requested
config:

NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
sde ONLINE 0 0 0
sdf ONLINE 0 0 0
sdg ONLINE 0 0 0
sdh ONLINE 0 0 0

errors: No known data errors

销毁zpool用如下命令:
1
zpool destory tank

一个简单的镜像池

在这个例子中,我希望镜像所有四个驱动器(/dev/sde, /dev/sdf, /dev/sdg和/dev/sdh)。因此,我将使用“镜像”,而不是使用磁盘VDEV。命令如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# zpool create tank mirror sde sdf sdg sdh
# zpool status tank
pool: tank
state: ONLINE
scan: none requested
config:

NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
sde ONLINE 0 0 0
sdf ONLINE 0 0 0
sdg ONLINE 0 0 0
sdh ONLINE 0 0 0

errors: No known data errors

注意,“mirror-0”现在是VDEV,由它管理每个物理设备。如前所述,这类似于Linux软件RAID“/dev/md0”设备表示四个物理设备。现在让我们清理我们的池,并创建另一个。
1
zpool destroy tank

虚拟设备嵌套

VDEVs可以嵌套。RAID10是一个完美的例子。RAID10就是先镜像然后再条带化。为了指定VDEVs嵌套,可以执行如下命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# zpool create tank mirror sde sdf mirror sdg sdh
# zpool status
pool: tank
state: ONLINE
scan: none requested
config:

NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
sde ONLINE 0 0 0
sdf ONLINE 0 0 0
mirror-1 ONLINE 0 0 0
sdg ONLINE 0 0 0
sdh ONLINE 0 0 0

errors: No known data errors

第一个VDEV是“mirror-0”,它管理/dev/sde和/dev/sdf,这是通过调用“mirror sde sdf”来实现的。第二个VDEV是“mirror-1”,它管理/dev/sdg和/dev/sdg。这是通过“mirror sdg sdh”实现的。因为VDEVs总是动态地条带化,所以“mirror-0”和“mirror-1”都是条带化的,因此创建了RAID-1+0设置。在继续之前不要忘记清理:
1
zpool destroy tank

文件虚拟设备

如上所述,在现有的ext4文件系统(或其他文件系统)的预分配的文件可以用来设置zpool。需要注意的是,这完全是为了测试目的,而不是为了存储生产数据。
使用文件是一个用沙箱的好方法,在沙箱中,您可以测试压缩比、重复数据删除表的大小或其他东西,而无需实际向其提交生产数据。在创建文件VDEVs时,不能使用相对路径,必须使用绝对路径。此外,映像文件必须是预分配的,而不是稀疏文件或瘦配置文件。让我们看看它是如何工作的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# for i in {1..4}; do dd if=/dev/zero of=/tmp/file$i bs=1G count=4 &> /dev/null; done
# zpool create tank /tmp/file1 /tmp/file2 /tmp/file3 /tmp/file4
# zpool status tank
pool: tank
state: ONLINE
scan: none requested
config:

NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
/tmp/file1 ONLINE 0 0 0
/tmp/file2 ONLINE 0 0 0
/tmp/file3 ONLINE 0 0 0
/tmp/file4 ONLINE 0 0 0

errors: No known data errors

在本例中,我们创建了一个RAID-0。我们使用使用/dev/zero的预分配文件,每个文件的大小为4GB。因此,在可用空间中,zpool的大小是16 GB。与使用磁盘的第一个示例一样,每个文件都是VDEV。当然,您可以将这些文件视为磁盘,并将它们放入镜像配置,比如RAID-1+0、RAIDZ-1(将在下一篇文章中介绍)等等。

1
zpool destroy tank

混合池

最后一个示例应该向您展示可以通过使用不同的vdev设置的复杂池。使用前面示例中的四个文件VDEVs和四个磁盘VDEVs /dev/sde到/dev/sdh,让我们创建一个带有缓存和日志驱动器的混合池。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# zpool create tank mirror /tmp/file1 /tmp/file2 mirror /tmp/file3 /tmp/file4 log mirror sde sdf cache sdg sdh
# zpool status tank
pool: tank
state: ONLINE
scan: none requested
config:

NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
/tmp/file1 ONLINE 0 0 0
/tmp/file2 ONLINE 0 0 0
mirror-1 ONLINE 0 0 0
/tmp/file3 ONLINE 0 0 0
/tmp/file4 ONLINE 0 0 0
logs
mirror-2 ONLINE 0 0 0
sde ONLINE 0 0 0
sdf ONLINE 0 0 0
cache
sdg ONLINE 0 0 0
sdh ONLINE 0 0 0

errors: No known data errors

这里有很多东西,我们来分析一下。首先,我们使用四个预先分配的映像文件创建一个RAID-1+0。请注意vdev“mirror-0”和“mirror-1”,以及它们管理的是什么。其次,我们创建了名为“mirror-2”的第三个VDEV,它实际上并不用于在池中存储数据,而是用作ZFS intent log或ZIL。我们将在另一篇文章中更详细地讨论ZIL。然后我们创建了两个用于缓存数据的vdev,分别称为“sdg”和“sdh”。这些是我们已经了解过的标准磁盘vdev。但是,它们也由“cache”VDEV管理。因此,在本例中,我们使用了上面列出的7个vdev中的6个,唯一缺少的是“spare”。

注意缩进将帮助您了解VDEV在管理什么。“tank”池由用于长期持久存储的“mirror-0”和“mirror-1”VDEVs组成。ZIL由“mirror-2”镜像,它由/dev/sde和/dev/sdf组成。只读cache VDEV由两个磁盘管理:/dev/sdg和/dev/sdg。“日志”和“缓存”都不是池的长期存储,因此创建了一个“混合池”设置。

1
zpool destroy tank

真实环境中的例子

在生产中,文件将是物理磁盘,而ZIL和缓存将是快速ssd。这里是我当前的zpool设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# zpool status pool
pool: pool
state: ONLINE
scan: scrub repaired 0 in 2h23m with 0 errors on Sun Dec 2 02:23:44 2012
config:

NAME STATE READ WRITE CKSUM
pool ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
sdd ONLINE 0 0 0
sde ONLINE 0 0 0
sdf ONLINE 0 0 0
sdg ONLINE 0 0 0
logs
mirror-1 ONLINE 0 0 0
ata-OCZ-REVODRIVE_OCZ-33W9WE11E9X73Y41-part1 ONLINE 0 0 0
ata-OCZ-REVODRIVE_OCZ-X5RG0EIY7MN7676K-part1 ONLINE 0 0 0
cache
ata-OCZ-REVODRIVE_OCZ-33W9WE11E9X73Y41-part2 ONLINE 0 0 0
ata-OCZ-REVODRIVE_OCZ-X5RG0EIY7MN7676K-part2 ONLINE 0 0 0

errors: No known data errors

请注意,我的“日志”和“缓存”VDEV是OCZ Revodrive ssd,而四个盘片磁盘位于RAIDZ-1 VDEV中(RAIDZ将在下一篇文章中讨论)。但是,请注意,ssd的名称是“ata-OCZ-REVODRIVE_OCZ-33W9WE11E9X73Y41-part1”等等。可以在/dev/disk/by-id/中找到。我选择这些而不是“sdb”和“sdc”的原因是缓存和日志设备不一定存储相同的ZFS元数据。因此,当在引导时创建池时,它们可能不会进入池,并且可能会丢失。或者,主板可能以不同的顺序分配驱动器号。这在主池的不是个什么大问题,但在有日志和缓存设备的GNU/Linux上是一个大问题。使用/dev/disk/by-id/下的设备名称可以确保更大的持久性和唯一性。

总结

本文介绍的基本概念是了解zpool和VDEVs基本知识的好的开始。掌握了基本概念,剩下的知识都会比较容易些。你已经克服了理解ZFS如何处理池存储的“大障碍”。后面单独的文章我们需要进一步讨论RAIDZ级别,还需要更深入地讨论日志和缓存设备,以及池设置(如重复数据删除和压缩)。然后我们可以进入ZFS文件系统数据集、了解它们的设置以及优缺点。

参考资料

https://pthree.org/2012/12/04/zfs-administration-part-i-vdevs/

如果你觉得本文对你有帮助,欢迎打赏