Linux 搭建 NFS 服务

5 minute read

NFS 协议

NFS 服务工作在 TCP2049 端口,UDP2049 端口。

NFS 是 Network File System 的缩写,即网络文件系统,是一种使用于分散式文件系统的协定。功能是通过网络让不同的机器、不同的操作系统能够彼此分享个别的数据,让应用程序在客户端通过网络访问位于服务器磁盘中的数据,是在类 Unix 系统间实现磁盘文件共享的一种方法。

这个 NFS 服务器可以让你的 PC 来将网络远程的 NFS 服务器分享的目录,挂载到本地端的机器当中, 在本地端的机器看起来,那个远程主机的目录就好像是自己的一个磁盘分区槽一样。

工作原理

因为 NFS 支持的功能相当的多,而不同的功能都会使用不同的程序来启动, 每启动一个功能就会启用一些端口来传输数据,因此, NFS 的功能所对应的端口才没有固定住, 而是随机取用一些未被使用的小于 1024 的端口来作为传输之用。但如此一来又造成客户端想要连上服务器时的困扰, 因为客户端得要知道服务器端的相关端口才能够联机吧!

NFS 在文件传送或信息传送过程中依赖于 RPC 协议。RPC,即远程过程调用的缩写,是能使客户端执行其他系统中程序的一种机制。RPC 最主要的功能就是在指定每个 NFS 功能所对应的端口号,并且回报给客户端,让客户端可以连接到正确的端口上去。

NFS 本身是没有提供信息传输的协议和功能的,但 NFS 却能让我们通过网络进行资料的分享,这是因为 NFS 使用了一些其它的传输协议。而这些传输协议用到这个 RPC 功能的。可以说 NFS 本身就是使用 RPC 的一个程序,或者说 NFS 也是一个 RPC SERVER。所以只要用到 NFS 的地方都要启动 RPC 服务,不论是 NFS SERVER 或者 NFS CLIENT。这样 SERVER 和 CLIENT 才能通过 RPC 来实现 PROGRAM PORT 的对应。可以这么理解 RPC 和 NFS 的关系:NFS 是一个文件系统,而 RPC 则是负责信息的传输

事实上,有很多这样的服务器都是向 RPC 注册的,举例来说,NIS (Network Information Service) 也是 RPC server 的一种。

RPC 又是如何知道每个 NFS 的端口呢?

  • 这是因为当服务器在启动 NFS 时会随机取用数个端口,并主动的向 RPC 注册,因此 RPC 可以知道每个埠口对应的 NFS 功能,然后 RPC 又是固定使用 111 端口来监听客户端的需求并报客户端正确的埠口, 所以当然可以让 NFS 的启动更为轻松愉快了。
  • 所以你要注意,要启动 NFS 之前,RPC 就要先启动了,否则 NFS 会无法向 RPC 注册。另外,RPC 若重新启动时,原本注册的数据会不见,因此 RPC 重新启动后,它管理的所有服务都要重新启动来重新向 RPC 注册。

那客户端如何向 NFS 服务端交换数据呢?

  • (1) 客户端会向服务器端的 RPC 的 111 端口发出 NFS 档案存取功能的询问要求
  • (2) 服务器端找到对应的已注册的 NFS 守护进程端口后,会回报给客户端
  • (3) 客户端了解正确的端口后,就可以直接与 NFS 守护进程来联机

激活 NFS 服务

NFS 服务需要激活几个重要的 RPC 守护进程

工作流程

nfs—client => portmapper => mountd => nfs-server(nfsd)

(1) rpc.nfsd

  • 这个守护进程主要的功能,则是在管理客户端是否能够登入主机的权限,其中还包含这个登入者的 ID 的判别。

(2) rpc.mountd

主要功能

  • 这个守护进程主要的功能,则是在管理 NFS 的档案系统,用于给用户提供访问令牌。
  • 访问的令牌,由本地的 RPC 提供随机端口。本地的 RPC 叫做 portmapper,可以使用 rpcinfo -P 查看。
  • RPC的 portmapper 服务工作在 1111 端口。

