在纯ZFS安装Gentoo Linux

其他Linux/Unix/BSD/OSX等发行版讨论
回复
头像
woodelf
帖子: 166
注册时间: 2010-05-25 10:26
系统: FreeBSD 9.1 amd64
送出感谢: 0
接收感谢: 4 次

在纯ZFS安装Gentoo Linux

#1

帖子 woodelf » 2012-09-06 9:39

关于ZFS文件系统,不多做介绍,在这里有详细信息:http://zh.wikipedia.org/wiki/ZFS

虽然ZFS本身开源,但是由于ZFS的CDDL许可证和Linux的GPL许可证并不兼容,因此ZFS无法进入Linux内核。尽管如此,并不代表我们就不能在纯ZFS的/安装Linux。本人最近就一直在研究ZFS on Linux,今天才顺利安装启动,特把教程分享如下。

注意:目前能安装到ZFS的发行版不多,只有Ubuntu,Gentoo和Arch等有限的几种。经过我的测试,个人认为Gentoo是最方便安装到ZFS的,Ubuntu需要进行debootstrap,而且由于教程步骤有点问题,到后面pid 1会占用/mnt/dev,导致无法卸载/mnt/dev,步骤无法进行下去。本文仅以amd64为例,i386未测试。

内存要求:至少2GB,最好是能达到8GB。ZFS吃内存很厉害。

本文主体内容来自:https://github.com/ryao/zfs-overlay,感谢ryao的贡献。本人主要负责资料整理和步骤完善。

安装介质准备:
推荐使用Gentoo LiveDVD 2012.1,可以写入U盘启动,因为这个ISO包含了ZFS模块。

硬盘分区要求:
GPT分区表,分出32MB的BIOS boot partition(事实上应该1MB就足够了),另外的部分随便分一个分区,文件系统随意,准备给ZFS用。
以我的为例,我的BIOS boot partition在/dev/sdb3,ZFS在/dev/sdb2。

安装步骤:
启动Gentoo LiveDVD 2012.1

创建zpool

代码: 全选

zpool create -f -o ashift=12 -o cachefile= -O normalization=formD -m none -R /mnt/gentoo rpool /dev/sdb2
创建rootfs

代码: 全选

zfs create -o mountpoint=none rpool/ROOT
zfs create -o mountpoint=/ rpool/ROOT/gentoo
创建home目录

代码: 全选

zfs create -o mountpoint=/home rpool/HOME
创建portage目录

代码: 全选

zfs create -o mountpoint=none rpool/GENTOO
zfs create -o mountpoint=/usr/portage rpool/GENTOO/portage
zfs create -o mountpoint=/usr/portage/distfiles rpool/GENTOO/distfiles
建立packages目录(可选)

代码: 全选

zfs create -o mountpoint=/usr/portage/packages rpool/GENTOO/packages
建立ccache目录(可选)

代码: 全选

zfs create -o mountpoint=/var/tmp/ccache -o compression=gzip-9 rpool/GENTOO/ccache
下载stage3

代码: 全选

wget ftp://gentoo.osuosl.org/pub/gentoo/releases/amd64/current-stage3/stage3-amd64-*.tar.bz2
解压stage3

代码: 全选

tar -xf stage3-amd64-*.tar.bz2 -C /mnt/gentoo
把zpool.cache复制到目标ZFS分区

代码: 全选

mkdir -p /mnt/gentoo/etc/zfs
cp /etc/zfs/zpool.cache /mnt/gentoo/etc/zfs/zpool.cache
把resolv.conf复制到目标ZFS分区

代码: 全选

cp /etc/resolv.conf /mnt/gentoo/etc/resolv.conf
挂载必要的文件系统

代码: 全选

mount -t proc none /mnt/gentoo/proc
mount --rbind /dev /mnt/gentoo/dev
mount --rbind /sys /mnt/gentoo/sys
chroot

代码: 全选

chroot /mnt/gentoo /bin/bash
env-update; source /etc/profile; export PS1="(chroot) $PS1"; cd
同步portage

代码: 全选

emerge --sync
由于Gentoo的stage3相当老旧,最好先emerge -avuDN world,把所有包升级一遍,有几个软件冲突也要处理一下。
安装genkernel(最好在/etc/make.conf设置ACCEPT_KEYWORDS="~amd64")

代码: 全选

emerge sys-kernel/genkernel
安装内核源代码

