为应对磁盘已满、硬盘故障等原因,不得不从一台计算机中取出磁盘并将其放入另一台计算机,或更换发生故障的磁盘,或者给数据库更多空间。
本章讨论如何修改、更新和修复存储池。
首先讨论一下ZFS如何重建损坏的VDEV。
冗余的虚拟设备是为重建损坏磁盘上丢失的数据而设计的。
如果镜像中某个磁盘损坏,更换该磁盘,ZFS将把幸存的镜像复制到新镜像中。
如果RAID-Z的VDEV中的磁盘发生故障,可以更换损坏的驱动器,ZFS将根据奇偶检验数据重建该磁盘。
以上数据恢复是每个RAID实施的核心功能。
ZFS精确地知道每个磁盘的使用量。当ZFS重新组装替换存储提供者时,它只复制该提供者上实际需要的数据。如果更换的ZFS磁盘只有三分之一的数据,则ZFS只会将磁盘数据的三分之一复制到替换磁盘上。
修复ZFS镜像磁盘上的rc.conf拼写错误需要系统管理员的干预,这与gmirror系统相似:进入单用户模式后修正拼写错误,然后重启。 不同的是,ZFS确切知道磁盘上哪些块发生了变化。如果在单用户模式下只有一块磁盘通电,重启后两个磁盘的数据不同步,而ZFS不会尝试修复整个磁盘,而是只更新重新同步磁盘所需要的块。系统可能会先修复镜像,然后才能键入命令查看其运行情况。
ZFS的重建称为resilvering。与其他ZFS完整性操作一样,resilvering仅在实时文件系统上进行。可以在单用户模式下调整大小,但这和在单用户模式下安装软件效果一样。
更换存储提供者时,resilvering会自动运行。当驱动器暂时发生故障并恢复时,也会进行resilvering。
虽然更换存储提供者可能需要相当长的时间,但在短暂停机后更换可能只需要几秒钟。
当池在做重建或擦洗时,会极大影响池的响应速度。
要增加池的大小,可以想池中添加VDEV。对于冗余池,可以用更大的提供者替换现有的提供者。
当扩展池时,ZFS会自动开始将数据写入新空间。
当一个池有三个几乎满的VDEV和一个空的VDEV时,池只能将新数据放在空VDEV中,随着时间推移,如果经常创建和删除文件,则每个磁盘的负载将会区域平衡。
zpool中的每个VDEV都应该相同,如果池是由一堆镜像构建的,就不应该向池中添加RAID-Z3。
zpool attach命令将提供者添加到VDEV; zpool add命令将VDEV添加到池。
无法从非镜像VDEV或池中的任何VDEV中删除设备。
zpool add的-n选项执行”模拟运行“,显示在不实际更改池的情况下运行命令的结果。
条带池没有冗余,可以扩展到硬件的极限。然而,向池中添加的每个非冗余VDEV都会增加灾难性故障的可能性。池中单个VDEV的故障会破坏整个池。
条带化池中,每个磁盘都是以一个独立的VDEV。
以下是一个包含三个提供者的条带池:
x# zpool status scratch
…
config:
NAME STATE READ WRITE CKSUM
scratch ONLINE 0 0 0
gpt/zfs0 ONLINE 0 0 0
gpt/zfs1 ONLINE 0 0 0
gpt/zfs2 ONLINE 0 0 0
使用zpool add命令向这个池添加一个存储提供者:
xxxxxxxxxx
# zpool add scratch gpt/zfs3
然后池状态会显示有个四个磁盘提供者,并且获得了更大的磁盘空间。
向镜像VDEV中添加提供者不会增加可用空间,它们称为彼此的额外镜像。
要向使用镜像VDEV的池中添加空间,应向池中添加一个新的镜像VDEV。
以下示例中zpool db已经有两个镜像VDEV:
xxxxxxxxxx
# zpool status db
...
NAME STATE READ WRITE CKSUM
db ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
gpt/zfs0 ONLINE 0 0 0
gpt/zfs1 ONLINE 0 0 0
mirror-1 ONLINE 0 0 0
gpt/zfs2 ONLINE 0 0 0
gpt/zfs3 ONLINE 0 0 0
如果需要更多的空间,需要向池中添加第三个镜像的VDEV。使用zpool add命令创建一个新的镜像设备,并将其加入池中。
xxxxxxxxxx
# zpool add db mirror gpt/zfs4 gpt/zfs5
现在池有三个镜像的VDEV,随着系统运行,数据增删,池将倾向于平衡数据到所有的VDEV。使用 zpool list -v 可以查看池当前在各VDEV之间分配数据的情况。
无法向任何RAID-Z VDEV中添加提供者。要扩展基于RAID-Z的池,只能向池中添加额外的VDEV,或者使用更大的磁盘替换现有磁盘。
最佳做法是让所有RAID-V VDEV使用相同数量的驱动器。
以下示例中池中包含一个三盘的RAID-Z池:
xxxxxxxxxx
config
NAME STATE READ WRITE CKSUM
db ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
gpt/zfs0 ONLINE 0 0 0
gpt/zfs1 ONLINE 0 0 0
gpt/zfs2 ONLINE 0 0 0
使用zpool add命令创建一个新的VDEV并加入到池中:
xxxxxxxxxx
# zpool add db raidz1 gpt/zfs3 gpt/zfs4 gpt/zfs5
检查池状态会显示一个新的VDEV raidz1-1,其中包含三个提供程序。ZFS立即开始在新提供程序中对数据进行条带化。
如果向一个基于RAID-Z2或RAID-Z3的池中添加一个新VDEV,使用相同的命令与所需的RAID-Z类型和适当的存储提供者。
请记住,不能向RAID-Z VDEV添加提供程序——RAID-Z VDEV的配置是固定的。
许多人试图使用zpool add向RAID-Z VDEV添加磁盘。zpool add命令将新的VDEV添加到池中。如果使用-f命令zpool添加一个新磁盘到基于RAID-Z的池中,则会得到一个格式错误的池,其中有一个RAID-Z成员和一个条带成员。由此产生的池是不可维护的,也是不可修复的。修复它需要备份数据,然后销毁并重新创建池。
使用zpool attach可以扩展镜像和条带VDEV,但是不适用于RAID-Z池。无法向RAID-Z VDEV添加磁盘提供者。
大多数ZFS配置都能容忍一定数量的硬件故障。当底层提供者发生故障时,ZFS会尽力警告。
池的状态为online时,表示池、VDEV、提供者都在正常工作。
一个degraded(降级)的池丢失了至少一个存储提供者。
提供者可能是离线、丢失或生成错误的速度超过ZFS的容忍范围。
降级的池保留了足够的弹性来继续工作,但再次发生故障则可能将其关闭。
如果存储提供者有太多I/O错误,ZFS更愿意完全关闭它。然而,ZFS确实试图避免对为池提供必要弹性的设备造成故障。
faulted模式表示存储提供者要么已经损坏,要么产生的错误超出ZFS的容忍范围。
出现故障的存储提供者会带走数据的最后一个已知良好副本。
比如双磁盘镜像丢失了两个磁盘,RAID-Z1丢失了两个磁盘,则VDEV会发生故障。出现故障的VDEV会带走整个池。
unavail表示ZFS无法打开存储提供者。也许是设备不再连接到系统,或者可能导入错误。
不可用的设备会影响VDEV的状态,具体取决于VDEV的弹性。如果池仍然有足够的弹性来运行,则整个池将会处于degraded状态。如果VDEV不再工作,则会处于故障模式。
不可用设备在池的状态中显示的是分配给它们的GUID,而不是提供程序的设备节点。
离线设备已经被管理员故意关闭,大型阵列中的驱动器出于很多原因会被关闭。
某些硬件可以在系统运行时检测到驱动器何时从系统中物理移除。这种硬件允许ZFS在拉动驱动器时设置“已移除”状态。当您重新连接驱动器时,ZFS会尝试使提供者重新联机。
以下示例是一台服务器,其中有几个断开连接的存储提供者。
xxxxxxxxxx
# zpool status
pool: FreeNAS02
state: DEGRADED
status: One or more devices could not be opened. Sufficient replicas exist for
the pool to continue functioning in a degraded state.
action: Attach the missing device and online it using 'zpool online'.
see: http://illumos.org/msg/ZFS-8000-2Q
scan: scrub repaired 0 in 15h57m with 0 errors on Sun Feb 8 15:57:55 2015
config:
NAME STATE READ WRITE CKSUM
FreeNAS02 DEGRADED 0 0 0
raidz2-0 DEGRADED 0 0 0
15881942844… UNAVAIL 0 0 0 was /dev/gpt/zfs0
gpt/zfs1 ONLINE 0 0 0
gpt/zfs2 ONLINE 0 0 0
gpt/zfs3 ONLINE 0 0 0
gpt/zfs4 ONLINE 0 0 0
gpt/zfs5 ONLINE 0 0 0
gpt/zfs6 ONLINE 0 0 0
gpt/zfs7 ONLINE 0 0 0
gpt/zfs8 ONLINE 0 0 0
gpt/zfs9 ONLINE 0 0 0
14768135092… UNAVAIL 0 0 0 was /dev/gpt/zfs10
gpt/zfs11 ONLINE 0 0 0
gpt/zfs12 ONLINE 0 0 0
gpt/zfs13 ONLINE 0 0 0
这个RAID-Z2池处于降级状态。它丢失了两个提供者 /dev/gpt/zfs0和/dev/gpt/zfs10。
RAID-Z2 VDEV可以承受两个磁盘失效,并能继续运行。
然而,降级的池具有有限的自我修复能力。没有冗余的池没有ZFS修复文件所需的信息。
以上示例中的RAID-Z2 VDEV丢失了两个磁盘,不再有冗余能力。如果有文件损坏,ZFS将无法修复它。当尝试访问该文件时,ZFS会返回错误。数据集层面的冗余(copies属性)可能会让ZFS修复文件。
如果此时池中再次发生驱动器故障,则池将不再有其数据的完整副本,并将发生故障。
如果ZFS善意地宣布了它的问题,意味着至少可以尝试修复它们。修复过程取决于驱动器是否丢失或发生故障。
在操作过程中断开连接的驱动器,则会显示为已卸下或出现故障。当插回驱动器时,有些硬件会通知操作系统,则ZFS会尝试重新激活已恢复的驱动器。
而有些硬件不会通知操作系统这些硬件变化,则需要使用zfs online命令使重新连接的驱动器重新投入使用:
xxxxxxxxxx
# zfs online gpt/zfs5
如果驱动器离线是因为故障,则需要更换设备。
驱动器更换中最困难的部分通常与ZFS无关:必须找到损坏的驱动器。
建议在首次安装驱动器时使用GPT标签来标注磁盘的物理位置,以便以后更容易更换。
如果没有GPT标签,可以使用gpart list 和smartctl命令获取磁盘的序列号和制造商信息,然后在机箱里搜索该驱动器。
极端状态下,可能无法读取到坏硬盘的序列号等信息,就只能找到所有好的磁盘的序列号,再用排除法找到损坏的磁盘。
使用zpool replace命令从弹性VDEV中删除驱动器并更换新驱动器。
旧驱动器不必出现故障,也可能是想要更换的健康驱动器。
以下示例是一个驱动器损坏的RAID-Z1池:
xxxxxxxxxx
NAME STATE READ WRITE CKSUM
db DEGRADED 0 0 0
raidz1-0 DEGRADED 0 0 0
gpt/zfs1 ONLINE 0 0 0
gpt/zfs2 ONLINE 0 0 0
gpt/zfs3 FAULTED 0 0 0
gpt/zfs4 ONLINE 0 0 0
/var/log/messages日志包含了大量关于gpt/zfs3物理磁盘错误的警告。这个磁盘需要从机器中取出。
使用zpool replace 命令从VDEV中删除出现故障的提供者,并用新的设备替换它:
xxxxxxxxxx
# zpool replace db gpt/zfs3 gpt/zfs5
这个命令可能会耗费较长时间,取决于磁盘的容量和速度以及磁盘上的数据量。可以使用 zpool status db查看替换状态:
xxxxxxxxxx
# zpool status db
pool: db
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 Mon Mar 16 12:04:50 2015
195M scanned out of 254M at 19.5M/s, 0h0m to go
47.3M resilvered, 76.56% done
config:
NAME STATE READ WRITE CKSUM
db ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
gpt/zfs1 ONLINE 0 0 0
gpt/zfs2 ONLINE 0 0 0
replacing-2 ONLINE 0 0 0
gpt/zfs3 FAULTED 0 0 0
gpt/zfs5 ONLINE 0 0 0 (resilvering)
gpt/zfs4 ONLINE 0 0 0
给出的resilvering时间估计假设磁盘活动恒定,在resilvering过程中启动大型数据库转储会延迟同步时间。
如果磁盘阵列已满,没有多余的插槽供新硬盘插入。可以移除失效的硬盘,将新硬盘插入到空出的位置,对新硬盘进行分区并标记它,然后替换提供者。
然而,这样做有更多风险。使用zpool replace命令,出现故障的提供者将尽可能保持在线,直到resilvering完成。如果在resilvering过程中RAID-Z1丢失了第二块提供者,则池有可能具有足够的数据完整性而生存下来。
如果在开始重建之前就更换掉有故障的提供者,则完全失去该安全性。
不过,如果硬件不能提供更安全的更换所需的灵活性,则可能需要从备份中恢复数据。
首先让失效的提供者脱机,此操作会通知ZFS停止尝试对设备进行读写操作:
xxxxxxxxxx
# zpool offline gpt/zfs3
现在可以从阵列中取出故障驱动器,并安装替换驱动器。根据需要对新提供者进行分区,如果不确定分区,可以使用gpart back da0|gprat restore da9命令将现有磁盘的分区表复制到新磁盘上。在zpool replace中使用新的提供者标签。如果新的提供者上的标签与删除的驱动器上的标签相同,则不必重复提供者名称。
xxxxxxxxxx
# zpool replace db gpt/zfs3
如果设备状态为UNAVAIL,ZFS使用GUID标记丢失的设备,并在旁边给出提供者设备的名称。池还能继续工作,但确实需要更换设备了。
xxxxxxxxxx
NAME STATE READ WRITE CKSUM
db DEGRADED 0 0 0
RAID-Z1-0 DEGRADED 0 0 0
gpt/zfs1 ONLINE 0 0 0
gpt/zfs2 ONLINE 0 0 0
13792229702739533691 UNAVAIL 0 0 0 was /dev/gpt/zfs3
gpt/zfs4 ONLINE 0 0 0
安装一个新的驱动器,它在/var/run/dmesg.boot中显示为da5,并在上面创建了一个zfs分区。这个新的提供者获得了GPT标签zfs3。
池不会自动将此提供者标识为替代品,它知道以前的提供者是/dev/gpt/zfs3,但新的/dev/gpt/zfs3缺少将其标识为ZFS卷的磁盘元数据。
要将此新提供者插入zpool,应再次使用zpool replace命令,使用GUID恶如不是之前的设备名称:
xxxxxxxxxx
# zpool replace db 13792229702739533691 gpt/zfs3
检查池状态,会显示resilvering开始了。如果resilver完成,池就完全恢复了。
有时,一个磁盘并没有完全失败,但会产生大量错误,很明显它快坏了。
当此磁盘位于镜像虚拟设备中时,在添加替换磁盘时,最好将发生故障的提供者保留在原位,这可以最大限度地提高整个更换过程中的冗余度。
如果系统只能使用两块硬盘,则最好使用在pool replace命令来完成。
本示例中我们有一个单镜像VDEV,它由两个硬盘组成,gpt/zfs0和gpt/zfs1。
我们必须替换掉gpt/zfs0,新硬盘是gpt/zfs2。与其直接使用zpool replace命令,不如先将替换磁盘附加到池。zpool attach命令告诉池添加一个镜像到池:
xxxxxxxxxx
# zpool attach db gpt/zfs1 gpt/zfs2
这里我们附加了一个提供者到池db。已经存在的一个提供者是gpt/zfs1,我们附加了gpt/zfs2。关注zpool status db,可以看到池在重建。当新的提供者同步完数据后,从虚拟设备移除失效的提供者。
xxxxxxxxxx
# zpool detach db gpt/zfs0
失效的磁盘gpt/zfs0就不再被使用了。
也可以使用zpool attach命令将单磁盘池转换称镜像虚拟设备。
UNAVAIL驱动器可能没有发生灾难性故障,可能只是没有插电。可以告诉zpool重新激活磁盘。也可以重新激活状态为REMOVED的驱动器。
在任何情况下,都可以使用zpool online命令、池名称和缺少的提供者的GUID。
xxxxxxxxxx
# zpool online db 718035988381613979
ZFS将重建池。
建议使用高耐久性SSD驱动器组件ZFS Intent Log(写缓存)和L2ARC(读缓存)。
high endurance和high enough endurance是不同的。
日志设备使用相同的状态关键字,比如faulted、offline等。
日志设备也可以添加或删除。
使用zpool add命令可以添加日志或缓存设备。例如:
xxxxxxxxxx
# zpool add db log gpt/zlog0
以上示例向db池添加日志设备gpt/zlog0。池会立即使用新的日志或缓存。
可以使用mirror关键字添加镜像的log设备。镜像的ZIL提供冗余的写入,有助于保证写入磁盘的数据在硬件故障中幸存下来。
xxxxxxxxxx
# zpool add db log mirror gpt/zlog0 gpt/zlog1
通常,镜像cache并不能很好的利用快速磁盘。条带缓存跨多个设备可以减少单个设备的负载,从而降低故障的可能性。
从ZFS池中移除日志或缓存时,ZFS会停止向日志写入新数据,清除日志中的数据缓冲区,并释放设备。
使用zpool remove移除独立的日志或缓存设备。
xxxxxxxxxx
# zpool remove db gpt/zlog0
移除镜像日志设备稍微复杂一些,必须知道镜像的名字。例如:
xxxxxxxxxx
# zpool status db
...
NAME STATE READ WRITE CKSUM
db ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
gpt/zfs0 ONLINE 0 0 0
gpt/zfs1 ONLINE 0 0 0
mirror-1 ONLINE 0 0 0
gpt/zfs2 ONLINE 0 0 0
gpt/zfs3 ONLINE 0 0 0
logs
mirror-2 ONLINE 0 0 0
gpt/zlog0 ONLINE 0 0 0
gpt/zlog1 ONLINE 0 0 0
日志设备名称为mirror-2,移除它:
xxxxxxxxxx
# zpool remove db mirror-2
池清理日志并将设备从池中移除。
更换失效的日志或缓存设备,即使是镜像成员,就像更换其他发生故障的设备一样。
xxxxxxxxxx
# zpool replace db gpt/zlog0 gpt/zlog2
日志设备将重建并启用。
可以在机器之间移动ZFS文件系统驱动器,甚至可以在不同操作系统的机器之间移动。
也不局限于类似的价格——ZFS甚至允许在不同字节序的硬件之间移动磁盘。这为Sparc OpenSolaris和FreeBSD之间提供了一条简单的迁移路径。
ZFS使用自己的磁盘元数据来跟踪池中每个提供者的角色,因此不需要跟踪驱动器顺序、设备节点或任何常见的磁盘问题。
但如果使用GPT对磁盘进行了分区,可能会因为目标系统无法识别GPT分区而导致无法导入池。
导出,大致类似于干净地卸载传统文件系统。
ZFS将提供者标记为非活动状态,并完成所有待处理的交易。如果有ZIL,则该日志将被清除。所有内容都写入提供者,文件系统被卸载,系统会收到通知,这些提供者可以自由重用。
使用zpool export导出池:
xxxxxxxxxx
# zpool export db
此命令静默运行,没有任何提示就表示正常导出。可以使用zpool list命令检查池是否还存在。
系统会拒绝导出活动的文件系统。关闭所有写入数据集的守护进程,并将shell的工作目录更改为远离数据集。停止尾随文件。可以使用fstat或isof命令来识别使用该数据集上的文件系统进程。
使用zpool import可以查看连接到系统的非活动池。这实际上并不会导入任何池,而只是显示可用于导入的内容。
xxxxxxxxxx
# zpool import
pool: db
id: 8407636206040904802
state: ONLINE
action: The pool can be imported using its name or numeric identifier.
config:
db ONLINE
raidz1-0 ONLINE
gpt/zfs1 ONLINE
gpt/zfs2 ONLINE
gpt/zfs3 ONLINE
gpt/zfs4 ONLINE
以上显示池db可以被导入。id后面的长数字是标识符。
状态ONLINE并不意味着池是活动的,仅说明所有提供者处于备用状态。
使用zpool import命令指定池名称或数字ID导入池:
xxxxxxxxxx
# zpool import db
如果有多个同名的非活动池,可以按数字ID导入:
xxxxxxxxxx
# zpool import 8407636206040904802
如果同名池已存在,则无法导入该池,除非重命名该池。
xxxxxxxxxx
# zpool import db olddb
以上命令将原来的db池作为olddb导入。
导入池的数据集可以在/olddb中找到。这些重命名是永久性的。再次导出该池,将保留最后的池名。
要将池临时挂载到通常装载点以外的位置,可使用-R标志:
xxxxxxxxxx
# zpool import -R /dunno data
这会将路径/dunno临时添加到导入池中的所有数据集中。导出池会删除额外的路径并取消设置altroot属性。
当不确定池中有什么,并且不想将其叠加到现有的数据集或文件系统上时,可使用altroot属性。
记住,BSD文件系统是可以堆叠的。可以在另一种引导环境中使用它,在这种环境中,导入的池可能会覆盖正在运行的根文件系统,并隐藏管理池所需要的工具。
如果池没有足够的成员来提供所有需要的数据,则无法导入池。
xxxxxxxxxx
# zpool import
pool: db
id: 8407636206040904802
state: UNAVAIL
status: One or more devices are missing from the system.
action: The pool cannot be imported. Attach the missing
devices and try again.
see: http://illumos.org/msg/ZFS-8000-3C
config:
db UNAVAIL insufficient replicas
RAID-Z1-0 UNAVAIL insufficient replicas
gpt/zfs1 ONLINE
4300284214136283306 UNAVAIL cannot open
gpt/zfs3 ONLINE
3061272315720693424 UNAVAIL cannot open
以上是一个四提供者组成的RAID-Z1,但是两个提供者丢失了。
检查重新安装的磁盘是否已正确连接,然后重试。
池导入在从损坏的系统中恢复时非常有用。ZFS允许在导入池时解决许多错误和问题。
销毁池并不会销毁数据。仅仅是将池标记为消除,但是池和其中的数据还保存在硬盘上,直到被覆写。使用-D选项告诉ZFS查找已销毁但可以导入的池。
xxxxxxxxxx
# zpool import -D
如果已销毁的池状态显示ONLINE,则表示该池拥有运行所需的一切。使用-D选项可以将其复活。
xxxxxxxxxx
# zpool import -D 8407636206040904802
如果一个池缺少太多存储提供者,则无法导入。不能使用zpool online分离驱动器。
检查驱动器托盘,确保要导入的驱动器都已经连接并通电。下次运行zpool import时将显示重新连接的驱动器。
如果池缺少日志设备,请添加-m标志以在没有该设备的情况下导入它,导出的池应该包含存储提供者上的所有内容。
xxxxxxxxxx
# zpool import -m db
在导入池的时候,可以使用-o选项指定池的属性。
xxxxxxxxxx
# zpool import -o readonly=on db olddb
以上示例以只读方式将池db导入为池olddb。现在,可以从旧池中复制文件,而不会损坏数据的原始副本。
有时可能需要导入损坏的池,以尝试恢复其中的部分数据。-F标志告诉zpool导入回滚最后几个事务。这可能会使池返回可导入状态。这将丢失回滚事务的内容。但这样做依然可能会导致一些问题。
ZFS池允许使用更大的提供者替换小的提供者。
如果一个冗余存储池使用4TB磁盘,可以用10TB磁盘替换它们,并增加池的大小。
池根据每个VDEV中最小的磁盘计算其大小。如果镜像在单个VDEV中有一个4TB的磁盘和一个10TB的磁盘,则镜像VDEV将只有4TB的空间。如果将4TB磁盘更换掉,则可以将镜像扩展到最小磁盘的大小。
ZFS可以自动扩展,但需要为每个池设置autoexpansion属性。默认情况下此选项是关闭的。
默认情况下打开自动扩展会让池变得太大,无法容纳其他任何磁盘。
xxxxxxxxxx
# zpool set autoexpand=on db
如果没有此属性集,则必须在替换提供者后运行命令来扩展池。
以下示例为由三个提供者组成的RAID-Z1池:
xxxxxxxxxx
NAME STATE READ WRITE CKSUM
db ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
gpt/zfs1 ONLINE 0 0 0
gpt/zfs2 ONLINE 0 0 0
gpt/zfs3 ONLINE 0 0 0
每个提供者都是单独的小磁盘。
xxxxxxxxxx
# zpool list db
NAME SIZE ALLOC FREE FRAG EXPANDSZ CAP DEDUP HEALTH ALTROOT
db 59.5G 1.43G 58.1G 1% - 2% 1.00x ONLINE -
如果硬件有足够的物理空间,可添加新的驱动器并创建替换提供者。如果物理空间不足,可关闭提供者并更换磁盘。本例中脱机并更换驱动器。
此池有三个提供者:gpt/zfs1、gpt/zfs2、gpt/zfs3。先替换gpt/zfs1,使用gpart show -l 显示提供者是设备da1。
如果需要离线设备并添加替换设备,首先要确定驱动器da1的物理位置。根据硬件要求准备替换驱动器,然后将提供者脱离池。
xxxxxxxxxx
# zpool offline db gpt/zfs1
此命令应该是静默执行的。使用zpool status检查提供者是否离线。然后将硬盘移出系统。
将替换驱动器插入到卸下旧驱动器的空间或新插槽中。新设备将出现在 /var/run/dmesg.boot中。本例中,新设备显示为/dev/da4。在该驱动器上创建所需的分区并为其添加标签。如果标签中没有使用序列号,而是仅按物理位置进行标签,则可以使用相同的标签。(同样的,我们在这里使用这些短标签,因为它们在学习时更容易阅读。)
xxxxxxxxxx
# gpart create -s gpt da4
da4 created
# gpart add –a 1m -t freebsd-zfs -l zfs1 da4
# zpool replace -f db gpt/zfs1
池完成重建后,再替换其他磁盘。如果使用RAID-Z2或RAID-Z3,可以同时替换多个磁盘,但这是有风险的。额外的磁盘故障可能会导致VDEV故障。
如果没有额外提供者提供冗余,ZFS无法自我修复。每个磁盘的I/O限制可能会限制重新加载的速度。
在第一个提供者重建后,更换下一个较小的提供者。在更换VDEV中的每一个提供者之前,将不会看到磁盘空间的变化。为确保已经用更大的提供者替换了每个提供者,可以使用zpool list查看:
xxxxxxxxxx
# zpool list db
NAME SIZE ALLOC FREE FRAG EXPANDSZ CAP DEDUP HEALTH ALTROOT
db 59.5G 1.70G 57.8G 0% 240G 2% 1.00x ONLINE -
EXPANDSZ表示池可以扩展到的最大尺寸。
如果在开始之前将设置为自动扩展,它应该会自动增长。如果没有,可使用zpool online -e手动扩展池中的每个设备:
xxxxxxxxxx
# zpool online -e db gpt/zfs1
# zpool online -e db gpt/zfs2
# zpool online -e db gpt/zfs3
这个池现在有更多的空间。
FreeBSD和OpenZFS团队不断改进他们的软件,为ZFS和FreeBSD的ZFS支持添加新功能。其中一些改进需要对zpools进行更改或添加。当您升级主机的操作系统时,主机可能会获得现有池不支持的ZFS功能。在使用这些新功能之前,必须升级存储池。如果您不升级池,池将继续运行,但它们将无法利用需要更改磁盘格式的新功能。
但是,在升级操作系统时,您可能会选择不升级池。如果您要将系统从FreeBSD 11升级到FreeBSD 12,您可能会将磁盘保留为FreeBSD 11的池格式。如果需要回滚升级,操作系统仍将能够读取池。操作系统升级是可逆的。但池升级是不可逆的。
最初,ZFS使用版本号来指示支持的池或操作系统版本的功能。版本号从1开始,每改进一次ZFS,就会增加一个版本号。当Sun Microsystems担任所有ZFS开发的中央协调人时,一个递增的版本号是有意义的。OpenZFS中的版本号设置为5000,池使用功能标志。我们在第3章中详细讨论了特征标志。
功能标志的两个问题是:“您的池目前支持哪些功能?”和“您的操作系统支持哪些功能呢?”检查池属性以查看磁盘上的内容,如第3章所述。要查看FreeBSD版本支持的所有功能标志,请运行zpool upgrade -v。
xxxxxxxxxx
# zpool upgrade -v
This system supports ZFS pool feature flags.
The following features are supported:
FEAT DESCRIPTION
-------------------------------------------------------------
async_destroy (read-only compatible)
Destroy filesystems asynchronously.
empty_bpobj (read-only compatible)
Snapshots use less space.
lz4_compress
LZ4 compression algorithm support.
...
标记为“read-only compatible”的功能意味着不支持这些功能标志的主机可以导入这些池,但只能作为只读。有关在主机之间移动池的讨论,请参阅本章前面的“池导入和导出”。 每个版本的FreeBSD发行说明都指出了ZFS的新功能。在升级之前,你确实仔细阅读了发行说明,是吗?如果您以某种方式错过了文档的这一部分,zpool状态告诉您哪些池可以使用升级。(记住,仅仅因为池可以进行升级并不意味着你应该进行升级。如果你可能需要还原操作系统升级,请不要使用池功能!)
xxxxxxxxxx
# zpool status db
pool: db
state: ONLINE
status: Some supported features are not enabled on the pool. The pool can
still be used, but some features are unavailable.
action: Enable all features using 'zpool upgrade'. Once this is done,
the pool may no longer be accessible by software that does not support
the features. See zpool-features(7) for details.
...
您还将获得升级支持的新功能列表。通过在池上运行zpool upgrade来升级您的池。
xxxxxxxxxx
# zpool upgrade zroot
池升级将不可逆地向现有池布局添加新字段。然而,升级不会重写现有数据。虽然新功能可能存在问题,但磁盘上仅提供该功能标志的风险非常低。
如果您计划将磁盘移动到运行旧操作系统的系统,或移动到运行OpenZFS旧版本的操作系统,则可以更有选择地启用池功能。将磁盘从FreeBSD 11系统移动到FreeBSD 10系统需要仔细检查池功能。通过将单个功能的属性设置为enabled来启用该功能。
xxxxxxxxxx
# zpool set feature@large_blocks=enabled data
此池现在支持large_blocks功能。
FreeBSD的引导加载程序必须了解您从中引导的ZFS池。这意味着它必须识别池的特征。
每当更新包含/boot文件系统的池时,都必须更新磁盘上的引导加载程序。
使用gpart(8)更新引导加载程序。
如果从磁盘da0和da1上的ZFS镜像启动,您将按如下方式更新这两个磁盘上的加载器:
xxxxxxxxxx
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da1
没有此更新,系统可能无法启动。zpool upgrade命令会打印一个提醒以执行更新,但如果你愿意,可以忽略它。如果您使系统无法启动,您可能会尝试从最新的FreeBSD当前ISO或活动CD启动,并将其引导加载程序复制到您的系统。
FreeBSD还不支持ZFS的所有功能。由于FreeBSD和Solaris架构之间的根本差异,大多数不受支持的功能都无法工作。人们正在积极开发解决方案,让FreeBSD支持ZFS的所有功能。我们预计其中一些将在本书出版后得到支持。
此时,热备盘不起作用。热备盘使ZFS能够自动将故障驱动器与系统上分配的备用驱动器进行交换。这取决于即将到来的zfsd(8)实现,该实现仍在进行中。
现在,您可以用数据填充池并修复硬件,让我们使用ZFS的几个更有用的功能,克隆和快照。