github编辑

22.3.zpool 管理

22.3.1. 创建和销毁存储池

创建一个 ZFS 存储池需要做出永久性的决策,因为池的结构在创建后无法更改。最重要的决策是将物理磁盘分组为哪种类型的 vdev。有关可能的选项,请参阅 vdev 类型arrow-up-right 列表。创建池后,大多数 vdev 类型不允许向 vdev 添加磁盘。例外的是镜像(mirrors),它允许向 vdev 添加新磁盘;条带(stripes)也可以通过将新磁盘附加到 vdev 来升级为镜像。尽管添加新的 vdev 会扩展池,但池的布局在创建后无法更改。相反,你需要备份数据,销毁池并重新创建。

创建一个简单的镜像池:

# zpool create mypool mirror /dev/ada1 /dev/ada2
# zpool status
  pool: mypool
 state: ONLINE
  scan: none requested
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            ada1    ONLINE       0     0     0
            ada2    ONLINE       0     0     0

errors: No known data errors

要在单个命令中创建多个 vdev,请指定由 vdev 类型关键字(在此示例中为 mirror)分隔的磁盘组:

# zpool create mypool mirror /dev/ada1 /dev/ada2 mirror /dev/ada3 /dev/ada4
# zpool status
  pool: mypool
 state: ONLINE
  scan: none requested
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            ada1    ONLINE       0     0     0
            ada2    ONLINE       0     0     0
          mirror-1  ONLINE       0     0     0
            ada3    ONLINE       0     0     0
            ada4    ONLINE       0     0     0

errors: No known data errors

池也可以使用分区,而不是整个磁盘。将 ZFS 放入单独的分区可以使同一磁盘具有其他分区,用于其他目的。特别是,它允许添加具有启动代码和启动所需文件系统的分区。这使得可以从同时作为池成员的磁盘启动。使用分区而不是整个磁盘不会对 FreeBSD 性能造成额外的负担。使用分区还允许管理员进行 低配 磁盘操作,即使用比整个磁盘容量少的空间。如果未来替换的磁盘与原始磁盘的名义大小相同,但实际容量略小,则较小的分区仍然可以适应替换磁盘。

使用分区创建一个 RAID-Z2arrow-up-right 池:

销毁一个不再需要的池以重新利用磁盘。销毁池之前需要先卸载该池中的文件系统。如果某个数据集正在使用中,卸载操作会失败,无法销毁池。可以使用 -f 强制销毁池。这可能会导致应用程序出现未定义行为,特别是当应用程序有打开的文件时。

22.3.2. 添加和移除设备

有两种方法可以将磁盘添加到池中:通过 zpool attach 将磁盘附加到现有的 vdev,或者通过 zpool add 向池中添加 vdev。一些 vdev 类型arrow-up-right 在创建后允许向 vdev 添加磁盘。

使用单个磁盘创建的池没有冗余。它可以检测到损坏,但无法修复,因为没有数据的其他副本。复制arrow-up-right 属性可能能够从小的故障(例如坏道)中恢复,但它不像镜像或 RAID-Z 那样提供相同级别的保护。从一个由单个磁盘 vdev 组成的池开始,使用 zpool attach 将新磁盘添加到 vdev,创建一个镜像。也可以使用 zpool attach 将新磁盘添加到镜像组中,从而增加冗余和读取性能。在对用于池的磁盘进行分区时,将第一个磁盘的布局复制到第二个磁盘。使用 gpart backupgpart restore 可以简化这一过程。

将单个磁盘(条带)vdev ada0p3 升级为镜像,通过附加 ada1p3

当向现有的 vdev 添加磁盘不可行时(例如 RAID-Z),一种替代方法是向池中添加另一个 vdev。添加 vdev 提供了更高的性能,通过将写入分配到各个 vdev 上。每个 vdev 提供其自身的冗余。可以混合使用 mirrorRAID-Z 类型的 vdev,但不推荐这样做。向包含镜像或 RAID-Z vdev 的池中添加非冗余 vdev 会使整个池的数据面临风险。分布式写入意味着,如果非冗余磁盘发生故障,将导致写入池的每个块的一部分丢失。

