# FreeBSD vs Linux: ZFS

* 原文：[FreeBSD vs Linux: ZFS](https://freebsdfoundation.org/wp-content/uploads/2017/10/FreeBSD-vs.-Linux-ZFS.pdf)
* 作者：ALLAN JUDE

OpenZFS 可在多种平台上使用，包括 FreeBSD、Solaris 衍生系统（如 illumos）、Mac OS X 以及 Linux。然而，在后者平台上，并非所有功能都可用。FreeBSD 项目已全面采用 ZFS，投入大量精力将其与系统及管理工具集成，使 ZFS 成为操作系统的无缝组成部分，而非附加组件。在 FreeBSD 上，OpenZFS 的集成度、监控能力和文档完善程度均优于各类 Linux 发行版。

## 为何使用 ZFS

这并不是说其他文件系统不好；只是它们犯了个错误——相信你的存储硬件在你请求时会返回正确的数据。事实证明，硬盘在这方面表现相当不错，但“相当不错”往往仍不足以保障数据安全。ZFS 是唯一一款开源、生产级的文件系统，不仅能检测磁盘返回的错误数据，还能进行纠正。通过结合文件系统和卷管理器的功能，ZFS 还能确保数据安全，即使在一块或多块磁盘缺失的情况下，也能根据配置保护数据。ZFS 不信任你的硬件；它会验证每次从磁盘读取的数据是否正确。

ZFS 的首要设计考量是数据安全。写入文件系统的每个数据块都会附带一个数据校验和，并与其他元数据一起存储。该元数据块本身也有校验和，其父块也有，直到顶层块——称为 uber block。

当 ZFS 文件系统进行挂载时，它会检查可用的 uber block 数组，并选择最新且校验和有效的块。结合写时复制（copy-on-write，CoW）特性，这意味着即使发生断电或系统崩溃，ZFS 也能保持文件系统的一致性；所有正在进行但未完成的操作都会被回滚，以保持文件系统的完整性。这也就不需要在意外关机后进行长时间的文件系统检查。

每当从 ZFS 文件系统读取文件的一个数据块时，磁盘返回的数据都会生成校验和，并与元数据中存储的校验和进行验证。如果两者不符，说明磁盘返回了错误数据。ZFS 会检测到这一情况，并为每块磁盘记录此类错误次数，因为这可能是磁盘即将发生故障的信号。

如果 ZFS 文件系统配置了冗余（如镜像或 RAID-Z），这些校验信息将用于重建错误的数据块，并将修复后的数据写回磁盘。如果没有冗余且数据无法恢复，将返回错误。这能让操作系统阻止应用程序使用无效数据，避免程序崩溃或执行错误操作。

ZFS 还提供许多其他功能，包括透明压缩、高级分层缓存、快照、去重、数据复制、权限委派、启动环境，以及即将支持的“静态”加密。ZFS 的设计旨在简化存储管理员的工作，使扩容操作尽可能容易。ZFS 还简化了配额与保留管理、网络文件共享管理、权限委派以及存储管理员日常的其他常见任务。所有操作均通过直观的命令行界面进行管理，既可供人工操作，也可通过脚本自动化执行。

## 启动环境

虽然 OpenZFS 最大的特点是它提供的数据完整性保证，但紧随其后的最有用功能是启动环境（boot environments）的概念。该功能允许设备同时拥有多个操作系统安装，并能在启动时轻松切换。借助 ZFS 的写时复制特性，这些额外的系统镜像通常占用极少的存储空间。实现这一功能的前提是根文件系统位于 ZFS 上，并与启动加载器进行一定集成。这些功能在 FreeBSD 上已经存在多年，并且不断得到优化和改进。

在移动计算平台上，这种灵活性和稳定性保障尤其有用。设想在大型演示前几分钟，你发现上周的更新导致演示软件出现问题。只需重启，选择上周的启动环境，操作系统和应用程序就会回滚到已知可用状态，而你的数据文件、主目录等仍是最新版本。再次重启，你又可以回到最新的系统镜像。整个系统实际上就像处于一种基本的版本控制之下。你可以分叉系统进行实验，并放心地知道，随时可以通过快速重启切换回可用系统。

你的各个系统镜像并不需要互为写时复制的克隆，它们可以完全独立成为单独的镜像。在共享用户数据文件的同时，可以轻松地在稳定版本与开发快照之间切换。需要在每个支持的 FreeBSD 版本上测试最新工作？完全没问题。通过额外配置，甚至可以实现多重启动其他支持 OpenZFS 的操作系统。

在 ScaleEngine，我们利用这一机制分发定制的 FreeBSD 黄金镜像（最终的）。我们在构建并调整 FreeBSD 到理想状态后，使用 `zfs send` 命令生成复制流，并重定向到文件。生产服务器通过 HTTPS 获取该镜像，并通过 `zfs recv` 创建新的启动环境。然后，`zfsbootcfg` 配置该启动环境用于下一次启动（仅一次）。如果镜像存在问题导致无法启动或崩溃，通过断电重启，系统会回到原始镜像。

如果新镜像在系统启动 10 分钟且网络连接正常的情况下保持运行，镜像中的脚本可以将其设置为新的默认镜像。这一流程让我们安全地升级全球各地的远程系统，几乎无需人工干预。如果新镜像不满意，只需一个命令即可将默认镜像切换回之前的任意版本，再次重启即可恢复系统运行。这使得在生产环境中，只用一小部分服务器就能轻松测试开发镜像，无需任何特殊操作。

OpenZFS 即将推出的另一项功能是在系统发生重复故障时，自动引导到一个特殊的调试/救援镜像。在像 Amazon EC2 这样的环境中，由于没有控制台支持，如果系统因启动失败或连续 panic 而无法正常启动，就很难修复系统，除非将其磁盘挂载到另一台 EC2 实例上。有了这项新功能，每次启动时系统会递增一个计数器，只有当系统持续运行足够长时间时，镜像中的脚本才会将计数器重置为零。如果计数器超过设定阈值，下一次启动将加载救援镜像，并通知运维人员进行调试和问题解决。

## 磁盘加密

FreeBSD 拥有高性能的全盘加密系统 GELI。它长期以来常与 ZFS 结合使用，以创建完全加密的存储池。这要求对启动过程进行特殊处理，因为启动加载器需要从未加密的存储中加载内核。2016 年初，我将 GELI 支持集成到 bootstrap 和 loader 中，使得可以从一个整个文件系统都加密的 zpool 启动。

Oracle 提供的闭源 ZFS 版本已经支持加密功能一段时间，但 OpenZFS 一直没有提供该功能。

## SSD TRIM

FreeBSD 目前是唯一支持 TRIM 的 OpenZFS 实现。TRIM 支持于 2012 年集成到 FreeBSD 中，以提升由 SSD 和其他基于闪存的设备组成的存储池的性能。TRIM 功能会向 FTL（Flash Translation Layer）反馈哪些数据块已不再使用并可回收，从而使 SSD 固件能够更好地管理磨损均衡和垃圾回收。

OpenZFS 项目正在开发一个不同的、跨所有支持平台的通用 TRIM/UNMAP 功能，但预计要到 2018 年才会完成。这个新实现更为先进，预计能进一步提升性能；但在此之前，其他平台上的 ZFS 用户完全无法使用 TRIM 功能。

## Jail

Solaris 及其衍生系统拥有 zones，以及基于 FreeBSD jail 概念发展的先进容器技术。这意味着从一开始，ZFS 就与 zones 实现了高级集成，当 ZFS 移植到 FreeBSD 时，这些特性随之而来，并被改造以适应 FreeBSD 的 jail。Linux 没有与 jail 或 zones 直接对应的机制，因此目前在 Linux 容器中没有 ZFS 支持。

在 FreeBSD 中，可以将一个数据集（ZFS 文件系统）标记为“jailed”。一旦设置了此标志，该文件系统将无法在宿主系统（在 Solaris 术语中为 Global Zone）上挂载，这是一个安全特性。被委派给容器的数据集的挂载点相对于容器的根目录。若一个挂载点为 `/etc` 的 jailed 数据集被挂载在宿主系统上，可能修改 root 密码或其他配置，使容器中的用户能够控制宿主上的文件内容。

只要文件系统设置了 jailed 属性，可以使用 `zfs jail` 命令将该数据集及其子数据集委派给特定的 jail。如果激活了 `allow.mount_zfs` 参数，容器内的 root 对该数据集及其子数据集拥有完整控制权限，除了 jailed 属性和诸如配额等限制。这允许容器内的 root 创建和管理新的数据集、快照以及 ZFS 的所有其他功能。容器内的 root 甚至可以利用常规 ZFS 委派功能，进一步将命令和属性的访问权限委派给该 jail 中的普通用户。这种灵活性使得高并发多租户管理变得相对容易。

在 ScaleEngine，我们利用这些特性允许客户通过 SSH 访问其视频存储，并通过 jail 将其隔离在不受信任的容器中，仅能访问自己的文件。用户委派和容器委派让我们能够在不使用特权访问的情况下进行客户数据的远程复制，同时隔离客户数据，又确保他们对自己的文件有完全访问权限。

## 许可协议

当 Sun Microsystems 将 ZFS 作为 OpenSolaris 的一部分发布时，采用了 CDDL（Common Development and Distribution License，通用开发与分发许可证，第 1.0 版）。CDDL 来源于 Mozilla 公共许可证（MPL），试图在 GPL（强制性、传染性）与 BSD 许可证（宽松型）之间取得中间立场。

GPL 授权的代码必须始终保持 GPL 授权，任何衍生或组合作品，无论是源代码、二进制还是其他形式，都必须遵循 GPL。BSD 许可证对代码使用没有限制，只要求源代码中的版权声明不得删除，并可在其他许可证下重分发。相比之下，CDDL 授权的源代码必须保持 CDDL 授权，但由其生成的二进制文件可以由创作者以任意方式授权，只要修改后的源代码仍以 CDDL 形式提供。CDDL 授权的文件可以与其他许可证（开源或专有）授权的文件组合使用。

Sun 认为，这为企业在最终产品授权上提供了更多灵活性，同时确保 ZFS 的所有功能保持开源。将 OpenZFS 与 FreeBSD 结合使用，依托其宽松的 BSD 许可证，就无需担心潜在的合规性问题。

自由软件基金会（FSF）在 2016 年 4 月 11 日发布声明，明确指出将 CDDL 授权的软件（尤其是 ZFS）作为 GPL 授权作品（如 Linux 内核）的一部分进行分发，是违反 GPL 许可证的。“仅仅要求组合程序以某种方式成为自由软件是不够的。整个组合必须以原始的 copyleft 许可证（GPL）发布。”

因此，虽然根据 CDDL 许可证，你可以将代码与 GPL 授权代码结合，并生成一个以 GPL 授权的二进制模块，但这仍与 GPL 不兼容，因为组合后的源代码也必须以 GPL 发布，而 CDDL 不允许这一点。幸运的是，这些限制仅适用于再分发，而不适用于私人使用。“GNU GPL 对你私下使用没有实质性要求；GPL 条件适用于你将作品提供给他人时。”所以，你可以使用 ZFS，但不能将其作为完整产品进行分发。

Ubuntu 项目对此有不同看法：“zfs.ko 作为一个独立的文件系统模块，显然不是 Linux 内核的衍生作品，而很明显是 OpenZFS 和 OpenSolaris 的衍生作品。”然而，Software Freedom Conservancy（SFC，软件自由保护组织）持不同意见。看来谨慎的做法是避免这一法律泥潭，直接使用 FreeBSD，其简洁的两条款许可证避免了这些问题。

ZFS 的主要设计考虑是数据的安全性。每个写入文件系统的块都会附带一个数据校验和，并与其他元数据一起存储。该元数据块本身也有校验和，其父块同样有校验和，一直递归到顶层块，称为 uber 块。

## 总结

如果数据完整性对你很重要，OpenZFS 是唯一值得信赖的开源解决方案。而运行 OpenZFS 的最佳平台是 FreeBSD。利用 FreeBSD 提供的完整生态系统，包括功能、工具、应用和解决方案，使其成为服务器和存储的领先选择。

如果你想深入了解 ZFS 以及如何将其高级功能应用于存储挑战，可以在你喜欢的零售商处或访问 [www.zfsbook.com](http://www.zfsbook.com) 购买《FreeBSD Mastery: ZFS》和《FreeBSD Mastery: Advanced ZFS》。

ALLAN JUDE 是 ScaleEngine Inc. 的运营副总裁，该公司是一家视频流内容分发网络，他在 FreeBSD 上广泛使用 ZFS。Allan 是 FreeBSD 源码和文档的 committer，并于 2016 年夏被选入 FreeBSD 核心团队。他还是每周视频播客 BSDNow\.tv（与 Benedict Reuschling 合作）的主持人，并与 Michael W Lucas 合著了《FreeBSD Mastery: ZFS》和《FreeBSD Mastery: Advanced ZFS》。

* 1 本文不构成法律建议，你不能也不应将其视作法律依据。
* 2 <https://www.fsf.org/licensing/zfs-and-linux>
* 3 <https://insights.ubuntu.com/2016/02/18/zfs-licensing-and-linux/>
* 4 <https://sfconservancy.org/blog/2016/feb/25/zfs-and-linux/>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://freebsd-journal-cn.bsdcn.org/2017-0910-freebsd-vs-linux/freebsd-vs-linux-zfs.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