请求过程

  • 当客户端顺利的通过 rpc.nfsd 而登入主机之后,在它可以使用 NFS server 提供的档案之前,还会经过档案使用权限的认证程序,就是那个-rwxrwxrwxownergroup那几个权限啦。
  • 然后它会去读 NFS 的设定档 /etc/exports 来比对客户端的权限,当通过这一关之后,客户端就可以取得使用 NFS 档案的权限啦。

注释:NFS 需要有两个套件

  • nfs-utils

NFS服务的主要套件

提供 rpc.nfsdrpc.mountd 两个 NFS 守护进程和与其它相关文档与说明文件、执行档等的套件

  • portmap

主要负责 RPC 端口和守护进程的映射关系,即 portmapper

在激活任何一个 RPC server 之前,我们都需要激活 portmapper 才行

各个版本之间的比较

NFS 是一种网络文件系统,从 1985 年推出至今,共发布了 3 个版本:NFSv2NFSv3NFSv4,NFSv4 包含两个次版本 NFSv4.0 和 NFSv4.1。经过 20 多年发展,NFS 发生了非常大的变化,最大的变化就是推动者从 Sun 变成了 NetApp,NFSv2 和 NFSv3 基本上是 Sun 起草的,NetApp 从 NFSv4.0 参与进来,并且主导了 NFSv4.1 标准的制定过程,而 Sun 已经被 Oracle 收购了。

编号 协议版本 RFC 时间 页数
1 NFSv2 rfc1094 1989 年 3 月 27 页
2 NFSv3 rfc1813 1995 年 6 月 126 页
3 NFSV4.0 rfc3530 2003年 4 月 275 页
4 NFSV4.1 rfc5661 2010 年 1 月 716 页

1. NFSv2

  • NFSv2 是第一个以 RFC 形式发布的版本,实现了基本的功能。

2. NFSv3

协议特点

NFSv3 修正了 NFSv2 的一些 bug,两者有如下一些差别,但是感觉没有本质的差别。

区别差别

  • (1) NFSv2 只支持同步写,如果客户端向服务器端写入数据,服务器必须将数据写入磁盘中才能发送应答消息。NFSv3 支持异步写操作,服务器只需要将数据写入缓存中就可以发送应答信息了。
  • (2) NFSv3 增加了 ACCESS 请求,ACCESS 用来检查用户的访问权限。因为服务器端可能进行 uid 映射,因此客户端的 uidgid 不能正确反映用户的访问权限。
  • (3) 一些请求调整了参数和返回信息,毕竟 NFSv3 和 NFSv2 发布的间隔有 6 年,经过长期运行可能觉得 NFSv2 某些请求参数和返回信息需要改进。

3. NFSv4.0

协议特点

  • (1) 相比 NFSv3NFSv4 发生了比较大的变化,最大的变化是 NFSv4 有状态了。NFSv2 和 NFSv3 都是无状态协议,服务区端不需要维护客户端的状态信息。
  • (2) 无状态协议的一个优点在于灾难恢复,当服务器出现问题后,客户端只需要重复发送失败请求就可以了,直到收到服务器的响应信息。

