Last Updated on

前言

NFS(Network File System)即网络文件系统,它允许网络中的计算机之间通过TCP/IP网络共享资源。在NFS的应用中,本地NFS的客户端应用可以透明地读写位于远端NFS服务器上的文件,就像访问本地文件一样。

这在如今微服务为首的架构环境下,非常实用,可以让微服务运行在多台服务器上,通过NFS实现文件同步,解决了微服务中的静态文件同步问题。任何一台服务器上的文件发生变化,都可以实时同步到别的主机上。

如图所示,用户在NFS客户端上操作文件会实时通过网络传到NFS服务端,然后写到服务端的磁盘上,文件实际都是存在了服务端,所以所有网络和磁盘的I/O压力都在服务端,所以一旦系统过大,负载过高时,其稳定性和时效性就得不到保障,所以NFS在中小型互联网公司总应用广泛,如果中大型互联网公司,当压力访问过大时,还会用到更复杂的分布式文件系统,例如:Moosefs(mfs)、GlusterFS、FastDFS 等等。

下面就详细记录介绍一下NFS网络文件系统的搭建

正文

1. 服务端安装

# 安装nfs 和 rpcbind(使用nfs服务,都需要安装的rpc服务),并配置开机启动
$ yum install -y nfs-utils rpcbind

# 启动nfs和rpcbind,并设置开机启动
$ systemctl enable nfs-server
$ systemctl enable rpcbind
$ systemctl start nfs
$ systemctl start rpcbind

# 查看两个服务状态,确保服务正常运行
$ systemctl status nfs
$ systemctl status rpcbind
 
# 创建要共享的文件,原先已经存在的文件夹则不用创建了
$ mkdir /mydata
 
# 为文件夹设置用户和用户组,需要设为nfsnobody
$ chown nfsnobody.nfsnobody /mydata

# 编辑nfs配置文件
$ vim /etc/exports
--------------------------------------------------------------------
# 添加配置,将本机的这个路径的文件作为nfs共享文件,共享给指定IP
# /mydata 192.168.0.2(rw,sync,all_squash)
# 或共享给指定IP段
/mydata 192.168.0.0/24(rw,sync,all_squash)
--------------------------------------------------------------------
 
# 重载配置
$ exportfs -rv
exporting 192.168.0.0/24:/data
 
# 查看本地挂载情况
$ showmount -e localhost
Export list for localhost:
/data 192.168.0.0/24

# 开放防火墙nfs服务
$ firewall-cmd --add-service=nfs --permanent
$ firewall-cmd --reload

OK,到此服务端安装完成。

2. 客户端安装

切换到需要连接NFS的客户端的服务器上来,进行客户端的安装

# 同样需要先下载安装nfs,rpcbind,并设为开机启动
$ yum install -y nfs-utils rpcbind

# 启动nfs和rpcbind,并设置开机启动
$ systemctl enable nfs-server
$ systemctl enable rpcbind
$ systemctl start nfs
$ systemctl start rpcbind

# 查看两个服务状态,确保服务正常运行
$ systemctl status nfs
$ systemctl status rpcbind

# 创建需要将NFS的共享文件夹放置到本机的目录,当然可以是任何目录
$ mkdir -p /usr/local/mydata
 
# 将服务端的目录挂载到本地的对应目录下
$ mount -t nfs 192.168.0.1:/mydata /usr/local/mydata
 
## 查看挂载情况,会发现最后一行出现了nfs的挂载信息
$ df -h
192.168.0.1:/mydata   40G  5.1G   33G  14% /usr/local/mydata
 
# 卸载挂载方式
$ umount /usr/local/mydata

OK,到此nfs客户端安装成功,且挂载成功,可以此时,在客户端上修改修改挂载目录中的文件,服务端和其他客户端会有相同变化,实现文件了文件呢共享。

3. 服务端配置参数详解

按照上面安装使用后,你会发现,客户端在操作nfs挂载文件中的文件时,读写的文件的所有人和组都会变成nfsnobody,这样所有客户端都可以读写文件。

此时,如果你在服务端上,手动在挂载的文件中新增文件,会发现文件的所有人会是你操作的账号,比如root,这时候,你再到客户端上看,同样会看到这个属于root的文件,但是只能读,却无法写,且在客户端上也无法修改其文件属性,将所有人改为nfsnobody,只有在服务端上才能操作,改为nfsnobody后,客户端才能操作。

这些权限的控制,实际上是由服务端在设置的时候,配置的,详细看第一步服务端安装时,我们配置了需要共享的目录,如下:

/mydata 192.168.0.0/24(rw,sync,all_squash)

