2015 年 2 月 3 日,freeshell 出现持续两个小时的 NFS 卡死问题。事实上,2014 年 8 月启用外部磁盘以来,就经常出现持续几十秒甚至几分钟的 NFS 卡死,卡死期间外部磁盘上的 freeshell 无法执行任何操作,有的 freeshell 还会因为磁盘操作超时而关机。之前一直以为是 NFS bug 导致了死锁,没有定位到故障原因,也没能重现。

2 月 3 日,通过 tcpdump 抓包和 strace nfsiod 进程的方法,查明 NFS server not responding 的问题是由于外部硬盘(一块希捷的 2T 绿盘)过于繁忙。

在 NFS 卡死的时段,外部磁盘读的平均延迟可达 600ms,写的平均延迟是 1400ms。当初设置 NFS 挂载参数的时候,我没有考虑到磁盘繁忙的问题,只是想到了网络延迟不应当超过 1 秒,于是就设置了超时 timeo=10,表示 1 秒超时。一个 NFS 请求可能需要分解为多个磁盘读请求,这些请求的时间之和很可能超过 1 秒,也就是大部分读写请求还没来得及发给磁盘就超时了,形成了 NFS 服务器失去响应的假象。

下面是 早先的挂载参数
vers=3,rw,rsize=32768,wsize=32768,tcp,timeo=10,retrans=5,soft,intr,sec=sys,lookupcache=all,ac,nocto

现将超时修改成 30 秒(timeo=300)。
vers=3,rw,rsize=32768,wsize=32768,tcp,timeo=300,retrans=5,soft,intr,sec=sys,lookupcache=all,ac,nocto

2 月 3 日已经修改 fstab,但由于挂载着的 NFS 不能修改挂载参数(见 man nfs),需要关闭所有外部磁盘上的虚拟机才能重新挂载 NFS。2 月 4 日刚好 1 号节点挂了,于是把所有其他节点也重启了一遍,NFS 参数就更新了。