NFS 服务器总结:概念、原理、配置与实战详解

一、NFS 概述

NFS(Network File System,网络文件系统) 是一种经典的网络文件共享技术,允许客户端像访问本地文件一样透明地访问远程服务器上的文件资源。它由 Sun Microsystems 在 20 世纪 80 年代开发,最初用于 UNIX 系统间的文件共享。

1.1 版本演进

版本 特点
NFSv2 早期版本,支持 32 位文件偏移,文件大小限制为 2GB
NFSv3 应用最广泛,支持 64 位文件大小、异步写入、更强的性能和可靠性
NFSv4 引入状态化连接、强安全性(Kerberos)、文件锁改进、复合操作(减少 RPC 调用)

1.2 NFS 核心架构

  • NFS 服务器:存储文件资源,运行 NFS 守护进程,监听客户端请求,维护共享目录权限。
  • NFS 客户端:通过挂载(mount)将远程共享目录集成到本地文件系统,之后可像操作本地文件一样读写、创建、删除。

1.3 工作原理(基于 RPC)

NFS 使用 RPC(Remote Procedure Call,远程过程调用) 机制,工作流程如下:

  1. 注册阶段:NFS 服务启动时向 RPC 服务注册端口(rpcbindportmap)。
  2. 连接建立:客户端向 RPC 服务器查询 NFS 服务的端口。
  3. 挂载阶段:客户端发起挂载请求,服务器验证身份和权限,通过后允许挂载。
  4. 文件访问:客户端对远程文件的操作(读/写)通过 RPC 转换为对服务器的远程调用,服务器执行并返回结果。
  5. 权限控制:基于 UNIX 的 UID/GID 进行文件权限检查。

1.4 数据传输特点

  • 无状态性(NFSv3 及之前):服务器不保存客户端状态,故障恢复简单。
  • 支持 UDP 和 TCP:UDP 适合实时性要求高但可靠性要求低的场景;TCP 更可靠,现代网络常用 TCP。

1.5 NFS 优势与局限

优势 局限
透明性:访问远程文件如同本地文件 安全性较弱(早期版本无加密和强认证)
跨平台:Linux、UNIX、macOS 等 强依赖网络,延迟和丢包影响性能
高效:优化的传输和缓存 文件锁机制复杂,多客户端并发易不一致
易管理:配置简单,集中管理 无状态协议下文件锁需额外机制

1.6 典型应用场景

  • 企业内部文件共享(办公文档、软件包)
  • Web 服务器集群共享存储(统一网站代码和附件)
  • 数据库集群备份与共享
  • 嵌入式设备(路由器、NAS)简单文件共享

二、NFS 服务部署实验

2.1 实验环境规划

节点名称 IP 地址 作用
nfs-server 10.1.8.20/24 NFS 服务器,提供共享存储
nfs-client1 10.1.8.21/24 NFS 客户端(Web 服务器1)
nfs-client2 10.1.8.22/24 NFS 客户端(Web 服务器2)

2.2 服务器端部署步骤

2.2.1 安装软件包
# 安装 nfs-utils(提供 NFS 服务端工具和守护进程)
[root@nfs-server ~]# yum install -y nfs-utils

# 安装 httpd(仅用于后续测试 Web 共享场景,非 NFS 必需)
[root@nfs-server ~]# yum install -y httpd
2.2.2 准备共享目录
# 创建共享目录(作为挂载点供客户端使用)
[root@nfs-server ~]# mkdir -p /shares/webapp

# 修改目录所有者为 apache 用户(UID 48),以便与 Web 服务配合
[root@nfs-server ~]# chown apache:apache /shares/webapp
2.2.3 启动 NFS 服务并配置防火墙
# 启用并立即启动 nfs-server 服务(以及相关的 rpcbind、nfs-idmapd 等)
[root@nfs-server ~]# systemctl enable nfs-server --now

# 为简化实验,直接关闭防火墙(生产环境建议开放特定端口)
[root@nfs-server ~]# systemctl stop firewalld
[root@nfs-server ~]# systemctl disable firewalld   # 可选,防止重启后再次开启

生产环境中应开放 nfsrpc-bindmountd 等服务端口,而不是直接关闭防火墙。

2.2.4 配置 NFS 导出(/etc/exports)

/etc/exports 是 NFS 服务器的主配置文件,每一行定义:共享目录 客户端(选项)