代码: 全选

emerge sys-kernel/gentoo-sources
安装完内核源代码之后,请到/usr/src/linux按照自己的硬件配置内核,推荐把驱动编入内核,而不是编为模块。
初步安装内核(sys-kernel/spl和sys-fs/zfs会检查内核文件)

代码: 全选

genkernel kernel --no-clean --no-mountboot
安装layman

代码: 全选

emerge app-portage/layman
安装ZFS

代码: 全选

emerge sys-fs/zfs
把ZFS添加到boot运行级

代码: 全选

rc-update add zfs boot
把zfs-shutdown添加到shutdown运行级

代码: 全选

rc-update add zfs-shutdown shutdown
安装grub2

代码: 全选

echo "sys-boot/grub libzfs" >> /etc/portage/package.use
env FEATURES='-sandbox -usersandbox' emerge sys-boot/grub:2
touch /etc/mtab
grub2-install /dev/sdb
grub2-mkconfig -o /boot/grub2/grub.cfg
安装module-rebuild

代码: 全选

emerge module-rebuild
编译内核和initramfs

代码: 全选

genkernel all --no-clean --no-mountboot --zfs --bootloader=grub2 --callback="module-rebuild rebuild"
之后把/etc/fstab里面的BOOT,ROOT和SWAP行都注释掉
然后按照Gentoo手册的8-12章节做最后的系统配置:http://www.gentoo.org/doc/en/handbook/
启动进入新系统之后,可以先做个快照

代码: 全选

zfs snapshot rpool/ROOT/gentoo@install
另外,记得做一下/etc/mtab的链接

代码: 全选

ln -sf /proc/mounts /etc/mtab
在ZFS卷组内创建swap(实验性的)

代码: 全选

zfs create -o sync=always -o primarycache=metadata -o secondarycache=none -V 8G rpool/swap
mkswap -f /dev/zvol/rpool/swap
然后配置下/etc/fstab

代码: 全选

echo "/dev/zvol/rpool/swap    none    swap    sw    0 0" >> /etc/fstab
由于在ZFS卷组内创建swap尚未有良好支持,最好还是创建一个独立的swap分区。
基本系统到此安装完毕,后续的软件和设置可以自行参照Gentoo的wiki和文档。
安装完成以后的情况:
1.png
2.png
Tips:
ZFS采用ARC来管理其pool的cache,所以会尝试使用所有可用物理内存,内存占用看着就很恐怖,但并不会影响正常使用。可以通过限制ARC大小的方法来解决

代码: 全选

echo "options zfs zfs_arc_max=512M" >> /etc/modprobe.d/zfs.conf
使用效果:
3.png
上次由 woodelf 在 2012-11-14 19:31,总共编辑 9 次。
这些用户感谢了作者 woodelf 于这个帖子:
aduser (2012-09-06 20:39)
评价: 3.7%
/dev/ada1:Gentoo Linux+ZFS (GPT)
/dev/ada2:FreeBSD 9.1+ZFS (GPT)
晨★梦一柯南
帖子: 335
注册时间: 2010-12-28 17:03
送出感谢: 1 次
接收感谢: 4 次

Re: 在纯ZFS安装Gentoo Linux

#2

帖子 晨★梦一柯南 » 2012-09-06 10:28

:em11 mark
头像
woodelf
帖子: 166
注册时间: 2010-05-25 10:26
系统: FreeBSD 9.1 amd64
送出感谢: 0
接收感谢: 4 次

Re: 在纯ZFS安装Gentoo Linux

#4

帖子 woodelf » 2012-09-06 13:57

photor 写了:那么耗资源,有意义吗? :em09
zfs使用ARC算法管理其pool的cache,他会尝试使用所有可用内存。但是其实是不会影响正常进程的内存使用的。可以看这里的介绍(包括了如何限制ARC的大小):
http://www.solarisinternals.com/wiki/in ... ning_Guide
/dev/ada1:Gentoo Linux+ZFS (GPT)
/dev/ada2:FreeBSD 9.1+ZFS (GPT)
axlrose
帖子: 69
注册时间: 2007-02-11 15:58
送出感谢: 0
接收感谢: 0

Re: 在纯ZFS安装Gentoo Linux

#5

帖子 axlrose » 2012-09-19 21:27

好文章,准备在archlinux下试试
jtshs256
帖子: 22323
注册时间: 2010-07-19 21:41
系统: OS X
送出感谢: 2 次
接收感谢: 27 次

