最近折腾一下 NFS, 先白嫖一顿华子云的 1 个月服务器, 2C4G 感觉不错了, 但NFS 配置起来还是有点难度, 主要还是随机分配的端口配置方面比较恶心.
server环境:
- 华为云 2C4G Ubuntu22.04
client环境:
MacOS M1 with brew
Archlinux qemu-x86_64
NFS 可以理解为网络主机上的一种服务, 支持多端的存储, 并且没有架构的限制, 底层通过 RPC 完成通信, 具体就是通过 RPC 寻找Server, 然后将找到的 Server 传到 Client,
首先需要安装一下nfs-Server:
sudo apt install rpcbind
sudo apt install nfs-server
sudo apt install nfs-kernel-server #这个好像在安装 nfs-server 之后就已经作为依赖安装过了
开启指定服务: (开机启动)
sudo systemctl enable rpcbind nfs-server
sudo systemctl start rpcbind nfs-server #这步可选, 因为安装之后默认是开启的
新建文件夹: (需要共享的文件夹)
mkdir /home/user/nfs_data
# 这里用 /nfs 也可以, 不过权限要注意.
sudo vi /etc/exports
# 下面的内容写入: (注意*之后左括号之前不要加任何空格!!!)
/home/user/nfs_data *(rw,async,insecure,no_subtree_check,all_squash,anonuid=0,anongid=0)
接下来遇到一个坑点了, 网上找到的关于 Ubuntu18 或者 20 的更改端口的方法都不起作用, 后来发现原来是 Ubuntu22.04 的一个更新点:
Bug #1971096 “Cannot Specify Fixed Ports for mountd and statd” : Bugs : nfs-utils package : Ubuntu;
Network File System (NFS) | Ubuntu;
参考的第二行给出了最新的配置文档, 也就是具体需要更改的配置文件: /etc/nfs.conf
这里主要是设置三个静态端口:
[lockd]
port=40002
[mountd]
# debug=0
manage-gids=y
# descriptors=0
port=40001
[statd]
# debug=0
port=40000
其实主要就是搜索 port 对应的条目, 改之.
然后划重点的来了!!! (当然事实就是重启解决一切问题, 不过作为服务器来说总重启对用户体验不太好)
这里又是一个坑.
需要明确的是重启的服务不只是 nfs 的, 还有 rpc 相关的, 这里文档也提到了, 只是我没注意…
For example,
systemctl restart nfs-server.service
will restartnfs-mountd
,nfs-idmapd
andrpc-svcgssd
(if running). On the other hand, restartingnfs-utils.service
will restartnfs-blkmap
,rpc-gssd
,rpc-statd
andrpc-svcgssd
.Of course, each service can still be individually restarted with the usual
systemctl restart
.The
nfs.systemd(7)
manpage has more details on the several systemd units available with the NFS packages.
也就是说, status 改了之后需要重启的服务是rpc-utils
!
sudo systemctl restart nfs-server
sudo systemctl restart rpc-utils
这样才算是完成了端口的指定了.
最后看一下设置的情况:
==> rpcinfo -p
program vers proto port service
100000 4 tcp 111 portmapper
100000 3 tcp 111 portmapper
100000 2 tcp 111 portmapper
100000 4 udp 111 portmapper
100000 3 udp 111 portmapper
100000 2 udp 111 portmapper
100005 1 udp 40001 mountd
100005 1 tcp 40001 mountd
100005 2 udp 40001 mountd
100005 2 tcp 40001 mountd
100005 3 udp 40001 mountd
100005 3 tcp 40001 mountd
100003 3 tcp 2049 nfs
100003 4 tcp 2049 nfs
100227 3 tcp 2049
100021 1 udp 40002 nlockmgr
100021 3 udp 40002 nlockmgr
100021 4 udp 40002 nlockmgr
100021 1 tcp 40002 nlockmgr
100021 3 tcp 40002 nlockmgr
100021 4 tcp 40002 nlockmgr
100024 1 udp 40000 status
100024 1 tcp 40000 status
华为云服务器开放的端口:
控制台界面-> 安全组->配置规则->入方向规则->添加规则
优先级 1 即可, 端口都开放的是 TCP, 这里就不开放 UDP了, 如果网速比较慢需要开一下.
除了上面提到的rpcinfo
, 还可以通过下面的一些命令查看连接状态
1024 以下的端口号需要 sudo
==> sudo lsof -i:111
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd 1 root 91u IPv4 1847 0t0 TCP *:sunrpc (LISTEN)
systemd 1 root 93u IPv4 1848 0t0 UDP *:sunrpc
systemd 1 root 96u IPv6 1849 0t0 TCP *:sunrpc (LISTEN)
systemd 1 root 97u IPv6 1850 0t0 UDP *:sunrpc
rpcbind 485 _rpc 4u IPv4 1847 0t0 TCP *:sunrpc (LISTEN)
rpcbind 485 _rpc 5u IPv4 1848 0t0 UDP *:sunrpc
rpcbind 485 _rpc 6u IPv6 1849 0t0 TCP *:sunrpc (LISTEN)
rpcbind 485 _rpc 7u IPv6 1850 0t0 UDP *:sunrpc
==> showmount -a
All mount points on hecs:
ip:/home/user/nfs_data
[Ubuntu] √ ~
==> showmount -e
Export list for hecs:
/home/user/nfs_data *
[Ubuntu] √ ~
==> showmount -d
Directories on hecs:
/home/user/nfs_data
[Ubuntu] √ ~
==> showmount -d
--all -a -- list both hostname and mounted dir in host:dir format
--directories -d -- list only the directories mounted by some client
--exports -e -- show server export list
--help -h -- help
--no-headers -- suppress descriptive headers from output
--version -v -- version
==> rpcinfo -m
PORTMAP (version 2) statistics
NULL SET UNSET GETPORT DUMP CALLIT
19 0/0 0/0 18/22 21 0/0
PMAP_GETPORT call statistics
prog vers netid success failure
status 1 tcp 3 0
mountd 3 tcp 7 0
nfs 3 tcp 8 0
status 1 udp 0 4
RPCBIND (version 3) statistics
NULL SET UNSET GETADDR DUMP CALLIT TIME U2T T2U
0 148/148 73/73 0/0 0 0/0 0 0 0
RPCBIND (version 4) statistics
NULL SET UNSET GETADDR DUMP CALLIT TIME U2T T2U
11 198/198 168/168 10/10 0 0/0 0 0 0
VERADDR INDRECT GETLIST GETSTAT
0 0 0 1
RPCB_GETADDR (version 4) call statistics
prog vers netid success failure
mountd 3 tcp 10 0
==> nfsstat -m #在 Client 端执行
/Volumes/nfs_data from ip:/home/user/nfs_data
-- Original mount options:
General mount flags: 0x0
NFS parameters: deadtimeout=45
File system locations:
/home/user/nfs_data @ ip (ip)
-- Current mount parameters:
General mount flags: 0x4000018 nodev,nosuid,multilabel
NFS parameters: vers=3,tcp,port=2049,nomntudp,hard,nointr,noresvport,negnamecache,callumnt,locks,quota,rsize=32768,wsize=32768,readahead=16,dsize=32768,rdirplus,nodumbtimer,timeo=10,maxgroups=16,acregmin=5,acregmax=60,acdirmin=5,acdirmax=60,deadtimeout=45,nomutejukebox,nonfc,sec=sys
File system locations:
/home/user/nfs_data @ ip (ip)
Status flags: 0x0
Server 端的一些选项:
==> nfsstat -l
nfs v3 server total: 180
------------- ------------- --------
nfs v3 server null: 8
nfs v3 server getattr: 81
nfs v3 server lookup: 22
nfs v3 server access: 33
nfs v3 server read: 1
nfs v3 server readdirplus: 3
nfs v3 server fsstat: 24
nfs v3 server fsinfo: 4
nfs v3 server pathconf: 4
nfs v4 server total: 130
------------- ------------- --------
nfs v4 server null: 2
nfs v4 server compound: 128
nfs v4 servop total: 401
------------- ------------- --------
nfs v4 servop access: 9
nfs v4 servop close: 1
nfs v4 servop getattr: 104
nfs v4 servop getfh: 15
nfs v4 servop lookup: 14
nfs v4 servop open: 1
nfs v4 servop putfh: 113
nfs v4 servop putrootfh: 4
nfs v4 servop readdir: 4
nfs v4 servop rename: 1
nfs v4 servop savefh: 1
nfs v4 servop setattr: 1
nfs v4 servop write: 1
nfs v4 servop exchange_id: 4
nfs v4 servop create_ses: 2
nfs v4 servop destroy_ses: 2
nfs v4 servop secinfononam: 2
nfs v4 servop sequence: 118
nfs v4 servop destroy_clid: 2
nfs v4 servop reclaim_comp: 2
==> sudo exportfs -v
/home/user/nfs_data
<world>(async,wdelay,hide,no_subtree_check,anonuid=0,anongid=0,sec=sys,rw,insecure,root_squash,all_squash)
这里比较有讲究, MacOS需要开放全部的端口, 否则连接会失败, 但是 archLinux 不需要, 仅通过 2049 完成连接, 这也是 Linux 的魅力所在吧.
不需要安装额外的软件, 甚至通过访达也能连接, 只需要通过⌘+K, 键入:
nfs://<公网IP>/home/user/nfs_data
或者终端:
sudo mount_nfs -o rw <公网IP>:/home/user/nfs_data ~/code/nfs
sudo umount ~/code/nfs #取消挂载, 取消挂载之前记得先返回上级目录
都是比较方便的, 通过:
rpcinfo -p <公网IP>
查看连接情况, 一般来说应该与 Server 端的端口开放情况保持一致的, 例如:
program vers proto port
100000 4 tcp 111 rpcbind
100000 3 tcp 111 rpcbind
100000 2 tcp 111 rpcbind
100000 4 udp 111 rpcbind
100000 3 udp 111 rpcbind
100000 2 udp 111 rpcbind
100005 1 udp 40001 mountd
100005 1 tcp 40001 mountd
100005 2 udp 40001 mountd
100005 2 tcp 40001 mountd
100005 3 udp 40001 mountd
100005 3 tcp 40001 mountd
100003 3 tcp 2049 nfs
100003 4 tcp 2049 nfs
100227 3 tcp 2049 nfs_acl
100021 1 udp 40002 nlockmgr
100021 3 udp 40002 nlockmgr
100021 4 udp 40002 nlockmgr
100021 1 tcp 40002 nlockmgr
100021 3 tcp 40002 nlockmgr
100021 4 tcp 40002 nlockmgr
100024 1 udp 40000 status
100024 1 tcp 40000 status
直接一行:
sudo mount -t nfs -o rw <公网IP>:/home/user/nfs_data ~/nfs
# 因为没读取系统级端口, 所以 sudo 不是必须的.