区别差别

  • (1) NFSv4 增加了安全性,支持 RPCSEC-GSS 身份认证。

  • (2) NFSv4 设计成了一种有状态的协议,自身实现了文件锁功能和获取文件系统根节点功能。

  • (3) NFSv4 只提供了两个请求 NULLCOMPOUND ,所有的操作都整合进了 COMPOUND 中,客户端可以根据实际请求将多个操作封装到一个 COMPOUND 请求中,增加了灵活性。

  • (4) NFSv4 文件系统的命令空间发生了变化,服务器端必须设置一个根文件系统( fsid=0 ),其他文件系统挂载在根文件系统上导出。

  • (5) NFSv4 支持 delegation。由于多个客户端可以挂载同一个文件系统,为了保持文件同步,NFSv3 中客户端需要经常向服务器发起请求,请求文件属性信息,判断其他客户端是否修改了文件。如果文件系统是只读的,或者客户端对文件的修改不频繁,频繁向服务器请求文件属性信息会降低系统性能。NFSv4 可以依靠 delegation 实现文件同步。

  • (6) NFSv4 修改了文件属性的表示方法。由于 NFS 是 Sun 开发的一套文件系统,设计之出 NFS 文件属性参考了 UNIX 中的文件属性,可能 Windows 中不具备某些属性,因此 NFS 对操作系统的兼容性不太好。

4. NFSv4.1

  • NFSv4.0 相比,NFSv4.1 最大的变化是支持并行存储了。在以前的协议中,客户端直接与服务器连接,客户端直接将数据传输到服务器中。
  • 当客户端数量较少时这种方式没有问题,但是如果大量的客户端要访问数据时,NFS 服务器很快就会成为一个瓶颈,抑制了系统的性能。NFSv4.1 支持并行存储,服务器由一台元数据服务器( MDS )和多台数据服务器( DS )构成,元数据服务器只管理文件在磁盘中的布局,数据传输在客户端和数据服务器之间直接进行。由于系统中包含多台数据服务器,因此数据可以以并行方式访问,系统吞吐量迅速提升。

NFS 服务

CentOS7NFSv4 作为默认版本,NFSv4 使用 TCP 协议(端口号是 2049 )和 NFS 服务器建立连接。

安装 NFS 服务

服务端

  • 服务端,程序包名 nfs-utilsrpcbind
  • 可以通过 rpm -ql nfs-utils 查看帮助文档等信息

客户端

  • 客户端,需要安装程序包名 nfs-utils ,提供基本的客户端命令工具
$ yum install nfs-utils

查看 NFS 服务端口

  • NFS 启动时会随机启动多个端口并向 RPC 注册,为了方便配置防火墙,需要固定 NFS 服务端口。
  • 这样如果使用防火墙对 NFS 端口进行限制就会有点麻烦,可以更改配置文件固定 NFS 服务相关端口
  • 分配固定端口,编辑配置文件 /etc/sysconfig/nfs
# 使用 rpcinfo -P 会发现 rpc 启动了很多监听端口
$ rpcinfo -p localhost
   program vers proto   port  service
    100000    4   tcp    111  portmapper
    100000    3   tcp    111  portmapper
    100000    2   tcp    111  portmapper
    100000    4   udp    111  portmapper
    100000    3   udp    111  portmapper
    100000    2   udp    111  portmapper
    100005    1   udp  48892  mountd
    100024    1   udp  32954  status
    100005    1   tcp  48892  mountd
    100005    2   udp  48892  mountd
    100005    2   tcp  48892  mountd
    100005    3   udp  48892  mountd
    100005    3   tcp  48892  mountd
    100024    1   tcp  36922  status
    100003    3   tcp   2049  nfs
    100003    4   tcp   2049  nfs
    100227    3   tcp   2049  nfs_acl
    100003    3   udp   2049  nfs
    100003    4   udp   2049  nfs
    100227    3   udp   2049  nfs_acl
    100021    1   udp  32769  nlockmgr
    100021    3   udp  32769  nlockmgr
    100021    4   udp  32769  nlockmgr
    100021    1   tcp  32803  nlockmgr
    100021    3   tcp  32803  nlockmgr
    100021    4   tcp  32803  nlockmgr
    
# 添加如下
$ cat <<EOF | tee -a /etc/sysconfig/nfs
RQUOTAD_PORT=30001
LOCKD_TCPPORT=30002
LOCKD_UDPPORT=30002
MOUNTD_PORT=30003
STATD_PORT=30004
EOF

启动服务

$ systemctl start nfs

服务文件配置

相关文件和命令