Re: 在纯ZFS安装Gentoo Linux

#6

帖子 jtshs256 » 2012-09-19 21:35

这个可以顶
躺平
neko1990
帖子: 7
注册时间: 2010-01-30 8:34
系统: Gentoo
送出感谢: 0
接收感谢: 0

Re: 在纯ZFS安装Gentoo Linux

#7

帖子 neko1990 » 2012-11-13 23:14

图片

按照这个步骤安装成功
在学校实验室的机子里装的,2G内存,一块300GHDD硬盘,由于它是nvidia的显卡,那驱动还不会装,桌面暂时跑不起来

「另外自己的笔记本SSD(一块toshiba 128G)上也做成了ZFS,把已有的gentoo(500G HDD上)拷贝过去,然后不能启动,卡在initramfs上。本子上是这么分区的(分区对齐到1MiB,zpool设置的块大小是4k):

代码: 全选

[root@Planetarian neko1990]# zfs list
NAME                   USED  AVAIL  REFER  MOUNTPOINT
zpool                 30.9G  78.4G   136K  none
zpool/GENTOO          21.4G  78.4G   136K  /mnt/gentoo
zpool/GENTOO/ROOT     19.6G  78.4G  19.4G  /mnt/gentoo
zpool/GENTOO/ccache    921M  78.4G   921M  /mnt/gentoo/var/tmp/ccache
zpool/GENTOO/portage   893M  78.4G   893M  /mnt/gentoo/usr/portage
zpool/HOME            9.44G  78.4G  9.44G  /mnt/gentoo/home


有一个问题:是不是zfs处理小文件的性能很差?
在同步/usr/portage文件夹时速度 非!常!慢!,看屏幕输出的信息,应该是一连写入了很多文件,暂停一会,在写很多文件、暂停会儿。
我试过解压portage-lastest包、用内网的rsync服务器,那写入速率都非常糟糕。
在笔记本上拷贝的时候也是忍受着各种慢,
后来把atime,速度有所提升(看编译的时候速度快了),但没有具体测试。
头像
woodelf
帖子: 166
注册时间: 2010-05-25 10:26
系统: FreeBSD 9.1 amd64
送出感谢: 0
接收感谢: 4 次

Re: 在纯ZFS安装Gentoo Linux

#8

帖子 woodelf » 2012-11-14 19:29

neko1990 写了:图片

按照这个步骤安装成功
在学校实验室的机子里装的,2G内存,一块300GHDD硬盘,由于它是nvidia的显卡,那驱动还不会装,桌面暂时跑不起来

「另外自己的笔记本SSD(一块toshiba 128G)上也做成了ZFS,把已有的gentoo(500G HDD上)拷贝过去,然后不能启动,卡在initramfs上。本子上是这么分区的(分区对齐到1MiB,zpool设置的块大小是4k):

代码: 全选

[root@Planetarian neko1990]# zfs list
NAME                   USED  AVAIL  REFER  MOUNTPOINT
zpool                 30.9G  78.4G   136K  none
zpool/GENTOO          21.4G  78.4G   136K  /mnt/gentoo
zpool/GENTOO/ROOT     19.6G  78.4G  19.4G  /mnt/gentoo
zpool/GENTOO/ccache    921M  78.4G   921M  /mnt/gentoo/var/tmp/ccache
zpool/GENTOO/portage   893M  78.4G   893M  /mnt/gentoo/usr/portage
zpool/HOME            9.44G  78.4G  9.44G  /mnt/gentoo/home


有一个问题:是不是zfs处理小文件的性能很差?
在同步/usr/portage文件夹时速度 非!常!慢!,看屏幕输出的信息,应该是一连写入了很多文件,暂停一会,在写很多文件、暂停会儿。
我试过解压portage-lastest包、用内网的rsync服务器,那写入速率都非常糟糕。
在笔记本上拷贝的时候也是忍受着各种慢,
后来把atime,速度有所提升(看编译的时候速度快了),但没有具体测试。
注意你的分区结构,是否和源机器的分区完全一致。实在不行的话,chroot过去重新编译下内核和initramfs就行了。
我曾经用IOzone对比测试过Linux原生ZFS和btrfs的性能,结果是,当数据块小于32KB,btrfs具有明显的I/O优势,但是一旦数据块大于等于32KB,ZFS完爆btrfs。ZFS对小文件确实不在行。
注意,SSD必须指定ashift=12,否则性能大打折扣。
不过话说回来,我倒没觉得ZFS很慢,没有你说的现象。有条件的话,做个RAIDz吧,可以带来一定的性能提升。
/dev/ada1:Gentoo Linux+ZFS (GPT)
/dev/ada2:FreeBSD 9.1+ZFS (GPT)
neko1990
帖子: 7
注册时间: 2010-01-30 8:34
系统: Gentoo
送出感谢: 0
接收感谢: 0

