1:问题出现

这几天部署zonda集群,意外的发现这样一个问题:

 

Zonda集群因为迁移数据,需要挂载NAS,但是发现一个问题,集群中的机器在mount存储之后报出如下错误:

 

centos7挂载nfs存储无法写入 linux nfs挂载失败_server


这个错误是机器少见的,通过strace发现在挂载时报出如下错误:

 

centos7挂载nfs存储无法写入 linux nfs挂载失败_centos7挂载nfs存储无法写入_02

在检查了NAS的配置和挂载参数都没有发现问题的情况下,由于报错的内容又很奇葩,一时没有什么思路,于是向库哥求助。

 

2:问题排错

我重启了主机,发现重启后是可以挂载的,但是如果卸载后,却不一定可以重新挂载成功。这又怪了,于是开始用tcp抓包,看nfs挂载的整个过程。然后发现了如下情况:

 

挂载成功的rpc情况:

centos7挂载nfs存储无法写入 linux nfs挂载失败_redhat_03

 


 

而没有挂载成功的机器:

centos7挂载nfs存储无法写入 linux nfs挂载失败_集群_04


 

两个比较下来,发现rpc中多了一个nfs,然后想到该集群里的glusterfs在启动server时同时启动一个自有的nfsserver,难道是因为和nfs client有冲突,所以导致mount不上NAS??

 

3:问题找到

本来以为我们已经找到了答案,但是过了一个周末,情况发生了变化,周一在没有任何变化的情况下,集群绝大部分机器都能挂载NAS了!

 

我们的方向错了!

 

于是重新寻找答案。在这个时候,库哥发现加入一个参数“noresvport”后,部分NAS卷可以挂载成功。根据这个参数我们马上想起glusterfs会带起很多长连接。检查结果:

 

[root@zonda-ss02 /root]
#netstat -na|grep 172.16.197.87|awk '{print $4}'|awk -F ":" '{print $2}'|sort -n|wc -l
1853

 

然后发现特权端口都用完了!

 

而nfs client是在默认情况下是使用特权端口去连接nfs server的,如果自己的特权端口用完了,自然无法连接nfs server。

 

4:解决方案。

 

 

那么怎么解决这个问题呢?在redhat 5.3(我们最常使用的系统里),有个官方关于mount过多nfs文件系统的bug(bug 212398),当挂载超过350个文件系统时会失败。

 

而在2.6.28以后的kernel(对我们来讲就是用rh6以上)里,linux提供了一个控制方案,就是使用resvport/norevport来控制client将通过何种端口来挂载nfs server。

 

在默认或指定resvport参数时,系统通过特权端口来挂载,使用noresvport,则可以使用非特权端口。

 

centos7挂载nfs存储无法写入 linux nfs挂载失败_集群_05

 

这个同时也需要nfs server端也支持非特权端口。经过验证,主流的NAS(EMC,NetApp),GLUSTERFS的nfsserver都是支持非特权端口的。

 

 

PS:关于解决方案还有个方法就是修改系统参数改变nfs使用特权端口的范围:

sunrpc.min_resvport = 665

sunrpc.max_resvport = 1023

 

但是这样的操作会带来安全隐患,在修改后系统提示希望能够用其他更好的方式来加强安全性,因此不推荐。