# 编辑配置文件
[root@nfs-server ~]# vim /etc/exports

# 示例:将 /shares/webapp 共享给 10.1.8.0/24 网段的所有客户端
# 选项 rw:允许读写;no_root_squash:不将客户端的 root 用户映射为匿名用户
/shares/webapp 10.1.8.0/24(rw,no_root_squash)

常用导出选项说明:

选项 含义
ro 只读(默认)
rw 读写
sync 同步写入(保证数据一致性,默认)
async 异步写入(性能好,但掉电可能丢数据)
no_root_squash 客户端的 root 用户映射为服务器的 root 用户(谨慎使用)
root_squash 客户端的 root 用户映射为匿名用户 nfsnobody(默认,更安全)
all_squash 所有用户都映射为匿名用户
anonuid/anongid 指定匿名用户的 UID/GID

客户端指定方式示例:

# 单主机
/shares/webapp 10.1.8.21(rw)
# 域名(支持通配符)
/shares/webapp *.laogao.cloud(rw)
# 多个客户端混合
/shares/webapp 10.1.8.0/24(rw) client.example.com(ro)
2.2.5 重新加载 NFS 配置
# 重新加载 /etc/exports,不中断已有连接
[root@nfs-server ~]# systemctl reload nfs-server
2.2.6 验证 NFS 导出
# 查看当前导出的目录及客户端
[root@nfs-server ~]# exportfs
/shares/webapp  10.1.8.0/24

# 显示详细选项(包括默认选项)
[root@nfs-server ~]# exportfs -v
/shares/webapp  10.1.8.0/24(sync,wdelay,hide,no_subtree_check,sec=sys,rw,secure,no_root_squash,no_all_squash)

2.3 客户端部署步骤

2.3.1 安装客户端软件包
# 在两个客户端上分别执行(nfs-client1 和 nfs-client2)
[root@nfs-client1 ~]# yum install -y nfs-utils httpd

# 查看 apache 用户的 UID/GID(应与服务端一致,即 48)
[root@nfs-client1 ~]# id apache
uid=48(apache) gid=48(apache)=48(apache)

# 启动 httpd 服务(客户端也将作为 Web 服务器)
[root@nfs-client1 ~]# systemctl enable httpd --now
2.3.2 查看服务器导出的共享
# showmount -e 服务器IP:列出 NFS 服务器导出的所有共享目录
[root@nfs-client1 ~]# showmount -e 10.1.8.20
Export list for 10.1.8.20:
/shares/webapp 10.1.8.0/24
2.3.3 手动挂载 NFS 共享
# 将服务器的 /shares/webapp 挂载到客户端的 Web 根目录 /var/www/html
[root@nfs-client1 ~]# mount -t nfs 10.1.8.20:/shares/webapp /var/www/html

# 验证挂载结果
[root@nfs-client1 ~]# df -h | grep www
10.1.8.20:/shares/webapp   50G  4.9G   46G  10% /var/www/html
2.3.4 测试共享文件一致性

nfs-client1 上创建文件:

[root@nfs-client1 ~]# touch /var/www/html/xiyangyang

nfs-client2 上查看:

[root@nfs-client2 ~]# ls /var/www/html/
xiyangyang

可以看到文件同步出现,证明两个客户端挂载的是同一个后端共享存储。

2.3.5 Web 内容共享测试

在 NFS 服务器上创建 index.html:

[root@nfs-server ~]# echo "xixihahaheihei - from NFS server" > /shares/webapp/index.html

在客户端1和客户端2上通过浏览器或 curl 访问:

[root@nfs-client1 ~]# curl http://localhost/index.html
xixihahaheihei - from NFS server
# 客户端2 同理返回相同内容

2.4 权限测试(root_squash 影响)

默认情况下,NFS 启用 root_squash,将客户端的 root 用户映射为匿名用户 nfsnobody,因此 root 无法在共享目录中创建文件(除非使用 no_root_squash 选项)。

2.4.1 修改服务器配置为 rw(不含 no_root_squash)
# 在 nfs-server 上修改 /etc/exports
[root@nfs-server ~]# vim /etc/exports
/shares/webapp 10.1.8.0/24(rw)

# 重新加载配置
[root@nfs-server ~]# systemctl reload nfs-server
2.4.2 客户端 root 用户测试
# 在客户端以 root 身份尝试创建文件
[root@nfs-client1 ~]# touch /var/www/html/file1
touch: cannot touch '/var/www/html/file1': Permission denied
# 失败,因为 root 被映射为 nfsnobody,无写权限
2.4.3 客户端 apache 用户测试
# 切换到 apache 用户(UID 48,与服务端目录所有者一致)
[root@nfs-client1 ~]# su -l -s /bin/bash apache
-bash-4.2$ echo "apache website" > /var/www/html/web1.html
-bash-4.2$ exit

此时 web1.html 文件创建成功,因为 apache 的 UID 48 在服务端拥有写权限。

2.5 持久化挂载(/etc/fstab)

为了让客户端重启后自动挂载 NFS 共享,将挂载信息写入 /etc/fstab

# 编辑 /etc/fstab,添加以下行
[root@nfs-client1 ~]# vim /etc/fstab
10.1.8.20:/shares/webapp  /var/www/html  nfs  defaults  0 0
  • defaults:使用默认挂载选项(rw, suid, dev, exec, auto, nouser, async)
  • 建议添加 _netdev 选项,确保网络可用后再挂载:nfs defaults,_netdev 0 0
# 重启测试自动挂载
[root@nfs-client1 ~]# reboot
# 重启后检查
[root@nfs-client1 ~]# df -h | grep www
10.1.8.20:/shares/webapp   50G  4.9G   46G  10% /var/www/html

三、NFS 高级配置与优化(拓展)

3.1 NFS 性能调优

参数 说明 建议值
rsize / wsize 读写块大小 8192~32768 字节(与网络 MTU 匹配)
hard / soft 挂载失败时的行为:hard 会一直重试,soft 返回错误 通常使用 hard,intr
timeo 重试超时时间(十分之一秒) 600(60秒)
retrans 重试次数 3~5
noatime 不更新文件访问时间,减少写操作 推荐添加

示例挂载:

mount -t nfs -o rsize=32768,wsize=32768,hard,intr,noatime 10.1.8.20:/shares/webapp /var/www/html

3.2 NFSv4 配置(增强安全)

NFSv4 不再需要 rpcbind,且支持 Kerberos 认证。配置示例:

# 在 /etc/nfs.conf 中设置
[nfsd]
vers4=yes
vers4.0=yes

# 导出时使用 fsid=0 定义根目录
/etc/exports:
/shares  *(rw,fsid=0,no_subtree_check)
/shares/webapp  10.1.8.0/24(rw)

客户端挂载:

mount -t nfs4 10.1.8.20:/webapp /var/www/html

3.3 常见故障排查

问题 检查方法
mount.nfs: No route to host 检查服务器防火墙是否开放端口(111, 2049, 随机端口)
Permission denied 检查 /etc/exports 选项(是否缺少 rwno_root_squash),检查目录权限
showmount -e 无输出 检查 rpcbind 服务是否运行,exportfs -v 查看导出是否正确
挂载后文件属主为 nobody 检查客户端和服务端 UID 是否一致,或使用了 root_squash
客户端重启后挂载失败 检查 /etc/fstab 中是否有 _netdev 选项,iscsi 网络服务是否先启动

四、总结

通过本实验,我们掌握了:

  • ✅ NFS 的基本概念、架构和工作原理(RPC、挂载、文件访问)
  • ✅ NFS 服务器配置:安装 nfs-utils,准备共享目录,编辑 /etc/exports,启动服务,开放防火墙
  • ✅ NFS 客户端配置:安装 nfs-utils,使用 showmount 查看导出,用 mount 挂载 NFS 共享
  • ✅ 权限管理:root_squashno_root_squash 的区别,以及如何利用一致的 UID 实现协同
  • ✅ 持久化挂载(/etc/fstab 添加 _netdev 选项)
  • ✅ NFS 共享存储的典型场景:Web 服务器集群共享代码和资源

NFS 作为经典的网络文件系统,因其简洁、高效、跨平台等优势,在现代 IT 基础设施中仍扮演着重要角色。尤其在虚拟化环境、容器持久化存储、企业内部文件共享等领域,NFS 依然是简单可靠的解决方案。对于更高性能和更复杂的功能需求,可以结合 NFSv4、Kerberos 认证、RSYNC 备份、分布式文件系统(如 GlusterFS、Ceph)等进一步扩展。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