Re: 在纯ZFS安装Gentoo Linux

#9

帖子 neko1990 » 2012-11-14 23:52

IO测试是这个帖子吧====>[讨论] btrfs和Linux原生ZFS性能对比

出现上面的情况我找到原因了。。。从旧的gentoo系统读取小文件速度太慢了
作了三个测试,1:把原gentoo的/usr/portage拷到内存(无distfiles)2:在zfs里解压portage-lastest,3:把内存中的portage拷入zfs
分别用时:6分40秒 、1分28秒 、50秒
图片

解压时候看得iostat:
图片


之前的系统里没有用到initramfs,没用到genkernal,正在研究中。。。
头像
woodelf
帖子: 166
注册时间: 2010-05-25 10:26
系统: FreeBSD 9.1 amd64
送出感谢: 0
接收感谢: 4 次

Re: 在纯ZFS安装Gentoo Linux

#10

帖子 woodelf » 2012-11-15 0:10

neko1990 写了:IO测试是这个帖子吧====>[讨论] btrfs和Linux原生ZFS性能对比

出现上面的情况我找到原因了。。。从旧的gentoo系统读取小文件速度太慢了
作了三个测试,1:把原gentoo的/usr/portage拷到内存(无distfiles)2:在zfs里解压portage-lastest,3:把内存中的portage拷入zfs
分别用时:6分40秒 、1分28秒 、50秒
图片

解压时候看得iostat:
图片


之前的系统里没有用到initramfs,没用到genkernal,正在研究中。。。
如果不把ZFS作为/,自然不需要initramfs,但是要从原生ZFS启动Linux,必须有initramfs。Richard Yao解释过这个问题,原生ZFS必须在内核先加载的情况下才能加载,而如果没有加载ZFS,/根本就挂不上去。这有点类似鸡与蛋的问题,我试过,即使把ZFS补丁编入内核也不行,因此在这里必须借助initramfs来提供临时/环境以便加载ZFS模块,挂载/文件系统。
/dev/ada1:Gentoo Linux+ZFS (GPT)
/dev/ada2:FreeBSD 9.1+ZFS (GPT)
neko1990
帖子: 7
注册时间: 2010-01-30 8:34
系统: Gentoo
送出感谢: 0
接收感谢: 0

Re: 在纯ZFS安装Gentoo Linux

#11

帖子 neko1990 » 2012-11-15 10:05

断网以后重做了initramfs,找到了出错原因
我是以/dev/sda上的gentoo作为宿主系统给/dev/sdb(SSD)分区、格式化,并在sdb里写了了grub2
安装好后我把原先的/dev/sda拿掉,然后zpool就不能加载了,显示是UNAVAIL,它试图从/dev/sdb里寻找zfs分区,但是现在变成了/dev/sda

我想这个问题也会出现在把gento-livedvd写入U盘装系统的情况,udev会把这些设备作为/dev/sda;但不会出现在刻盘安装的情况
头像
woodelf
帖子: 166
注册时间: 2010-05-25 10:26
系统: FreeBSD 9.1 amd64
送出感谢: 0
接收感谢: 4 次

Re: 在纯ZFS安装Gentoo Linux

#12

帖子 woodelf » 2012-11-15 11:16

neko1990 写了:断网以后重做了initramfs,找到了出错原因
我是以/dev/sda上的gentoo作为宿主系统给/dev/sdb(SSD)分区、格式化,并在sdb里写了了grub2
安装好后我把原先的/dev/sda拿掉,然后zpool就不能加载了,显示是UNAVAIL,它试图从/dev/sdb里寻找zfs分区,但是现在变成了/dev/sda