ZFS 将数据条带化到每个 vdev 上。例如,使用两个镜像 vdev,这实际上是一个 RAID 10,将写入条带化到两个镜像组上。ZFS 会分配空间,以确保每个 vdev 在相同时间达到 100% 满。拥有不同可用空间的 vdev 会降低性能,因为更多的数据写入会到达较少满的 vdev。

向启动池添加新设备时,请记得更新启动代码。

将第二个镜像组(ada2p3ada3p3)附加到现有的镜像:

无法从池中移除 vdev,只有在剩余冗余足够的情况下才可以移除镜像中的磁盘。如果一个镜像组中只剩一个磁盘,该组将不再是镜像,而变成条带,如果该磁盘发生故障,将危及整个池的数据。

从三重镜像组中移除一个磁盘:

22.3.3. 检查池的状态

池的状态很重要。如果某个硬盘脱机或 ZFS 检测到读取、写入或校验和错误,相应的错误计数将增加。status 输出显示了池中每个设备的配置和状态,以及整个池的状态。还会显示对上一次 scrubarrow-up-right 的操作详情。

22.3.4. 清除错误

当检测到错误时,ZFS 会增加读取、写入或校验和错误计数。使用 zpool clear <mypool> 清除错误消息并重置计数。清除错误状态对于自动化脚本非常重要,因为这些脚本会在池遇到错误时提醒管理员。如果不清除旧错误,脚本可能会无法报告后续错误。

22.3.5. 替换正常的设备

有时可能希望用不同的硬盘替换一个磁盘。替换正常磁盘时,操作过程中会保持旧磁盘在线,池不会进入 degradedarrow-up-right 状态,从而减少数据丢失的风险。运行 zpool replace 将数据从旧磁盘复制到新磁盘。操作完成后,ZFS 会将旧磁盘从 vdev 中断开。如果新磁盘比旧磁盘大,可能能够使用新空间扩展 zpool,见 扩展池arrow-up-right

替换池中的正常设备:

22.3.6. 处理故障设备

当池中的磁盘发生故障时,磁盘所在的 vdev 会进入 degradedarrow-up-right 状态。数据仍然可用,但性能会降低,因为 ZFS 会从可用的冗余数据中计算缺失的数据。为了将 vdev 恢复到完全正常的状态,需要替换故障的物理设备。然后会指示 ZFS 开始 resilverarrow-up-right 操作。ZFS 会从可用的冗余数据中重新计算故障设备的数据,并将其写入替换设备。操作完成后,vdev 会恢复到 onlinearrow-up-right 状态。

如果 vdev 没有冗余,或者设备出现故障且冗余不足以弥补,池会进入 faultedarrow-up-right 状态。除非有足够的设备重新连接池,否则池将无法使用,必须从备份中恢复数据。

在替换故障磁盘时,故障磁盘的名称会更改为新磁盘的 GUID。如果替换设备的名称与原设备相同,zpool replace 不需要指定新的设备名称。

使用 zpool replace 替换故障磁盘:

22.3.7. 对池进行 Scrub

建议定期对池进行 scrubarrow-up-right,最好每月至少进行一次。scrub 操作会消耗磁盘资源,因此在运行时会降低性能。请避免在高负载时期安排 scrub 操作,或者使用 vfs.zfs.scrub_delayarrow-up-right 调整 scrub 的相对优先级,以免影响其他工作负载。

如果需要取消 scrub 操作,可以运行 zpool scrub -s <mypool>

22.3.8. 自我修复