文件名 说明
/etc/exports NFS 服务器端需要设定的内容,其作用是设定谁拥有什么样的权限去访问此服务器的哪个目录
/var/lib/nfs/etab 无需设定,用于记录 NFS 服务器完整的权限设定,exports 中没有设定的缺省值也会被列出
/var/lib/nfs/xtab 记录 NFS 连接的相关信息
/usr/sbin/exportfs NFS 设定管理命令,用于 Server 侧设定,通过此条命令使得 exports 的设定变得有效或者无效
/usr/sbin/showmount 用于显示 NFS 设定的相关信息,Server 端和 Client 端均可

配置文件 /etc/exports

我们可以按照 “共享目录的路径 允许访问的NFS客户端(共享权限参数)” 的格式,定义要共享的目录与相应的权限

常用参数 作用
ro 只读
rw 读写
root_squash 当NFS客户端以root管理员访问时,映射为NFS服务器的匿名用户
no_root_squash 当NFS客户端以root管理员访问时,映射为NFS服务器的root管理员
all_squash 无论NFS客户端使用什么账户访问,均映射为NFS服务器的匿名用户
sync 同时将数据写入到内存与硬盘中,保证不丢失数据
async 优先将数据保存到内存,然后再写入硬盘;这样效率更高,但可能会丢失数据
secure 这个选项是缺省选项,它使用了 1024 以下的 TCP/IP 端口实现 NFS 的连接
insecure 禁止使用了 1024 以下的 TCP/IP 端口实现 NFS 的连接
no_wdelay 这个选项关闭写延时,如果设置了 async ,那么 NFS 就会忽略这个选项
nohide 如果将一个目录挂载到另外一个目录之上,那么原来的目录通常就被隐藏起来或看起来像空的一样。要禁用这种行为,需启用 hide 选项
no_subtree_check 这个选项关闭子树检查,子树检查会执行一些不想忽略的安全性检查,缺省选项是启用子树检查
no_auth_nlm 这个选项也可以作为 insecure_locks 指定,它告诉 NFS 守护进程不要对加锁请求进行认证。如果关心安全性问题,就要避免使用这个选项。缺省选项是 auth_nlm 或 secure_locks
mp(mountpoint=path) 通过显示地声明这个选项,NFS 要求挂载所导出的目录
fsid=num 这个选项通常都在 NFS 故障恢复的情况中使用,如果希望实现 NFS 的故障恢复,请参考 NFS 文档
$ cat /etc/exports
/nfsfile 192.168.10.*(rw,sync,root_squash)
/tmp/serverdir 192.168.174.132(rw,sync,no_root_squash) 192.168.174.133(ro,sync,no_root_squash)

最佳实践

安装 NFS 服务

NFS 服务端安装 nfs-utils,rpcbind 会被作为依赖而安装

$ yum install nfs-utils -y

创建共享目录

在 NFS 服务端,建立用于 NFS 文件共享的目录,设置足够的权限确保其他人也有写入权限

$ mkdir /nfs-dir && chown -R nobody.nobody /nfs-dir

编辑配置文件

编辑配置文件 /etc/exports ,我们可以按照 “共享目录的路径 允许访问的NFS客户端(共享权限参数)” 的格式,定义要共享的目录与相应的权限;编辑配置文件 /etc/sysconfig/nfs ,分配固定端口

$ cat <<EOF | tee /etc/exports
/nfs-dir 192.168.25.*(rw,sync,no_root_squash)
EOF

$ cat <<EOF | tee -a /etc/sysconfig/nfs
RQUOTAD_PORT=30001
LOCKD_TCPPORT=30002
LOCKD_UDPPORT=30002
MOUNTD_PORT=30003
STATD_PORT=30004
EOF

配置防火墙

查看 NFS 服务端口

