ZFS只是共享存储的基础,最终还是需要通过nfs、smb/cifs、iscsi和fc提供给其它主机使用。本文仅涉及nfs。

术语

Table 1. 主机及用户角色
主机名 OS 角色 user/uid group/gid

storage1

OmniOS

NFS Server

alice/500

alice/500

bob/501

bob/501

shareuser/60000

sharegroup/60000

proxmox

proxmox

NFS Client

alice/500

alice/500

bob/501

bob/501

shareuser/60000

sharegroup/60000

share-point

nfs server中的共享目录,在本文中是/tank2/software/sharedir

mount-point

nfs client中的挂载点,在本文中是/mnt/dir.alice/mnt/dir.bob/mnt/sharedir

  • 分别在omnios和proxmox中添加两个账号

    $ pfexec zfs create rpool/export/home/alice
    $ pfexec zfs create rpool/export/home/bob
    $ pfexec groupadd -g 500 alice
    $ pfexec groupadd -g 501 bob
    $ pfexec useradd -u 500 -g alice -s /bin/bash -d /rpool/export/home/alice -c "alice" -m alice
    $ pfexec useradd -u 501 -g alice -s /bin/bash -d /rpool/export/home/bob -c "alice" -m bob
  • 在omnios中创建两个nfs共享

    $ pfexec zfs create tank2/software/alice
    $ pfexec chgrp alice /tank2/software/alice
    $ pfexec chmod g+rwx /tank2/software/alice
    $ pfexec zfs set sharenfs=on /tank2/software/alice
    $ pfexec sharemgr set -P nfs -S sys -p rw="*" tank2/software/alice
    
    $ pfexec zfs create tank2/software/bob
    $ pfexec chgrp bob /tank2/software/bob
    $ pfexec chmod g+rwx /tank2/software/bob
    $ pfexec zfs set sharenfs=on /tank2/software/bob
    $ pfexec sharemgr set -P nfs tank2/software/bob
  • 检查nfs共享信息

    $ pfexec sharemgr show -vp
    default nfs=()
    zfs nfs=() smb=()
        zfs/tank2/software/alice nfs=() nfs:sys=(rw="*")
              /tank2/software/alice
        zfs/tank2/software/bob nfs=()
  • 在proxmox中创建两个目录并分别mount

    $ sudo mkdir /mnt/dir.alice && chown alice.alice /mnt/dir.alice
    $ sudo mkdir /mnt/dir.bob && chown bob.bob /mnt/dir.bob
    
    $ sudo mount -t nfs storage1:/tank2/software/alice /mnt/dir.alice
    $ sudo mount -t nfs storage1:/tank2/software/bob /mnt/dir.bob
  • 检查mount-point的信息

$ ls -ltr
drwxr-xr-x  6 root     root     4.0K Sep 12 23:58 .
drwxr-xr-x 23 root     root     4.0K Jul 23 20:21 ..
drwxr-xr-x  2 alice  alice     3 Sep 12 23:59 dir.alice (1)
drwxr-xr-x  2 bob    bob    2 Sep 12 23:52 dir.bob (2)
drwxr-xr-x  2 root     root     4.0K Jul 23 18:40 tmp
drwxr-xr-x  2 root     root     4.0K Sep  6 22:48 vm
1 mount后,属主正常显示为alice
2 mount后,属主正常显示为bob

测试

使用alice账号登陆proxmox,对mount-point(/mnt/dir.alice)可以执行文件的读、写、删除,目录的创建和删除等操作。bob账号同样。

该测试表明:

  1. nfs server是否设置nfs:sys=(rw="*")对于mount-point中的读写权限并无影响。

  2. idmapd通过omnios中的zfs owner来映射mountpoint中的owner

权限问题

我使用proxmox挂载OmniOS中的nfs共享时,遇到权限的问题。现阶段,解决权限问题的关键是nfs server和nfs client需添加相同uid/gid的组和账号。

NFSv4使用一个辅助程序来映射用户名和uid,该辅助程序在不同的OS中,名字也不一样。

OS idmapd辅助程序

OpenSolaris*

nfsmapid

Ubuntu

rpc.idmapd

FreeBSD

nfsuserd

两边的idmapd会比对各自的域名,假如域名不一致,则nfs client所挂载的mount-point属主则为nobody/nogroup

所以,当发生权限问题时,首先要检查两边的idmapd的配置。下面详细介绍nfs的配置和权限的实验过程。

nfs server(OmniOS)的idmap(nfsmapid)配置

$ pfexec vim /etc/hosts

$ pfexec sharectl set nfsmapdid_domain=jklab.qmcc
$ pfexec svcadm retart svc:network/nfs/mapid:default

现在都需要通过sharectl来对nfs进行配置,通过修改/etc/default/nfs配置文件的设置方式已经弃用。

linux client(proxmox)的idmap(nfs.idmapd)配置

$ sudo vim /etc/idmapd.conf
Domain=jklab.qmcc