存储在数据块中的校验和使文件系统能够进行​自我修复​。此功能将在检测到数据的校验和与存储池中其他设备记录的校验和不匹配时,自动修复数据。例如,如果一个镜像配置中有两块磁盘,其中一块磁盘开始出现故障,无法再正确存储数据,而另一块磁盘仍然正常。这种情况在长期存档存储中尤为严重,因为数据可能长时间未被访问。传统的文件系统需要运行命令来检查和修复数据,如 fsck(8)arrow-up-right。这些命令需要时间,在严重情况下,管理员需要决定执行哪种修复操作。而 ZFS 在检测到数据块的校验和不匹配时,会尝试从镜像磁盘读取数据。如果该磁盘提供了正确的数据,ZFS 会将其提供给应用程序,并修复具有错误校验和的磁盘上的数据。此过程在正常池操作期间无需管理员干预。

以下示例展示了这种自我修复行为,创建了一个由 /dev/ada0/dev/ada1 组成的镜像池。

将一些重要数据复制到池中,以保护数据免受错误,并创建池的校验和以供后续比较。

通过向镜像中的一块磁盘写入随机数据来模拟数据损坏。为了防止 ZFS 在检测到损坏时修复数据,首先导出池,然后在损坏后重新导入。

警告

这是个危险操作,可能会销毁重要数据,仅用于演示。在正常操作的存储池中不要尝试。不要在任何具有 ZFS 文件系统以外分区的磁盘上运行此有意损坏示例。不要使用池外的任何其他磁盘设备名。确保存在正确的池备份,并在运行命令之前测试它们!

池的状态显示某个设备出现了错误。请注意,应用程序读取数据时未收到任何错误数据。ZFS 从未受影响的 ada0 镜像磁盘提供了数据。要查找校验和错误的设备,请查看 CKSUM 列包含非零值的设备。

ZFS 检测到错误并通过使用未受影响的 ada0 镜像磁盘中的冗余数据进行了修复。通过与原始校验和的比较,可以查看池是否一致。

在有意破坏数据时,生成校验和并与池数据仍然一致。这展示了 ZFS 如何能够在校验和不同的情况下自动检测并修复任何错误。请注意,这只有在池中有足够的冗余时才可能。由单个设备组成的池没有自我修复能力。这也是为什么校验和在 ZFS 中如此重要;不要因任何原因禁用它们。ZFS 无需 fsck(8)arrow-up-right 或类似的文件系统一致性检查程序来检测和修复这些问题,并在出现问题时保持池的可用性。现在需要进行一个 scrub 操作来覆盖 ada1 上的损坏数据。

scrub 操作从 ada0 读取数据,并在 ada1 上重写任何具有错误校验和的数据,显示为 zpool status 中的 (repairing) 输出。操作完成后,池状态将变为:

在 scrub 操作完成并将所有数据从 ada0 同步到 ada1 后,使用 zpool clear 清除池状态中的错误消息。

池现在已经恢复到完全正常的状态,所有错误计数都为零。

22.3.9. 扩展池

每个 vdev 中最小的设备限制了冗余池的可用大小。可以通过将最小设备替换为更大的设备来扩展池的容量。完成 replacearrow-up-rightresilverarrow-up-right 操作后,池的可用空间会增长到新设备的容量。例如,考虑一个由 1 TB 和 2 TB 硬盘组成的镜像池。可用空间为 1 TB。当将 1 TB 硬盘替换为另一个 2 TB 硬盘时,resilver 操作将现有数据复制到新硬盘。由于两个硬盘现在都具有 2 TB 的容量,因此镜像池的可用空间将增加到 2 TB。

通过对每个设备使用 zpool online -e 开始扩展。扩展所有设备后,额外的空间将可供池使用。

22.3.10. 导入和导出池

在将池迁移到另一台系统之前,应先 导出 池。ZFS 会卸载所有数据集,并将每个设备标记为已导出,但仍会锁定以防止被其他磁盘使用。这使得池可以在其他支持 ZFS 的机器、操作系统甚至不同硬件架构上进行 导入(有一些注意事项,参见 zpool(8)arrow-up-right)。当数据集有打开的文件时,使用 zpool export -f 强制导出池。使用此命令时需小心。数据集会被强制卸载,可能会导致应用程序在这些数据集上有打开文件时出现意外行为。

