Gentoo上运行ZFS¶
安装¶
ZFSOnLinux项目 提供了out-of-tree Linux内核模块。从ZFS模块版本 0.6.1 开始,OpenZFS项目宣布将ZFS视为可以广泛用于桌面到超级计算机的生产部署。
安装ZFS:
emerge --ask sys-fs/zfs
安装完成后提示信息:
* Messages for package sys-fs/zfs-kmod-2.2.2:
* You have virtual/dist-kernel installed, but
* USE="dist-kernel" is not enabled for sys-fs/zfs-kmod
* It's recommended to globally enable dist-kernel USE flag
* to auto-trigger initrd rebuilds with kernel updates
* Messages for package sys-fs/zfs-2.2.2-r1:
* You have virtual/dist-kernel installed, but
* USE="dist-kernel" is not enabled for sys-fs/zfs
* It's recommended to globally enable dist-kernel USE flag
* to auto-trigger initrd rebuilds with kernel updates
* Messages for package sys-fs/zfs-kmod-2.2.2:
* This version of OpenZFS includes support for new feature flags
* that are incompatible with previous versions. GRUB2 support for
* /boot with the new feature flags is not yet available.
* Do *NOT* upgrade root pools to use the new feature flags.
* Any new pools will be created with the new feature flags by default
* and will not be compatible with older versions of OpenZFS. To
* create a new pool that is backward compatible wih GRUB2, use
*
* zpool create -o compatibility=grub2 ...
*
* Refer to /usr/share/zfs/compatibility.d/grub2 for list of features
警告
每次内核编译之后,都需要重新 emerge sys-fs/zfs-kmod
,即使内核修改是微不足道的。如果你在merge了内核模块之后重新编译内核,则可能会是的zpool进入不可中断的睡眠(也就是不能杀死的进程)或者直接crash。
在内核变更之后,执行以下命令重新 remerge zfs-kmod :
emerge -va @module-rebuild
输出信息类似:
...
Calculating dependencies... done!
Dependency resolution took 1.73 s (backtrack: 0/20).
[ebuild R ] sys-fs/zfs-kmod-2.1.14:0/2.1.14::gentoo USE="dist-kernel-cap rootfs strip -custom-cflags -debug -dist-kernel -modules-sign -verify-sig" 0 KiB
Total: 1 package (1 reinstall), Size of downloads: 0 KiB
Would you like to merge these packages? [Yes/No]
ZFS Event Daemon通知¶
ZED(ZFS Event Daemon)监控ZFS内核模块产生的事件: 当一个 zevent
(ZFS Event)发出是,ZED将为对应的zevent分类运行一个 ZEDLETs
(ZFS Event Daemon Linkage for Executable Tasks)。
配置
/etc/zfs/zed.d/zed.rc
:
##
# Email address of the zpool administrator for receipt of notifications;
# multiple addresses can be specified if they are delimited by whitespace.
# Email will only be sent if ZED_EMAIL_ADDR is defined.
# Enabled by default; comment to disable.
#
ZED_EMAIL_ADDR="admin@example.com"
##
# Notification verbosity.
# If set to 0, suppress notification if the pool is healthy.
# If set to 1, send notification regardless of pool health.
#
ZED_NOTIFY_VERBOSE=1
OpenRC¶
配置 openrc 设置ZFS在操作系统启动时启动:
# 多数情况下只需要配置 zfs-import 和 zfs-mount
rc-update add zfs-import boot
rc-update add zfs-mount boot
# zfs-share 是提供NFS共享
rc-update add zfs-share default
# zfs-zed 是ZFS Event Daemon用于处理磁盘hotspares替换以及故障的电子邮件通知
rc-update add zfs-zed default
备注
多数情况下只需要配置 zfs-import 和 zfs-mount
zfs-share 是提供NFS共享
zfs-zed 是ZFS Event Daemon用于处理磁盘hotspares替换以及故障的电子邮件通知
Systemd¶
如果系统使用 Systemd进程管理器 则配置如下:
systemctl enable zfs.target
systemctl start zfs.target
systemctl enable zfs-import-cache
systemctl enable zfs-mount
systemctl enable zfs-import.target
内核¶
sys-fs/zfs
需要内核支持 zlib
:
Cryptographic API --->
Compression --->
<*> Deflate
备注
内核更改必须重新编译内核模块
如果使用clang来编译 sys-fs/zfs-kmod
则必须使用 2.1.7 以上版本
安装内核模块(前面安装 zfs 已经包括):
emerge --ask sys-fs/zfs-kmod
如果使用 initramfs
,则需要在编译模块以后重新生成initramfs
如果服务器没有重启过,可能需要手工夹在
zfs
内核模块:
/sbin/modprobe zfs
使用¶
磁盘分区:
这里的案例是 在MacBook Pro上安装Gentoo Linux ,磁盘已经划分了 sda1
(/boot) 和 sda2
(/) ,现在将剩余空间都作为ZFS分区:
# 已经划分了 sda1 和 sda2 ,用掉了21G,所以这里从 21GB开始到100%
parted -a optimal /dev/sda mkpart primary 21GB 100%
# 为磁盘分区3命名
parted /dev/sda name 3 zpool-data
# 最后显示输出磁盘分区信息
parted /dev/sda print
划分好以后,最后输出的分区信息:
Model: ATA APPLE SSD SD0128 (scsi)
Disk /dev/sda: 121GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:
Number Start End Size File system Name Flags
1 1049kB 256MB 255MB fat32 ESP boot, esp
2 256MB 21.0GB 20.7GB xfs rootfs
3 21.0GB 121GB 100GB zpool-data
( 仅供参考
请不要执行这步
)如果是常规使用,通常可以使用类似 ZFS快速起步(zcloud) 方法(注意那个案例使用的是整块sda磁盘,和这里的案例磁盘分区/dev/sda3
不同,注意区别):
zpool create zpool-data sda
# 设置了从zpool的根开始激活压缩
zfs set compression=lz4 zpool-data
我在 在MacBook Pro上安装Gentoo Linux 计划使用一个ZFS文件系统来作为 Docker ZFS 存储驱动 (需要将整个 zpool 存储池挂载到独立的
/var/lib/docker/
目录) ,所以我实际创建名为zpool-docker
存储池:
# 在 /dev/sda3 分区创建zpool
sudo zpool create -f zpool-docker -m /var/lib/docker /dev/sda3
# 存储池开启压缩,2015年后openzfs默认压缩算法LZ4,这里明确设置lz4
sudo zfs set compression=lz4 zpool-docker
完成以后检查 zpool list
可以看到新创建的 zpool-docker
存储池:
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
zpool-docker 93G 588K 93.0G - - 0% 0% 1.00x ONLINE -
再检查 zfs list
可以看到这个存储池 zpool-docker
被挂载到 /var/lib/docker
(通过 df -h
也能看到):
NAME USED AVAIL REFER MOUNTPOINT
zpool-docker 492K 90.1G 96K /var/lib/docker
一切就绪,现在可以执行 Gentoo Docker 部署了
子卷配置¶
我的 MacBook Air 13” Mid 2013 内置存储空间有限(128G),所以我在 在MacBook Pro上安装Gentoo Linux ( MacBook Air 13” Mid 2013 ),为操作系统分配了很小的分区(20G):
Model: ATA APPLE SSD SD0128 (scsi)
Disk /dev/sda: 121GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:
Number Start End Size File system Name Flags
1 1049kB 256MB 255MB fat32 ESP boot, esp
2 256MB 21.0GB 20.7GB xfs rootfs
3 21.0GB 121GB 100GB zpool-data
虽然 rootfs
精简能够空出更多宝贵的磁盘空间给数据盘,但是Gentoo的编译需要很大的空间,特别是 Gentoo内核编译 。所以我在上文的 zpool-docker
存储池中划分出一些子卷给特定的数据目录 – 通过 排查磁盘空间消耗 找到最消耗空间目录:
/var/cache
/var/tmp
/usr/src
Gentoo 虚拟化 libvirt
/var/lib/libvirt
将需要迁移的目录先重命名(添加
.bak
后缀),然后创建对应的 ZFS 子卷 指定 ZFS挂载 到对应目录下,最后使用tar
命令迁移数据,并清理掉无用数据释放空间:
# 重命名需要迁移的数据目录
mv /var/cache /var/cache.bak
mv /var/tmp /var/tmp.bak
mv /usr/src /usr/src.bak
mv /var/lib/libvirt /var/lib/libvirt.bak
# 创建ZFS存储卷的子卷,挂载到相应目录
zfs create -o mountpoint=/var/cache zpool-docker/var-cache
zfs create -o mountpoint=/var/tmp zpool-docker/var-tmp
zfs create -o mountpoint=/usr/src zpool-docker/usr-src
zfs create -o mountpoint=/var/lib/libvirt zpool-docker/var-lib-libvirt
# 数据迁移
(cd /var/cache.bak && tar cf - .)|(cd /var/cache && tar xf -)
(cd /var/tmp.bak && tar cf - .)|(cd /var/tmp && tar xf -)
(cd /usr/src.bak && tar cf - .)|(cd /usr/src && tar xf -)
(cd /var/lib/libvirt.bak && tar cf - .)|(cd /var/lib/libvirt && tar xf -)
# 清理无用数据
rm -rf /var/cache.bak
rm -rf /var/tmp.bak
rm -rf /usr/src.bak
rm -rf /var/lib/libivrt.bak