macOS系统NFS服务
我在构建macOS系统中 Docker运行Studio容器 ,想要在物理主机(macOS)上能够直接存储容器的数据,以避免容器销毁导致开发环境的数据丢失。例如,我可以运行数据库,代码存储。
将容器中的数据通过卷存储到远程NFS服务器上,也就是macOS物理主机上,能够方便进行数据备份和同步。需要注意,macOS上运行的Docker服务器实际上是运行在 xhyve - macOS平台的KVM 运行的一个轻量级的 Alpine Linux 。所以,如果通过容器内部挂载NFS的方式来访问macOS物理服务器的共享存储,可以通过 获取macOS平台Docker虚拟机shell 在虚拟机上实现对远程存储的挂载,然后映射到容器内部提供使用。
通过NFS输出macOS上目录
首先在macOS主机上启动NFS服务:
sudo nfsd enable
如果系统已经启用过nfsd,则可能提示:
The nfsd service is already enabled.
Can't open /etc/exports, No such file or directory
检查nfs服务(portmapper):
sudo rpcinfo -p
输出显示:
program vers proto port
100000 2 udp 111 rpcbind
100000 3 udp 111 rpcbind
100000 4 udp 111 rpcbind
100000 2 tcp 111 rpcbind
100000 3 tcp 111 rpcbind
100000 4 tcp 111 rpcbind
100024 1 udp 980 status
100024 1 tcp 1021 status
100021 0 udp 976 nlockmgr
100021 1 udp 976 nlockmgr
100021 3 udp 976 nlockmgr
100021 4 udp 976 nlockmgr
100021 0 tcp 1017 nlockmgr
100021 1 tcp 1017 nlockmgr
100021 3 tcp 1017 nlockmgr
100021 4 tcp 1017 nlockmgr
100003 2 udp 2049 nfs
100003 3 udp 2049 nfs
100003 2 tcp 2049 nfs
100003 3 tcp 2049 nfs
100011 1 udp 604 rquotad
100011 2 udp 604 rquotad
100011 1 tcp 1003 rquotad
100011 2 tcp 1003 rquotad
100005 1 udp 685 mountd
100005 3 udp 685 mountd
100005 1 tcp 1023 mountd
100005 3 tcp 1023 mountd
如果 rpcinfo -p
输出显示超时:
Can't contact rpcbind on localhost
rpcinfo: RPC: Timed out
则可以尝试重启(实际是stop)一次 com.apple.rpcbind
sudo launchctl stop com.apple.rpcbind
此时你会看到:
k sudo launchctl list | grep rpcbind
依然显示 rpcbind
进程存在,但是该进程的pid已经改变,实际上系统会自动重新拉起 com.apple.rpcbind
,相当于重启了一次该服务。
然后再执行 sudo rpcinfo -p
就可以看到正常输出。
和标准的Unix/Linux系统相似,macOS也是通过
/etc/exports
文件配置NFS输出:/System/Volumes/Data/Users/dev -maproot=502:20 -network 192.168.6.0 -mask 255.255.255.0
备注
对应macOS需要设置 -maproot
这样远程客户端的root账号才能被映射到本地到一个用户,才能读写某个目录(远程客户端的root用户被映射成NFS服务器上的某个账号进行读写)
如果是仅仅对外提供一个只读目录并且对整个网络开放,可以使用:
/System/Volumes/Data/Users/shareall -ro -mapall=nobody -network 192.168.6.0 -mask 255.255.255.0
参数 mapall
可以将所有没有对应 gid/uid 的NFS客户端都映射到服务器上一个相同账号,例如 nobody
提供安全
并且检查配置的NFS是否正确:
nfsd checkexports
重启一次nfs服务:
最后检查输出的共享是否正确:
showount -a
显示:
All mounts on localhost:
192.168.6.200:/System/Volumes/Data/Users/dev
NFS客户端访问
备注
在macOS上我曾经想 获取macOS平台Docker虚拟机shell 在Docker VM上使用NFS来挂载macOS上的共享NFS卷,但是实践没有找到方法(难点在于 Alpine Linux 软件包管理以及访问macOS的IP地址 ),有待探索。不过,我在使用 Alpine Linux运行KVM虚拟化 恰好需要访问macOS上共享的ISO镜像,所以采用局域网Linux来访问macOS NFS共享。
配置
/etc/fstab
添加:192.168.6.1:/System/Volumes/Data/Users/dev /mnt nfs,noauto rw 0 0
挂载:
mount /mnt
Connection refused
我在 Alpine Linux 上挂载macOS NFS时候出现报错:
mount: mounting 192.168.6.1:/System/Volumes/Data/Users/dev on /mnt failed: Connection refused
但是,同样的配置,在 树莓派4b运行64位Ubuntu ,却能够作为NFS客户端正常挂载和使用,这个报错是因为 Alpine Linux 默认没有安装 nfs-utils
工具,并且没有启动NFS相关服务导致的。详见 Alpine Linux配置NFS
排查方法的经验是使用 rpcinfo -p
查看远程服务是否打开了对应服务端口:
rpcinfo -p 192.168.6.1
要检查有哪些服务列表也可以使用以下命令:
rpcinfo -p 192.168.6.1 | cut -c30- | sort -u
可以看到:
mountd
nfs
nlockmgr
rpcbind
rquotad
status
此外可以检查服务器上输出的挂载点:
showmount -e 192.168.6.1
输出显示:
Exports list on 192.168.6.1:
/System/Volumes/Data/Users/dev 192.168.6.0
上述输出显示NFS服务器正常,并且对比不同NFS客户端现象不同,则需要排查NFS客户端
防火墙
macOS提供了一个防火墙,需要检查确认一下默认是否启用了防火墙(可能和版本相关,不同版本默认有可能开启也可能关闭了防火墙,目前最新的macOS都是默认关闭防火墙)。对于启用了防火墙的macOS系统,需要配置 System Preferences => Secuirty & Privancy => Firewall
,设置允许TCP端口 2049, 111
。
备注
macOS的防火墙配置我还没有具体实践,
参考
macOS Catalina: nfsd needs to change exported dir to /System/Volumes/Data/...
Snow Leopard NFS Server and no_root_squash 解决服务器端用户uid映射问题,否则写入失败
Fast NFS volume on macOS 介绍了OS X的NFS客户端,需要使用参数
nolocks,locallocks
Mounting Directory - Connection Refused 排查Connection Refused问题