NFS 原理
NFS(Network Files Network)网络文件系统,允许网络中主机通过通过 TCP/IP 进行资源共享。采用 C/S 工作模式,NFS 服务器相当于文件服务器,将某个目录设置为输出目录,客户端可将服务器端的输出目录挂载在本地进行访问。NFSv4 基于 TCP,端口号 2049。
RPC(Remote Procedure Call)远程过程调用,是一种通过网络从远程计算机程序上请求服务,跨越了传输层和应用层的协议。
NFS 在传输数据时使用的端口会随机选择,而客户端是通过 RPC 知道服务器端使用的哪个端口传输数据。NFS 的 RPC 主要功能是记录每个 NFS 功能对应的端口号,并在 NFS 客户端请求时将该端口和功能信息传给该客户端,确保客户端连到正确的端口。
当 NFS 服务启动时会随即取用若干端口,并主动向 RPC 服务注册这些端口,然后 RPC 使用固定的 111 端口监听 NFS 客户端请求,并将正确的端口信息返回给客户端。
注: 在启动 NFS 之前先要启动 RPC 服务,否则 NFS 无法向 RPC 注册,若 RPC 重启则原来注册的数据就全部丢失,NFS 也需重启以重新注册 RPC。
- 用户访问 web 页面,web 服务器上的 nfs 客户端便会向后端的 NFS 服务器通过 rpc 服务发出请求。
 - nfs 服务器端 rpc 找到对应注册的 nfs 端口后,通知 nfs 客户端的 rpc
 - nfs 客户端得到了服务器端的取数据的端口,与 nfs daemon 连接存取数据
 - nfs 客户端在将得到的文件传给前端
 
NFS 局限:
- 存在单点故障,可通过高可用集群解决
 - 高并发场景,NFS 性能有限
 - 客户端认证基于 IP 和主机名,安全性一般
 - NFS 传输明文,不对数据完整性验证
 - 多台客户端挂载一个 NFS 时,耦合度高,管理维护麻烦
 
NFS 基础配置
环境:
- 两台虚拟机
192.168.163.103/24
192.168.163.104/24 - 系统:CentOS7
 - Selinux:关闭
 - 防火墙:关闭
 
服务器端
NFS 服务依赖于 RPC 服务与外界通信,所以需要安装 rpcbind 程序
而 NFS
- 安装 NFS 主程序和 RPC 程序
yum install nfs-utils rpcbindsystemctl enable nfs-serversystemctl start nfs-server rpcbind.service - 配置文件
/etc/exports 
可通过rpcinfo -p localhost查看已注册的端口
# rpcinfo -p localhost  | 
nfs 相关进程
- rpc.statd:检查文件一致性
 - rpc.idmapd:名字映射
 - rpc.mountd:权限管理验证(nfs mount daemon)
 - nfsd:NFS 主进程,管理登入,ID 身份判明等
 
/etc/exports文件配置
# 格式为:共享目录 分享给的主机1(参数) 主机2(参数) ...  | 
参数列表
| 参数 | 含义 | 
|---|---|
| ro | 客户端只读 | 
| rw | 客户端可读写 | 
| sync | 数据同步写入内存与磁盘,保证数据一致性,效率低 | 
| async | 异步 IO,数据先暂时存与内存,待需要时写入硬盘,效率高,但数据丢失风险高 | 
| noaccess | 阻止访问该目录及其子目录 | 
| all_squash | 无论 NFS 客户端使用什么用户访问,都映射为 NFS 服务器端的匿名用户,即 nfsnobody | 
| root_squash | 当 NFS 客户端使用 root 访问时,映射为 NFS 服务器端的匿名用户,即 nfsnobody | 
| no_root_squash | 当 NFS 客户端使用 root 访问时,仍映射为 NFS 服务器端的 root,并不安全 | 
| wdelay | 为合并多次更新而延迟写入磁盘 | 
| no_wdelay | 尽可能快地写入磁盘 | 
| secure | 限制 nfs 服务只能使用小于 1024 的 TCP/IP 端口传输数据 | 
| insecure | 可使用大于 1024 的端口 | 
| anounuid | 指定 NFS 服务器中的用户为匿名用户 | 
| anoungid | 指定 NFS 服务器中的用户组为匿名用户组 | 
默认情况下,nfs 服务会禁止客户端的 root 用户对共享目录进行写操作,目的是为了保证当 nfs 以共享目录工作时,共享目录的数据不会被客户端随意修改,但是当 nfs 以远程存储工作时,这个功能就不合理,所以当 nfs 以远程存储来工作时,需要在服务端设置 no_root_squash 选项关闭该功能。