$ rpcinfo -p localhost
   program vers proto   port  service
    100000    4   tcp    111  portmapper
    100000    3   tcp    111  portmapper
    100000    2   tcp    111  portmapper
    100000    4   udp    111  portmapper
    100000    3   udp    111  portmapper
    100000    2   udp    111  portmapper
    100024    1   udp  30004  status
    100024    1   tcp  30004  status
    100005    1   udp  30003  mountd
    100005    2   udp  30003  mountd
    100005    3   udp  30003  mountd
    100003    3   tcp   2049  nfs
    100003    4   tcp   2049  nfs
    100227    3   tcp   2049  nfs_acl
    100003    3   udp   2049  nfs
    100003    4   udp   2049  nfs
    100227    3   udp   2049  nfs_acl
    100021    1   udp  30002  nlockmgr
    100021    3   udp  30002  nlockmgr
    100021    4   udp  30002  nlockmgr
    100021    1   tcp  30002  nlockmgr
    100021    3   tcp  30002  nlockmgr
    100021    4   tcp  30002  nlockmgr

端口 1112049 是 portmapper 和 nfs 进程对应的端口,是程序指定的;其他端口是我们通过修改配置文件 /etc/sysconfig/nfs 指定的。

Firewalld 通过添加自定义服务开放所有 NFS 服务端口

$ cat <<EOF | tee /etc/firewalld/services/nfs-server.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>nfs-server</short>
  <description>nfs-server</description>
  <port protocol="tcp" port="111"/>
  <port protocol="udp" port="111"/> 
  <port protocol="tcp" port="2049"/>
  <port protocol="udp" port="2049"/>
  <port protocol="tcp" port="30002"/>
  <port protocol="tcp" port="30004"/>
  <port protocol="udp" port="30002-30004"/>
</service>
EOF
$ firewall-cmd --permanent --add-service=nfs-server
$ firewall-cmd --reload

启动和启用 NFS 服务程序

在启动 NFS 服务之前,还需要顺带重启并启用 rpcbind 服务程序,并将这两个服务一并加入开机启动项中

$ systemctl restart rpcbind
$ systemctl enable rpcbind

$ systemctl start nfs-server
$ systemctl enable nfs-server

NFS 客户端的配置

相关命令

showmount 命令

使用 showmount 命令查询 NFS 服务器的远程共享信息,showmount 命令输出格式为 “共享的目录名称 允许使用客户端地址

参数 作用
-e 显示 NFS 服务器的共享列表
-a 显示本机挂载的文件资源的情况 NFS 资源的情况
-v 显示版本号
exportfs 命令

维护 exports 文件导出的文件系统表的专用工具,可以修改配置之后不重启 NFS 服务

  • export -ar:重新导出所有的文件系统
  • export -au:关闭导出的所有文件系统
  • export -u FS: 关闭指定的导出的文件系统

查看 NFS 服务器端共享的文件系统

# showmount -e NFS-SERVER-IP
$ showmount -e 192.168.25.10
Export list for 192.168.25.10:
/nfs-dir 192.168.25.*

挂载服务端 NFS 文件系统到本地

NFS 客户端创建一个挂载目录,挂载服务端 NFS 文件系统到本地

# mount -t nfs NFS-SERVER-IP:/path/to/sharedfs  /path/to/mount_point
$ mkdir /aluopy
$ mount -t nfs 192.168.25.10:/nfs-dir /aluopy

# 查看客户端挂载信息
$ df -h /aluopy
文件系统                容量  已用  可用 已用% 挂载点
192.168.25.10:/nfs-dir   50G  1.8G   49G    4% /aluopy

配置 NFS 开机自动挂载

如果希望 NFS 文件共享服务能一直有效,则需要将其写入到 fstab 文件中

# NFS-SERVER-IP:/PATH/TO/EXPORTED_FS  /mount_point  nfs  defaults,_netdev  0  0
$ cat <<EOF | tee -a /etc/fstab
192.168.25.10:/nfs-dir /aluopy nfs defaults 0 0
EOF

参考链接

Tags: ,

Categories:

Updated: