写在前面
最近折腾一下 NFS, 先白嫖一顿华子云的 1 个月服务器, 2C4G 感觉不错了, 但NFS 配置起来还是有点难度, 主要还是随机分配的端口配置方面比较恶心.
server环境:
- 华为云 2C4G Ubuntu22.04
client环境:
MacOS M1 with brew
Archlinux qemu-x86_64
背景
NFS 可以理解为网络主机上的一种服务, 支持多端的存储, 并且没有架构的限制, 底层通过 RPC 完成通信, 具体就是通过 RPC 寻找Server, 然后将找到的 Server 传到 Client,
server 端配置
安装基本包
首先需要安装一下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](https://ubuntu.com/server/docs/service-nfs);
参考的第二行给出了最新的配置文档, 也就是具体需要更改的配置文件: /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 <service>
.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了, 如果网速比较慢需要开一下.
- 2049(这里 UDP 可以开一下, 因为是实际走连接的端口)
- 111
- 40000
- 40001
- 40002
查看状态
除了上面提到的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
查看 rpc 连接情况
==> 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
==> 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)
client 端配置
这里比较有讲究, MacOS需要开放全部的端口, 否则连接会失败, 但是 archLinux 不需要, 仅通过 2049 完成连接, 这也是 Linux 的魅力所在吧.
MacOS
不需要安装额外的软件, 甚至通过访达也能连接, 只需要通过⌘+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
额外扩展: 自动挂载
参考文章简单配置一下即可.
archlinux
直接一行:
sudo mount -t nfs -o rw <公网IP>:/home/user/nfs_data ~/nfs
# 因为没读取系统级端口, 所以 sudo 不是必须的.