配置完后使用exportfs -rv命令,不需要重启 NFS。
exportfs  | 
nfsstat命令可查看当前 NFS 信息
nfsstat  | 
若开启了 firewalld,则需要放行 nfs 和 rpcbind 还有 mountd 服务,放行端口 2049
firewall-cmd --permanent --add-service=nfs  | 
NFS 客户端
- 需要安装
nfs-utils rpcbindyum install nfs-utils rpcbind - 通过
showmount查看 NFS 服务器的共享信息 
showmount [options] [NFS服务器]  | 
# showmount -e 192.168.163.102  | 
- 挂载到本机
 
# mkdir /nfsshare #创建挂载目录  | 
在 mount 时也可使用-o指定文件系统的选项
rsize= 从NFS服务器读文件时每次使用的字节数,默认1024字节  | 
也可通过配置文件/etc/fstab开机自动挂载
# vim /etc/fstab  | 
使用 mount 或配置文件/etc/fstab 挂载的不足:NFS 服务器与客户端的连接不是永久的,任何一方的掉线都会导致另一方等待超时。并且即使很多用户都挂载了共享目录,也会有大部分的用户在大部分时间是不会使用的,这样造成了 NFS 服务器资源的大量消耗。可通过 autofs 服务按需动态挂载解决该问题。
- 使用 autofs 自动挂载
autofs 是一个提供按需挂载的服务,只有在用户访问该挂载点时才会动态挂载该共享目录。
安装 autofs 程序,并开机自启yum install autofssystemctl enable autofs.servicesystemctl start autofs.service
创建 autofs 关于 nfs 主配置文件,也可以直接在 autofs 的主配置文件/etc/auto.master中添加内容。 
# vim /etc/auto.master.d/nfs.autofs  | 
创建 nfs 配置的映射文件/etc/nfs.misc
# vim /etc/nfs.misc  | 
配置完成后重启 autofs 服务即可。
进入/nfs目录中,查看并无内容。然后进入share便可查看到挂载目录的内容。再通过df查看,已成功挂载。
注:由于在客户端挂载时也会指定选项,若与服务器端选项不同,在执行操作时可能会报错,即:选项以服务器端配置为准。
nfs 挂载优化
系统安全相关
对企业一般来说,NFS 只共享静态数据,不需要 suid、exec 权限,不应允许执行命令。所以在挂载时应该指定以下参数
mount -t nfs -o nosuid,noexec,nodev,rw 10.0.0.1:/data /mnt  | 
挂载性能相关
- 禁止更新目录及文件时间戳挂载
mount -t nfs -o noatime,nodiratime 10.0.0.1:/data
 - 安全加优化
mount -t nfs -o nosuid,noexec,nodev,noatime,nodiratime,intr,rsize=131072,wsize=131072 10.0.0.1:/data /mnt
rsize 为 nfs 客户端读 server 的数据块大小,wsize 为 nfs 客户端写 server 的数据块大小,最好设为 1024 的倍数
配置这两个参数可以让一次读写更多数据包,提高访问性能 - 内核层面优化
net.core.wmem_default:接受套接字缓冲区大小的默认值,默认为 124928net.core.rmem_default:发送套接字缓冲区大小的默认值,默认为 124928net.core.rmem_max:接受套接字缓冲区大小的最大值,默认同上net.core.wmem_max:发送套接字缓冲区大小的最大值,默认同上
可以将这些参数调大