ZFS系列(十三)共享数据集

本文继续GNU/Linux ZFS的管理系列,主要讨论共享数据集(或者叫共享文件系统)。

声明

我一直在努力让这些ZFS帖子尽可能地与操作系统无关。尽管他们倾向于Linux内核,但您应该能够将其中的大部分内容带到BSD或任何Solaris衍生产品中,如OpenIndiana或Nexenta。然而,在这篇文章中,它将是针对linux内核的,甚至是针对Ubuntu和Debian的。原因是在写这篇文章的时候iSCSI支持还没有被编译到Linux上的ZFS中,但是通过NFS和SMB共享已经支持了。此外,本文中通过NFS和SMB共享的实现细节将在是针对Debian和Ubuntu的。因此,如果你使用的是Fedora、openSUSE、Gentoo、Arch等,那么你可能需要进行调整相应的参数。

动机

您可能会问,为什么要使用ZFS特定的数据集共享,而不是使用标准软件的“可靠的”方法。原因很简单。当系统启动并完成它的服务初始化过程(通常通过执行/etc/init.d/中找到的shell脚本)时,它有一个方法来判断哪个服务先启动。笼统来说,启动过程大致是首先安装文件系统,然后启用网络,最后才启动服务。其中一些是绑定在一起的,比如NFS导出,它需要挂载文件系统、安装防火墙、启动网络和运行NFS守护进程。但是,当文件系统没有安装时,会发生什么呢?如果目录仍然可以访问,则将通过NFS导出它,应用程序可以开始将数据导出。这可能会导致各种各样的问题,比如数据不一致。因此,管理员会进行检查,比如只导出挂载点中的嵌套目录,如果文件系统挂载失败,那么嵌套目录就不会被导出。这些都是聪明的技巧,但肯定不优雅。

当将导出直接绑定到文件系统中时,您可以很好地解决这个问题,ZFS就是这么做的。例如,在ZFS中,您可以通过NFS共享特定的数据集。但是,如果数据集没有挂载,则导出对应用程序不可用,NFS客户端将会阻塞。因为网络共享是文件系统固有的,所以不需要担心数据不一致,也不需要愚蠢的检查工具或脚本。因此,Oracle的ZFS能够通过NFS、SMB (CIFS或Samba)和iSCSI共享数据集。Linux上的ZFS目前只支持NFS和SMB,即将支持iSCSI。

在每种情况下,您仍然必须安装必要的守护程序以使共享可用。例如,如果您希望通过NFS共享数据集,那么您需要安装NFS服务器软件,并且该软件必须正在运行。然后,您所需要做的就是打开数据集上的共享NFS开关,它将立即可用。

通过NFS共享

要通过NFS共享数据集,首先需要确保NFS守护进程正在运行。在Debian和Ubuntu上,这是“nfs-kernel-server”包。此外,在Debian和Ubuntu中,NFS守护进程不会启动,除非在/etc/exports文件中有导出。因此,您有两个选项:您可以创建一个虚拟的导出,仅对localhost可用,或者您可以编辑初始化脚本以启动,而不检查当前的导出。我更喜欢前者。让我们来设置一下:

1
2
3
4
5
6
$ sudo aptitude install -R nfs-kernel-server
$ echo '/mnt localhost(ro)' >> /etc/exports
$ sudo /etc/init.d/nfs-kernel-server start
$ showmount -e hostname.example.com
Export list for hostname.example.com:
/mnt localhost

在NFS守护进程运行之后,我们现在可以开始共享ZFS数据集了。我假设您已经创建了数据集,它已经挂载,并且您已经准备好开始向它提交数据了。您会注意到在zfs(8)手册中,对于“sharenfs”属性,它可以是“on”、“off”或“opts”,其中“opts”是有效的NFS导出选项。所以,如果我想共享我的“pool/srv”数据集,并将它挂载到“/srv”到10.80.86.0/24网络,我可以做一些像这样的事情:

1
2
3
4
5
6
# zfs set sharenfs="rw=@10.80.86.0/24" pool/srv
# zfs share pool/srv
# showmount -e hostname.example.com
Export list for hostname.example.com:
/srv 10.80.86.0/24
/mnt localhost

如果您希望在启动时共享ZFS数据集,那么您需要安装/etc/default/zfs配置文件。如果你使用Ubuntu PPA,默认情况下你会安装它。如果从源代码进行编译,则不会提供此选项。这是那个文件的内容。我强调了两行,如果您想要启用NFS共享,那应该修改这两行。默认的是“不”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ cat /etc/default/zfs
# /etc/default/zfs
#
# Instead of changing these default ZFS options, Debian systems should install
# the zfs-mount package, and Ubuntu systems should install the zfs-mountall
# package. The debian-zfs and ubuntu-zfs metapackages ensure a correct system
# configuration.
#
# If the system runs parallel init jobs, like upstart or systemd, then the
# `zfs mount -a` command races in a way that causes sporadic mount failures.

# Automatically run `zfs mount -a` at system start. Disabled by default.
ZFS_MOUNT='yes'
ZFS_UNMOUNT='no'

# Automatically run `zfs share -a` at system start. Disabled by default.
# Requires nfsd and/or smbd. Incompletely implemented for Linux.
ZFS_SHARE='yes'
ZFS_UNSHARE='no'

正如注释中提到的,运行并行初始化系统会给ZFS带来问题。这是我最近遇到的问题,因为我的/var/log/和/var/cache/ dataset在引导时没有挂载。为了解决这个问题,并运行串行化的启动,从而确保所有操作都按照正确的顺序执行,您需要访问一个文件:

1
# touch /etc/init.d/.legacy-bootordering

这将增加您的启动时间,但考虑到我的系统每次运行几个月,我并不担心这将为我的启动增加5秒时间,在/etc/init.d/rc脚本中设置“CONCURRENCY=none”。
现在,您应该能够从NFS客户端挂载NFS导出:

1
(client)# mount -t nfs hostname.example.com:/srv /mnt

通过SMB共享

目前,通过SMB共享遇到些问题,请参阅我在Github上报告的bug #1170

与NFS一样,要通过SMB/CIFS共享ZFS数据集,需要安装并运行守护进程。 最近Samba发布了版本4,我们将继续使用Samba包的版本3,直到版本4稳定下来(注意:这篇文章原文发表于2012年,所以此时最新的稳定版本肯定不是版本3了)。

1
2
3
4
5
# aptitude install -R aptitude install samba samba-client samba-doc samba-tools samba-doc-pdf
# ps -ef | grep smb
root 22413 1 0 09:05 ? 00:00:00 /usr/sbin/smbd -D
root 22423 22413 0 09:05 ? 00:00:00 /usr/sbin/smbd -D
root 22451 21308 0 09:06 pts/1 00:00:00 grep smb

此时,我们需要做的就是共享数据集,并验证它是否已被共享。同样值得注意的是,微软Windows机器不像Unix那样区分大小写。因此,如果您在异构环境中,禁用ZFS数据集上的区分大小写可能是值得的。只能在创建时设置此值。因此,您可能希望在创建该数据集时发出以下命令:

1
# zfs create -o casesensitivity=mixed pool/srv

现在您可以继续配置数据集的其余部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# zfs set sharesmb=on pool/srv
# zfs share pool/srv
# smbclient -U guest -N -L localhost
Domain=[WORKGROUP] OS=[Unix] Server=[Samba 3.6.6]

Sharename Type Comment
--------- ---- -------
print$ Disk Printer Drivers
sysvol Disk
netlogon Disk
IPC$ IPC IPC Service (eightyeight server)
Canon-imageRunner-3300 Printer Canon imageRunner 3300
HP-Color-LaserJet-3600 Printer HP Color LaserJet 3600
salesprinter Printer Canon ImageClass MF7460
pool_srv Disk Comment: /srv
Domain=[WORKGROUP] OS=[Unix] Server=[Samba 3.6.6]

Server Comment
--------- -------
EIGHTYEIGHT eightyeight server

Workgroup Master
--------- -------
WORKGROUP EIGHTYEIGHT

您可以看到,在这个环境中(我的工作站主机名是’ eightyeight ‘),有一些打印机被共享,还有一些磁盘。我强调了我们在输出中共享的磁盘,以验证它是否正常工作。因此,我们应该能够将该共享挂载为CIFS挂载,并访问数据:

1
2
3
4
# aptitude install -R cifs-utils
# mount -t cifs -o username=USERNAME //localhost/srv /mnt
# ls /mnt
foo

通过iSCSI共享

不幸的是,Linux上的ZFS还不支持通过iSCSI共享ZFS数据集。然而,它在上游的Illumos源代码中是可用的,并且正在努力使它在GNU/Linux中工作。与SMB和NFS一样,您将需要安装并运行iSCSI守护进程。当启用支持后,我将通过这篇文章演示如何访问作为ZFS数据集的iSCSI目标。在此期间,您可以做如下操作:

1
2
# aptitude install -R openiscsi
# zfs set shareiscsi=on pool/srv

然后从iSCSI客户端,您将访问目标,格式化它,挂载它,并开始处理数据。

参考资料

https://pthree.org/2012/12/31/zfs-administration-part-xv-iscsi-nfs-and-samba/

如果你觉得本文对你有帮助,欢迎打赏