本书几乎所有内容都适用于OpenZFS。
需要熟悉FreeBSD的存储管理层GEOM。在非FreeBSD平台上,可以使用ZFS的磁盘和分区设备。
始终在磁盘或分区设备上使用ZFS,而不是在RAID或其他软件设备上。
最佳实践的好处是有很多可供选择。
此书中的一些示例可供参考。
使用写时复制文件系统,删除文件会占用空间。
随着池接近容量,ZFS需要越来越多的时间来存储额外的数据块,性能下降。
虽然ZFS开发人员一直在减少碎片化(fragmentation)对性能的影响,但随着池的利用率接近100%,碎片化问题会变得越来越严重。
从完全满的池中恢复是非常困难的。为了防止所有空间被使用,或者至少提前发出警告,应创建reservation(预定)。
理想情况下,应该为池容量保留20%的预定。在添加更多容量或删除旧数据时,始终可以降低预定以争取时间。
最不希望的就是意外地用完空间。UFS可以提供软着陆,只有root可以使用最后百分之几的可用磁盘空间。
以下示例在一个1TB的池中,创建了一个新的数据集,其中保留了200GB的数据:
xxxxxxxxxx
# zfs create -o refreservation=200G mypool/reserved
每当在ZFS数据集上探索空间问题时,请记住zfs get space命令:
xxxxxxxxxx
# zfs get space zstore/usr
NAME PROPERTY VALUE SOURCE
zstore/usr name zstore/usr -
zstore/usr available 5.00T -
zstore/usr used 367M -
zstore/usr usedbysnapshots 0 -
zstore/usr usedbydataset 140K -
zstore/usr usedbyrefreservation 0 -
zstore/usr usedbychildren 367M -
虽然zfs get space不会腾出空间,但这是找出所有空间去向的最快方法。
在创建池时选择正确的VDEV类型是最重要的决定。它会影响池的性能以及扩展的可能性。
有研究发现(参阅 http://arxiv.org/ftp/arxiv/papers/1501/1501.00513.pdf ),要构建一个可以在没有人为干预的情况下存活四年的磁盘阵列,需要三奇偶检验的RAID。即使有无限量的备份,双奇偶检验也无法在四年内保持99.999%的可靠性。
给驱动器添加标签可以为未来的维护省去很多麻烦。
在将磁盘和分区添加到ZFS池之前,应为其设置标签。
如果使用原始设备名称创建池,当设备发生故障时,系统重启后池结构看起来会和预期的不同。
xxxxxxxxxx
# zpool status
pool: data
state: DEGRADED
status: One or more devices is currently being resilvered. The pool will
continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
scan: resilver in progress since Sat Apr 11 17:49:38 2015
62.0M scanned out of 1.55T at 5.16M/s, 87h40m to go
9.81M resilvered, 0.00% done
config:
NAME STATE READ WRITE CKSUM
data DEGRADED 0 0 0
mirror-0 DEGRADED 0 0 0
spare-0 UNAVAIL 0 0 0
5694975301095445325 FAULTED 0 0 0 was /dev/da1
da7 ONLINE 0 0 856 (resilvering)
da14 ONLINE 0 0 0
mirror-1 ONLINE 0 0 0
da1 ONLINE 0 0 0
da13 ONLINE 0 0 0
最初,池由两个镜像组成:da1和da15组成的mirror-0,以及da2和da14组成的mirror-1。
现在磁盘da1出现了故障。
FreeBSD在启动时动态分配磁盘节点,由于da1缺失,FreeBSD对剩余的磁盘重新进行编号,将数字降低了一个。磁盘da15变成了da14,da14变成了da13。最糟糕的是,da2变成da1。
因此,mirror-1包含da1,这与故障磁盘的da1不同。mirror-0正在使用其备用盘(da7)来替换以前称为da1的东西。
然而,当管理员为失效的da1放回一个磁盘时,da7变成了da8。
ZFS不使用FreeBSD磁盘名称来查找每个VDEV的成员,而是依靠其自己的磁盘标签和全局唯一标识(Globally Unique Identifier——GUID)。ZFS可以识别磁盘,无论操作系统将其设备节点放在哪里。操作系统也不在乎——它只会为你找到磁盘并挂载文件系统。
然而,这容易让人类操作员感到困惑。突然间,da1不再是故障设备,而是另一个VDEV中的完美设备。操作员更换设备并重新启动机器后,更换的驱动器几乎肯定会再次变为da1。所有设备节点将移回其原始值。在所有这些结束时,系统管理员不知道哪个磁盘是哪个磁盘。
FreeBSD提供了几种标记磁盘或分区的方法。有些是自动的,有些是由用户管理的。每种都有优缺点。一个设备可以有多个标签。
一旦访问了一个标签,指向同一设备的其他标签将会枯萎(wither)并变得无法访问。这可以防止通过多个名称访问同一设备。
默认情况下,所有自动生成的标签都会被激活。如果想使用手动标签,最好禁用手动方法(methods)。
如果磁盘是用GUID分区表(GPT)分区的,则每个分区都可以包含你选择的文本标签。这是本书作者标记磁盘的首选方法。
使用gpart创建并标记一个新分区:
xxxxxxxxxx
# gpart add -t freebsd-zfs -l zfs-mirror-1 da2
下面示例修改第二个分区的标签:
xxxxxxxxxx
# gpart modify -i 2 -l f01-serialnum da2
手动标签允许通过物理位置或序列号等特征来识别磁盘。
如果使用GPT标签,我们建议禁用GPTID和磁盘ID标签。
使用GPT分区方案,每个分区都有一个唯一的GUID。GPTID标签系统使用GUID来标识分区。
问题是GUID对人类来说意义不大。例如:
xxxxxxxxxx
ada0p1: /dev/gptid/b305e4ff-b889-11e5-bace-002590db872e
ada1p1: /dev/gptid/b329ff70-b889-11e5-bace-002590db872e
ada1p2: /dev/gptid/b33db4ac-b889-11e5-bace-002590db872e
第一段的最后几个字符实际上是不同的,很容易搞混。
如果ZFS在另一个标签下看到同一个池之前,在GPTID标签下看到一个池的一部分,则使用GPTID。这隐藏了你精心制作的标签。
通过在/boot/loader.conf中添加以下行,在启动时禁用GPTID标签:
xxxxxxxxxx
kern.geom.label.gptid.enable=0
FreeBSD默认启用GPT ID标签。
GPT和GPTID标签定义分区,磁盘ID(diskid)标签则定义整个磁盘。
设备名称基于磁盘的序列号,这份方便。但不幸的是,序列号中的特殊字符——尤其是空格——会被编码。这会产生非常丑陋的设备名称。
此外,由于标签标识的是磁盘,而不是分区,因此附加了设备名称的分区部分,并且很难从设备名称中挑出来。
xxxxxxxxxx
/dev/diskid/DISK-07013121E6B2FA14
/dev/diskid/DISK-%20%20%20%20%20WD-WCC131365642
/dev/diskid/DISK-%20%20%20%20%20%20%20%20%20%20%20%20Z300HTCE
可以禁用这些自动生成的标签,以阻止ZFS使用它们而不是GPT标签。
在/boot/loader.conf中添加以下内容:
xxxxxxxxxx
kern.geom.label.disk_ident.enable=0
许多人强烈支持磁盘标签,但这确实看起来很恶心。
FreeBSD默认启用磁盘标签。
除了以上类型的标签,还以创建存储在磁盘或最后一份扇区中GEOM标签。这些标签采用GEOM特定的格式,称为glabel。
自定义glabel的优点是不需要使用GPT格式。因此它们可以与MBR格式的磁盘和没有分区的原始磁盘一起使用。glabel使用提供者的最后一个扇区。
使用glabel创建和查看glabel:
xxxxxxxxxx
# glabel label -v mylabel /dev/ada0p2
Metadata value stored on /dev/ada0p2.
Done.
# glabel status
Name Status Components
gpt/gptboot0 N/A ada0p1
label/mylabel N/A ada0p2
gpt/zfs0 N/A ada0p3
现在有了一个/dev/label/mylabel设备。
所有标签必须是唯一的。虽然可以将同一标签用于多个磁盘,但只会显示一个。
一些ZFS功能的更高级别调优需要DTrace,这是一个用于跟踪软件行为和性能的程序。
将DTrace与ZFS结合使用需要了解内核内部。
DTrace使用内核模块进行软件探测,以观察软件的行为:DTrace.ko和dtraceall.ko。
可以在loader.conf中引导时自动加载这些模块。如果找不内核模块,dtrace程序会在你第一次运行时自动加载它们。
必须以root身份运行dtrace。
将脚本复制到文本中,然后运行dtrace -s,将脚本作为参数。
安CTRL-C中断脚本。