我想这个问题也会出现在把gento-livedvd写入U盘装系统的情况,udev会把这些设备作为/dev/sda;但不会出现在刻盘安装的情况
你的方法有误,既然知道设备名要产生变化,就不应该采用设备名来创建zpool,而应该给分区打上label,以label名来创建zpool,或者采用分区GUID来创建。因为以设备名来区分分区是很不安全的方式,很多发行版都不推荐这么做,而应该采用label或者GUID。
比如说我要挂载/dev/sda作为宿主,在/dev/sdb2创建zpool,之后再移除/dev/sda,那么先给/dev/sdb2创建一个label(我记得gdisk就有这功能,自己找找),然后再

代码: 全选

zpool create -f -o ashift=12 -o cachefile= -O normalization=formD -m none -R /mnt/gentoo rpool /dev/YOUR_LABEL_PATH
或者

代码: 全选

zpool create -f -o ashift=12 -o cachefile= -O normalization=formD -m none -R /mnt/gentoo rpool /dev/YOUR_GUID_PATH
Grub的部分倒是问题不大,它会自动根据分区GUID来搜索内核,生成菜单。
/dev/ada1:Gentoo Linux+ZFS (GPT)
/dev/ada2:FreeBSD 9.1+ZFS (GPT)
neko1990
帖子: 7
注册时间: 2010-01-30 8:34
系统: Gentoo
送出感谢: 0
接收感谢: 0

Re: 在纯ZFS安装Gentoo Linux

#13

帖子 neko1990 » 2012-11-15 20:21

关机前把zpool export掉,再在开机initramfs期间import进来,zpool就能够正常挂载
但是每次关机(halt或reboot)shutdown运行级别里的几个脚本(killprocs、savecache、mount-ro、zfs-shutdown)没执行。在宿主系统里都是执行的。
我修改了init脚本,让它强行挂载

代码: 全选

/sbin/zpool export zpool
/sbin/zpool import -f zpool
/sbin/zfs mount zpool/GENTOO/ROOT

....
exec switch_root /mnt/gentoo /sbin/init
能使用,不过有缺陷,对openrc的机制还不是很了解,暂时搁这儿

图片
我们mountpoint起点不一样......

还有上面我犯了个错误:sd[a..z]这些名字是内核分配的,udev只是动态维护了一个/sys到/dev里的一个映射
头像
woodelf
帖子: 166
注册时间: 2010-05-25 10:26
系统: FreeBSD 9.1 amd64
送出感谢: 0
接收感谢: 4 次

Re: 在纯ZFS安装Gentoo Linux

#14

帖子 woodelf » 2012-11-15 22:36

neko1990 写了:关机前把zpool export掉,再在开机initramfs期间import进来,zpool就能够正常挂载
但是每次关机(halt或reboot)shutdown运行级别里的几个脚本(killprocs、savecache、mount-ro、zfs-shutdown)没执行。在宿主系统里都是执行的。
我修改了init脚本,让它强行挂载

代码: 全选

/sbin/zpool export zpool
/sbin/zpool import -f zpool
/sbin/zfs mount zpool/GENTOO/ROOT

....
exec switch_root /mnt/gentoo /sbin/init
能使用,不过有缺陷,对openrc的机制还不是很了解,暂时搁这儿

图片
我们mountpoint起点不一样......

还有上面我犯了个错误:sd[a..z]这些名字是内核分配的,udev只是动态维护了一个/sys到/dev里的一个映射
找个带ZFS模块的LiveCD,先导入你的zpool:

代码: 全选

zpool import -fN zpool
然后修正挂载点:

代码: 全选

zfs set mountpoint=/ zpool/GENTOO/ROOT
zfs set mountpoint=/var/tmp/ccache zpool/GENTOO/ccache
zfs set mountpoint=/usr/portage zpool/GENTOO/portage
zfs set mountpoint=/home zpool/HOME
善意提醒下,最好不要直接把zpool命名为zpool,以免引起不必要的混淆。
关机时候确实会提示/和/home无法卸载,设备忙,Richard Yao也有说明,是因为ZFS的集成度做得很不够好,不影响使用。
不过感觉Richard Yao的这个教程把zfs的dataset分得过于复杂了,虽然我知道他是按照Solaris 11的结构去分的。我在FreeBSD只有三个主要的dataset,tank/home,tank/usr和tank/var,其他dataset都是这三个的子目录。
/dev/ada1:Gentoo Linux+ZFS (GPT)
/dev/ada2:FreeBSD 9.1+ZFS (GPT)
回复