导出一个未使用的池:

导入池会自动挂载数据集。如果不希望出现这种行为,可以使用 zpool import -N 来防止自动挂载。zpool import -o 可以为此次导入设置临时属性。zpool import altroot= 允许使用基本挂载点而不是文件系统根目录导入池。如果池上次使用的是不同的系统,并且未正确导出,可以使用 zpool import -f 强制导入池。zpool import -a 导入所有未被其他系统使用的池。

列出所有可用的池进行导入:

使用替代根目录导入池:

22.3.11. 升级存储池

升级 FreeBSD 后,或者从使用较旧版本的系统导入池时,需要手动将池升级到最新的 ZFS 版本,以支持更新的特性。在升级之前,考虑池是否可能在未来需要在旧系统上导入。升级是单向操作。可以升级旧池,但无法将池降级以支持新特性。

将 v28 池升级以支持 Feature Flags

升级后,直到 zpool upgrade 完成,ZFS 的新特性将不再可用。使用 zpool upgrade -v 查看升级提供了哪些新特性,以及哪些特性已被支持。

升级池来支持新特性标志:

警告

在从池启动的系统上更新引导代码,以支持新池版本。

对于使用 GPT 启动的旧系统,可以使用以下命令:

对于使用 EFI 启动的系统,执行以下命令:

将引导代码应用于池中的所有可启动磁盘。有关更多信息,请参阅 gpart(8)arrow-up-right

22.3.12. 显示记录的池历史

ZFS 会记录所有改变池状态的命令,包括创建数据集、更改属性或替换磁盘。回顾池的创建历史很有用,同样也可以检查哪个用户在什么时候执行了特定的操作。历史记录并不会保存在日志文件中,而是池的一部分。查看历史记录的命令正如其名为 zpool history

输出显示了 zpoolzfs 命令如何以时间戳记录改变池状态的操作。像 zfs list 这样的命令不会包含在内。若不指定池名称,ZFS 会显示所有池的历史记录。

通过提供选项 -i-lzpool history 可以显示更多信息。-i 会显示用户发起的事件以及内部记录的 ZFS 事件。

通过加上 -l 显示更多细节。长格式的历史记录包括了执行命令的用户和命令发生的主机名信息。

输出显示 root 用户创建了由 /dev/ada0/dev/ada1 组成的镜像池。主机名 myzfsbox 也在池创建后的命令中显示出来。当池从一个系统导出并导入到另一个系统时,主机名信息变得非常重要。可以通过主机名区分在其他系统上执行的命令。

将两个选项结合使用,zpool history 可以提供任何池的最详细信息。池历史记录在追踪执行的操作或调试时提供了宝贵的帮助。

22.3.13. 性能监控

ZFS 提供了一个内建的监控系统,可以实时显示池的 I/O 统计数据。它展示了池的已用空间和空闲空间、每秒读写操作以及使用的 I/O 带宽。默认情况下,ZFS 会监控并显示系统中所有池的状态。若只想监控某个特定池,可以指定池的名称。以下是一个基本示例:

要持续查看 I/O 活动,可以指定一个数字作为最后一个参数,表示每次更新的间隔时间(以秒为单位)。每次统计数据将会在该间隔后打印一次。按 Ctrl**+**C 停止连续监控。如果还要指定显示的统计次数,可以在命令行中添加第二个数字。

通过使用 -v 显示更详细的 I/O 统计数据。每个池中的设备都会有一行统计数据。这有助于查看每个设备的读写操作,帮助判断是否有某个设备拖慢了池的性能。以下是一个镜像池的例子,包含两个设备:

22.3.14. 拆分存储池

ZFS 可以将由一个或多个镜像 vdev 组成的池拆分成两个池。除非特别指定,ZFS 会从每个镜像中分离出最后一个成员,并创建一个包含相同数据的新池。在实际执行前,最好先使用 -n 选项进行模拟运行,这会显示请求操作的细节,而不会实际执行该操作。这有助于确认操作会按照预期执行。

最后更新于