3 min read

Proxmox使用zfs实现的NFS挂载存储失败问题

问题

为pve的集群添加新的节点上的NFS作为备份专用存储的时候, 始终报错 create storage failed: storage 'nzvBackup' is not online (500)

但是到服务器后台手动 mount -t nfs ip:/path/to/folder /mnt/test 的时候又是成功的, 百思不得其解

排查

根据报错查了一遍资料, 发现了一个讨论这个的proxmox的帖子, 各种方案很详细, 可以做如下排查

防火墙

大部分都是防火墙或selinux引起的问题, 添加nfs放行规则或关闭防火墙或关闭selinux后即可解决

portmap未安装, 端口异常等

apt list --installed |grep portmap 看了下确实没装, 但我本地的另一个pve节点也是zfs实现的nfs, 也没装portmap, 就很奇怪

相关服务启动异常

后来发现 mount -t nfs 虽然正常, 但 mount -t nfs -o vers=3 确挂载不上

showmount --export ip.of.nfs.hostrpcinfo -p ip.of.nfs.host 都会报错

clnt_create: RPC: Unable to receiveip.of.nfs.host: RPC: Remote system error - Connection refused

在nfs服务器上用systemctl查了下, nfs-开头的服务似乎都是正常的, 2049端口也被正常监听着

进一步用 ps -ef |grep rpc 发现, 出问题的节点上少了一个进程, 正常应该是

# ps -ef |grep rpc
root         562       2  0 Dec27 ?        00:00:00 [rpciod]
root        3739       1  0 Dec27 ?        00:00:00 /usr/sbin/rpc.idmapd
_rpc        3750       1  0 Dec27 ?        00:00:00 /sbin/rpcbind -f -w
root        5437       1  0 Dec27 ?        00:00:00 /usr/sbin/rpc.mountd --manage-gids
statd     255194       1  0 Dec27 ?        00:00:00 /sbin/rpc.statd --no-notify
root      530269  167207  0 01:09 pts/2    00:00:00 grep rpc

四个rpc相关进程, 但问题节点上少了 rpc.statd 进程

systemctl status rpc.statd.service 发现服务果然处于退出状态

# systemctl status rpc-statd.service
● rpc-statd.service - NFS status monitor for NFSv2/3 locking.
     Loaded: loaded (/lib/systemd/system/rpc-statd.service; disabled; vendor preset: ena>
     Active: inactive (dead)

于是把它enable了, 再start起来, 本以为一切就正常了, 然而...

深层原因

为啥这个服务被禁用了, 没探究. 但它确实是负责nfs v2和v3的通信的, 停了就是会连不上.

上面的弄完了, 还是不行, rpcinfo有结果了, 但rpcinfo -p localhost 还是connection refused

再研究了一通, 发现在正常的节点上 curl localhost:111 响应是 curl: (56) Recv failure: Connection reset by peer , 但问题节点上直接就是 curl: (7) Failed to connect to 10.1.0.4 port 111: Connection refused

怀疑网络层面有一定的差异

后来又用netcat尝试监听本地端口, 发现竟然从110到120竟然都已经被监听了, natcat直接监听失败, 查看发现是dockerd监听了, 但本地并没有容器监听在该端口上.

猛然想起来, 我是docker swarm环境, 在别的节点上, 确实有监听 110-120 全部端口, 正好跟rpcbind的111端口冲突了. 所以才导致失败的, 把容器的端口改掉后, 一切恢复正常了

一切的本质, 竟然是因为我偷懒了, 直接在pve节点上运行了docker, 加入了swarm集群, 导致端口发生了冲突引起的问题