转自阿里巴巴陶毅的文章
1:问题出现
这几天部署zonda集群,意外的发现这样一个问题:
Zonda集群因为迁移数据,需要挂载NAS,但是发现一个问题,集群中的机器在mount存储之后报出如下错误:
这个错误是机器少见的,通过strace发现在挂载时报出如下错误:
在检查了NAS的配置和挂载参数都没有发现问题的情况下,由于报错的内容又很奇葩,一时没有什么思路,于是向库哥求助。
2:问题排错
我重启了主机,发现重启后是可以挂载的,但是如果卸载后,却不一定可以重新挂载成功。这又怪了,于是开始用tcp抓包,看nfs挂载的整个过程。然后发现了如下情况:
挂载成功的rpc情况:
而没有挂载成功的机器:
两个比较下来,发现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,则可以使用非特权端口。
这个同时也需要nfs server端也支持非特权端口。经过验证,主流的NAS(EMC,NetApp),GLUSTERFS的nfsserver都是支持非特权端口的。
PS:关于解决方案还有个方法就是修改系统参数改变nfs使用特权端口的范围:
sunrpc.min_resvport = 665
sunrpc.max_resvport = 1023
但是这样的操作会带来安全隐患,在修改后系统提示希望能够用其他更好的方式来加强安全性,因此不推荐。