在命令行中使用 ZFS 相关命令
坑边闲话:TrueNAS 提供了良好的 ZFS 使用体验,但是频繁使用 Web 界面并非是一个令人舒适的事情。我的原则是,与存储相关的问题尽量在命令行里解决。此外,将 Debian 系统配置为一个理想的存储服务器是很吸引人的,但这依旧需要用户对存储管理的命令行有深入的理解。
本文包括但不限于以下内容;
- ZFS 打快照、删除快照
- ZFS 存储吃创建
- ZFS 文件系统创建与销毁
- ZFS 文件系统的参数调整
1. 安装 ZFS 相关组件·
1.1 常规安装·
Debian 或者 Ubuntu 等 Linux 发行版不具备 TrueNAS 的网页图形化界面,因此操作 ZFS 时颇为繁琐,为此我们做简单介绍。
1 | sudo apt-get install -y zfs-dkms zfsutils-linux nfs4-acl-tools |
随后会注册两个 Systemd 服务:
1 | Created symlink /etc/systemd/system/zed.service → /lib/systemd/system/zfs-zed.service. |
1.2 问题排查·
如果遇到 zfs-load-module.service
服务失败时,大概率是 Linux Kernel 升级了但是系统并没有下载对应的 linux-headers
文件,可通过下列命令安装头文件并重新安装 ZFS DKMS 模块。
1 | sudo apt install linux-headers-$(uname -r) |
2. 存储池相关·
存储池是最关键的部分,因为它是数据集的底层。存储池与 RAID 类型密切相关,一般存储池将会涉及以下内容:
- 存储冗余度,
- 虚设备,如 Slog、L2ARC 等。
如果不能保证底层的可靠,用户侧做再多设置都是错的。接下来将介绍与存储池相关的高频操作。
2.1 创建存储池·
对于磁盘列表,可以使用 nvme-cli
等工具查看硬盘列表。
对于 SATA 硬盘,可能需要使用 lsblk
等命令进行查看。
获得了磁盘列表,并成功地将物理磁盘与磁盘句柄(盘符)进行配对之后,即可进行存储池创建:
1 | $POOL_NAME=tank |
2.2 对存储池进行导入和导出·
在创建存储池之后,如果需要将硬盘拔除,则需要先把存储池下线,即 export
导出。
1 | $POOL_NAME=tank |
如果需要恢复存储池,则使用相反的命令 import
导入。
1 | $POOL_NAME=tank |
如果需要对存储池进行重命名,则需要先导出再导入且在导入的时候使用新的名字,同时应该注意,并没有 zpool-rename
这种命令。
1 | # Rename a zfs pool |
3. 数据集相关·
在完成了底层存储池的构建之后,我们所关心的主要是用户侧的内容,如存储池和文件共享等。
存储池已经
- 通过 data vdev 提供了基本的存储能力,
- 通过 Slog 和 L2ARC 提供了读写强化(可选),
- 通过 Hot spare 盘提供了一定程度的故障自动转移(可选)。
数据集就是建立在存储池之上的抽象的文件系统,也是用户真正可读写的最基本单元。存储池使用 zpool
系列命令进行配置,数据集通过 zfs
命令进行配置。从命令名也可以看出,数据集就是真正的 ZFS 文件系统。
3.1 创建数据集·
1 | $DATASET_NAME=data |
3.2 设置数据集的相关属性·
熟悉 C# 编程的朋友应该清楚,通过设置一对 get
、set
函数,可以用来获取、修改 class 的属性。ZFS 的数据集属性访问与 C# 的语法非常相似。
- 获取属性使用
zfs get
- 设置属性使用
zfs set
3.2.1 设置压缩方式·
1 | sudo zfs set compression=lz4 ${POOL_NAME}/${DATASET_NAME} |
3.2.2 设置权限类型·
1 | sudo zfs set acltype=nfsv4 ${POOL_NAME}/${DATASET_NAME} |
3.2.3 设置挂载入口·
这是唯一一个特殊的命令,它使用 zfs
控制存储池。在存储池创建之后,原则上需要一个文件系统入口才可被用户访问,mountpoint
即该入口。
1 | sudo zfs set mountpoint=${/PATH/OF/MOUNT_POINT}] ${POOL_NAME} |
设置了存储池的入口之后,存储池下的数据集也将以对应目录结构被自动挂载。
3.2.4 重命名数据集·
使用 zfs rename
命令可对数据集进行重命名,如
1 | $OLD_DATASET_NAME |
4. 快照相关·
4.1 创建快照·
打快照建议使用标准化命名方式,随意取名字可能会导致后期管理紊乱。
1 | sudo zfs snapshot ${POOL_NAME}/${DATASET_NAME}@$(date +"manual-%Y-%m-%d_%H-%M") |
4.2 移除快照·
过于老旧的快照会占用很多不必要的空间,及时清理不再需要的快照是个好习惯。
1 | sudo zfs destroy ${POOL_NAME}/${DATASET_NAME}@${SNAPSHOT_NAME} |
5. 数据集迁移与备份·
5.1 数据集迁移·
1 | sudo zfs send ${POOL_NAME}/${DATASET_NAME}@${SNAPSHOT_NAME} | sudo ${TARGET_POOL}/${TARGET_DATASET} |
如果接受数据流的是另一台机器,则可通过网络传输:
1 | sudo zfs send ${POOL_NAME}/${DATASET_NAME}@${SNAPSHOT_NAME} | ssh -p ${PORT} ${USERNAME}@${HOSTNAME} sudo zfs recv ${TARGET_POOL}/${TARGET_DATASET} |
5.2 查看快照与数据集之间的差异·
1 | sudo zfs diff -F ${POOL_NAME}/${DATASET_NAME}@${OLD_SNAPSHOT} ${POOL_NAME}/${DATASET_NAME}@${NEW_SNAPSHOT} | while read -r line; do echo -e "$line"; done |
总结·
ZFS 因为优秀的特性使得它在一众文件系统中独领风骚很多年,至今它都是最优秀的文件系统之一,可以说在开源方案中,ZFS 是最优秀的之一。然而,因为 Linux Kernel 和 OpenZFS 的开源许可冲突,导致两者至今不能合并,这或许也是一个开源届的损失。但是我认为,这依旧是社会契约的一种合理表现。或许在未来的某一天我们能够看到 OpenZFS 正式融入 Linux Kernel.
除此之外,本文不涉及 boot from ZFS,毕竟这还不是一个非常完善的操作。