$ sudo vim /etc/default/nfs-common
[General]
NEED_IDMAPD=yes
...
  • 重启nfs服务

    $ sudo systemctl restart nfs-common
    $ sudo systemctl status nfs-common
    alice@pmx2:/etc/default$ sudo systemctl status nfs-common
    ● nfs-common.service - LSB: NFS support files common to client and server
       Loaded: loaded (/etc/init.d/nfs-common)
       Active: active (running) since Mon 2016-09-12 23:54:34 CST; 8h ago
      Process: 2306 ExecStop=/etc/init.d/nfs-common stop (code=exited, status=0/SUCCESS)
      Process: 2315 ExecStart=/etc/init.d/nfs-common start (code=exited, status=0/SUCCESS)
       CGroup: /system.slice/nfs-common.service
               ├─2323 /sbin/rpc.statd
               └─2335 /usr/sbin/rpc.idmapd
    
    Sep 12 23:54:34 pmx2 rpc.statd[2323]: Version 1.2.8 starting
    Sep 12 23:54:34 pmx2 nfs-common[2315]: Starting NFS common utilities: statd idmapd.
  • 打开log

    $ sudo vim /etc/idmapd.conf
    [General]
    Verbosity = 3
    ...
    
    $ sudo journalctl -f | grep rpc.idmapd
  • 以alice账号登陆后

    $ sudo mount -t nfs storage1:/tank2/software/bob /mnt/bob
    $ cd /mnt/bob
    $ touch bob.test
    touch: cannot touch ‘bob.test’: Permission denied

说明文件的权限是通过文件的标识位来控制的,但是究竟是以nfs server还是以nfs client的uid/gid来控制呢?

nfs server
$ pfexec chmod A+user:alice:read_data/write_data:allow bob.test
nfs client
alice@pmx2:/mnt/dir.bob$ echo "add line by alice" >> bob.test
alice@pmx2:/mnt/dir.bob$ cat bob.test
add line by alice

说明在nfs client中对mount-point进行操作时,是以nfs server中的uid/gid,甚至是nfsv4 acl来控制share-point中的文件权限。那如何保证nfs client可以读写nfs server中的文件和目录?简言之,要求mount-point和share-point的属主一致,即该用户同时存在于nfs server和nfs client中,且user/group、uid/gid均需一致。

nfs server

  • 创建共享账号和组

    $ pfexec groupadd -g 60000 sharegroup
    $ pfexec useradd -u 60000 -g sharegroup -s /bin/false -d /export/home/shareuser -c "share $ pfexec user account" -m shareuser
    $ pfexec usermod -G sharegroup alice
    $ pfexec usermod -G sharegroup bob
  • 创建一个zfs dataset

    $ sudo zfs create tank2/software/sharedir
    $ sudo chown shareuser:sharegroup /tank2/software/sharedir
    $ sudo chgrp g+rwx /tank2/software/sharedir
  • 开启nfs共享

    $ sudo zfs set sharenfs=on tank2/software/sharedir

最后结果是:

share-point                 owner:group             uid:gid     权限位
/tank2/software/sharedir	shareuser/sharegroup	60000/60000	drwxrwxr-x/775

nfs client

  • 创建一个mount-point并挂载

    $ sudo mkdir /mnt/sharedir (1)
    $ ls -ltr /mnt
    /mnt/sharedir	drwxr-xr-x	root/root (2)
    $ sudo mount -t nfs storage1:/tank2/software/sharedir /mnt/sharedir
    $ ls -ltr /mnt
    /mnt/sharedir	drwxrwxr-x	nobody/nobody (3)
    1 创建一个空目录/挂载点;
    2 在alice账号下使用sudo创建目录的本地属主为root/root;
    3 挂载后,目录权限位变成了775,这跟storage1中的/tank2/software/sharedir的权限位一致。另外,由于storage1 share-point的属主为shareuser:sharegroup/60000:60000,而pmx2中尚无对应的账号,所以nfs client会自动将mount-point的属主置为nobody:nobody/65534:65534

    这时候,alice用户无法在该目录进行文件/目录的创建、读和写的操作。

  • 创建共享账号和组

    $ sudo groupadd -g 60000 sharegroup
    $ sudo useradd -u 60000 -g sharegroup -s /bin/bin -m shareuser
    $ sudo usermod -G sharegroup,sudo alice
    $ sudo usermod -G sharegroup bob
  • 更改挂载点的属主和权限

    $ sudo chown shareuser:sharegroup /mnt/sharedir
  • 重新挂载并检查mount-point属性

    $ sudo umount /mnt/sharedir
    $ sudo mount -t nfs storage1:/tank2/software/sharedir /mnt/sharedir
    $ ls -ltr
    /mnt/sharedir	drwxrwxr-x	shareuser/sharegroup (1)
    1 挂载点的属性已经转换成本地目录属性。

    这时,alice账号可以在该mount-point进行文件/目录的创建、读和写的操作。

proxmox forum用户认为是solaris和linux关于nfsv4 acl的实现不兼容所致,然而通过上面的实验可以判断他是错的。
Solaris and derivatives implementation of NFS ACL is not compliant to the Linux NFS ACL. More directly it is the ACL in Linux which is not POSIX conformant so to avoid problems you should add the mount option noacl in your Linux fstab file. Noacl will instruct Omnios NFS to revert to plain old uid/gid.
— mir@proxmox.forum
http://lists.omniti.com/pipermail/omnios-discuss/2014-December/003786.html