其中在目录后面括号内的就是定义的配置,其中的参数有如下几种:

  • ro:目录只读
  • rw:目录可读写
  • sync:数据同步写入到NFS Server的硬盘后才返回,优点:数据安全不会丢;缺点:性能较差
  • async:数据写入到NFS Server内存缓冲区后就返回,再随服务器异步写入磁盘。优点:写入效率高,性能快。风险:若服务端服务器宕机或不正常关机,可能丢失内存缓冲区内的数据。
  • all_squash:将客户端访问的所有用户及所属组都压缩为匿名用户或用户组“nfsnobody”
  • no_all_squash:与all_squash取反,不压缩为匿名用户(默认设置)
  • root_squash:如果客户端访问的用户是root,将root用户及所属组都压缩为匿名用户或用户组“nfsnobody” (默认设置)
  • no_root_squash:与root_squash取反,不压缩为匿名用户
  • anonuid:将客户端访问的所有用户都压缩为匿名用户,并指定该用户的uid,前提是所有客户端都必须存在此用户,一般此值设置为nfsnobody用户的uid
  • anongid:与anonuid一样,只是将指定uid换成了gid

那么在生产环境中,我们一般怎么选择进行配置呢,一般生产环境中,我们都会存在多个客户端共同连接一个服务端,那么设置时,选择sync保证数据一致性,选择all_squash保证将所有用户压缩为指定用户来实现用户权限的统一

PS: anonuid/anongid 需要与all_squash 共同使用

常见生产环境如下配置:

/mydata 192.168.0.0/24(rw,sync,all_squash,anonuid=65534,anongid=65534)

注意:如果你在nfs服务端上也跑着业务服务,此业务服务会直接操作nfs共享文件夹,那么文件的所属就会是此业务服务的运行用户,假设为A用户,那么A用户创建的文件,就会没办法被客户端修改,因为客户端都被压缩为了nfsnobody用户。

解决办法的思路是:

  • 让服务端上操作nfs共享文件夹的用户,和客户端访问压缩成的用户相同,即可正常使用。

比如,一般常见我nfs服务端上用ops用户跑了服务,会读写nfs的共享文件夹,里面就会有ops权限的文件,此时,修改服务端配置中的anonuid和anongid,指定为ops用户即可。

另外的,如果运行业务服务的用户都是root,那么可以直接使用no_root_squash不压缩用户,都直接用root用户操作nfs共享文件夹。比如如下配置:

# no_root_squash有root权限,不是太安全,不推荐。
/mydata 192.168.0.0/24(rw,sync,no_root_squash)

另外,修改了服务端的配置后,需要重载生效:

# 在服务端重载配置生效,客户端不用重新挂载即可生效新的设置。
$ exportfs -rv

注意: 当nfs服务端停止服务时,客户端挂载目录会出现卡死情况。因为nfs挂载默认是hard-mount挂载,当服务端停止服务时,客户端加载nfs不成功,就会不断的重试,直到服务端恢复之前,挂载目录都会出现卡死的情况。

要解决有两种办法:

  • 用umount卸载此目录的nfs挂载,卸载后该目录正常访问。待服务端恢复后再重新mount挂载。
  • 挂载时更换为soft-mount,设置重试次数,当重试都不成功后,则会放弃,返回错误信息 "Connect time out"

使用软挂载方式:

# 上文客户端挂载的例子,nfs软挂载的方式为:
mount -t nfs -o rw,soft,timeo=30,retry=5,timeo=30 192.168.0.1:/mydata /usr/local/mydata

# timeo的单位是0.1秒,配置为30就是隔3秒客户端向服务器端请求。
# retry重试次数

结束

好啦,到此介绍完了NFS服务的详细部署与配置。

严谨的你会发现,nfs做共享文件的方式,优缺点很明显:

  • 优点: 方便简单,易上手,易维护,成本低,对代码侵入性少。
  • 缺点: 所有读写IO压力集中在服务端,性能有限,服务端存在单点问题,要解决单点问题,较复杂,就失去了方便简单的优点,不如直接使用高可用的分布式文件系统服务。

如上,因为nfs的优缺点,推荐大家使用nfs的场景是:内部系统或服务,性能要求不高,访问人数不大,中小型项目,数据重要程度有限。

那么不用nfs用什么呢,对于较大型项目,特别是一些对外服务,互联网应用等。可以使用高可用的分布式文件系统,或者推荐直接使用云对象存储服务,如阿里云oss,腾讯云cos。成本不高,管理简单,稳定高效。

好了,今天就说到这里,有任何问题,欢迎留言。