正如问题所说。
假设我想为我的 FreeNAS 池设置一个脚本化的“紧急按钮”——我可以单击它从 GUI 运行或在控制台/SSH 中执行,这会很快关闭可能正在读取或写入的所有内容,卸载文件系统,并且 - 理想情况下 - 静默它正在使用的磁盘或分区。
我不关心其他软件或远程连接引起的错误,或者过早中止任何长文件传输,我只希望它以最快的方式使池脱机,这与保持其一致性并可能给它一些任何挂起的写入完成和池处于一致状态以用于数据目的的秒数。
ZFS 命令建议的选项看起来并不乐观:zpool offline
仅适用于单个设备,因此如果在一次删除一个磁盘时发生写入,则可能会出现竞争条件;如果正在使用,则需要 -f 选项,并带有可能丢失数据zpool export
的警告。-f
可以使用池或其设备(数千个或数十万个?)检查所有打开file descriptors
的内容并手动强制关闭每个,但这可能会遇到竞争条件,因为它不会阻止同时创建新的 fd。我也不应该假设所有 ZFS 活动都由要发送退出信号的远程文件服务守护进程列表调解,因为某些文件活动可能是本地的(cron/CLI/分离会话)。
因此,看看如何最好地安全快速地使整个池脱机,这看起来umount
可能是我最好的选择 - 它在文件系统级别上工作,并且可以作为一个整体单元快速脱机整个文件系统,之后zpool export
看起来会然后能够在没有-f
选项的情况下以安全的方式实际完成和静默任何内部活动,从而使数据本身保持在有保证的一致状态。如果正在进行原始磁盘活动(重新同步或清理),那么我猜想当池稍后重新联机时会恢复或重新启动。
但umount
似乎并没有完全做到这一点,因为也可能有 iSCSIzvol
目标在使用中。由于服务器不知道其结构,因此其中的数据本质上无法保持一致,因此远程启动器在重新连接时必须尽可能地进行数据修复。我对此很好,但我不确定是否需要某种强制终止或离线目标的命令或最佳实践。(注意:强制终止连接与关闭单个 fd 的问题相同。)
我知道,如果在写入发生时池突然退出 RW 状态,肯定会出现某种数据丢失或问题。但只要它不失去一致性(在 ZFS 池和文件系统级别),那就没问题 - 任何正在更新的正在使用的文件/iSCSI 目标都必须在 ZFS 一致的文件/块上冒险但是由于在写入数据的中途离线而导致数据无效状态。这是不可避免的,也不是问题的问题。
那么我实际上需要执行哪些步骤,以尽可能快地使正在使用的池脱机,并与保证池的安全性和一致性保持一致 - 并且手动umount
使用正在使用的 ZFS 文件系统(作为解决方案的一部分)是安全的或承担任何数据损坏的风险?
更新:在这里提及以防其他人发现这很有用。接受的答案表明export -f
zvols(iSCSI 等)可能存在问题。基于这个提示,我发现 FreeNAS 使用的 iSCSI 处理程序可以强制注销/终止会话,并且还有其他可以预先发出的有用子命令 - 请参阅man ctladm
. 无论您的 zvol 用于什么用途,都可能有一些命令可以结束它们的会话。)
免责声明:目前我手头没有很多链接和参考资料可供备份,也没有进行广泛的测试。这只是我在过去五到七年中阅读的关于 ZFS 及其工作原理的内容的摘要,以及一些有限的自己的测试(未协调,但主要是随机重启)。
此外,以下所有内容均未涉及灾难性事件(服务器完全烧毁)、软件错误(ZFS 和主操作系统以及硬件控制器中的错误)和活动恶意(流氓管理员、管理错误)。对于所有这些情况,您仍然需要定期进行可恢复的备份!
静态数据/磁盘一致性
首先,好消息:由于 ZFS 使用 CoW 和原子事务,即使在突然断电的情况下,您已经存在的数据也将是安全的。这包括池布局和元数据。由于在新数据完全写入之前,旧数据永远不会移动(实际上,它根本不会移动,只是重新分配),因此如果写入突然中断,这些数据不会有任何危险。
此外,校验和(Merkle 哈希树)有助于证明在重新启动期间没有发生任何不良情况,您可以通过清理池来检查。如果您有冗余的 vdev,ZFS 将自动更正它从已知良好副本中发现的任何错误。如果某些块会以任何方式损坏(例如,被不写但说有的流氓磁盘控制器损坏),它们的校验和将与来自其他 vdev 的校验和不匹配,并且会显示错误。
飞行/写入模式中的数据和最后 n 秒的丢失
同步和异步写入
通常,ZFS 收集多个事务以加速对旋转驱动器的昂贵写入 - 定位 HDD 的写入头比实际写入需要更多时间,因此您将希望尽可能多地排队,然后按顺序将其写入(更快!)订单(请记住,我们有 CoW,这在这里很自然地工作)。
这样做的缺点是您收集的时间越长,您的应用程序等待“写入成功”消息的时间就越长 - 这意味着您的系统将锁定几秒钟,这是不可接受的。更糟糕的是——如果发生电源故障,您将丢失所有要写入磁盘但尚未写入的数据。如果您的应用程序无法处理此问题,则应用程序层可能会发生损坏。
为了解决这个问题,添加了 ZIL(ZFS 意图日志)。所有同步事务都收集在这个日志中(默认存储在慢池磁盘上,但可以存储在速度更快的镜像 SSD 上,称为 SLOG 设备),存储后返回“写入成功”到可以继续执行其任务的应用程序(不再锁定)。此外,所有异步事务都是在没有 ZIL 的情况下完成的,因此它们可以更快 - 只要应用程序为其数据调用正确的写入操作(同步与异步)。
ZFS 属性
现在来看更有趣的部分——你的作品会发生什么?在那里我们必须识别文件系统的操作模式(它是 ZFS 属性,可以为每个文件系统单独设置)。三种可能的模式是(来自手册页):
您会注意到,即使
disabled
选择了,您的池布局/内部一致性也不会受到影响 - 您只会丢失最后 5 秒的数据,这可能会使您的文件处于不正确的状态(例如,因为您有一个虚拟机top 期望同步写入,但您只提供了一个异步 zvol 作为后备数据存储)。另一方面,如果您根本不想丢失任何东西,请将所有文件系统设置为
always
并切换到高性能 SSD,至少对于 SLOG 设备(或忍受等待时间)。standard
是一种折衷方案,也是最灵活的——应用程序本身决定它需要哪种写入模式。如果您的应用程序不好,您可能会遇到数据丢失。如果它们表现良好,您将在给定的安全基线下获得最佳性能。池导出/导入:
从有关的文档中
zpool export
:这大致意味着三件事:
-f
通过强制卸载所有文件系统来强制导出池,即使它们处于活动状态(忽略锁或写在那里的应用程序)zvol
s概括:
export -f
或完全关闭sync=always
快速 SSD回复评论中的后续问题(省略了我没有任何有用答案的问题):
最坏的情况是所有冗余设备上的超级块(所有其他块的顶部)都损坏了。因为它上面没有块,你不能从上面重建它,所以每个 uberblock 都存在多个副本(IIRC 大约是 3 或 4 个),所以一个可能会丢失并且替换副本仍然存在。
我对 dedup 没有真正的经验,所以我不能在这里说任何有用的东西,除非你已经在硬件方面做出了很好的选择(低延迟、高随机 64k 写入 IOPS、NVMe 接口)。如果您投资一些非常昂贵的永久 RAM 驱动器(ZeusRAM 等人),它只会更快。
是的。本质上是“我的游泳池没有搞砸,耶!” 在多用户设置中 - 即使一个用户的文件有问题,其他用户也不会受到影响。
是的,本质上是硬关闭虚拟机而不是干净关闭然后拍摄快照 - 如果你之后打开它,
fsck
或者类似的取决于文件系统将运行,它可能会抱怨不干净的关闭。这与 ESXi 快照不同,后者在准确的时间点恢复,就好像什么都没发生一样,但它们需要与来宾系统交互(安装来宾添加)并包括 VM 的虚拟内存。您可以将两者结合起来发挥自己的优势:首先拍摄 ESXi 快照,然后拍摄数据存储的 ZFS 快照(ESXi 将其快照存储在 VM 旁边)。然后删除您的 ESXi 快照,但保留 ZFS 快照(由于块级副本占用的空间要少得多)。还原时,首先还原 ZFS 快照,然后还原到(已保存)的 ESXi 快照,然后从上次中断的地方继续。napp-it(带有 Web 界面的优秀 ZFS 管理系统)内置了这个概念(至少对于 NFS 数据存储,我没有检查 iSCSI,但假设它是相似的)。