
NFS(网络文件系统)是一种分布式文件系统协议,允许您在服务器上挂载远程目录。这使您能够管理位于不同位置的存储空间,并支持从多个客户端向该空间写入数据。NFS 提供了一种相对标准且高性能的网络远程系统访问方式,非常适合需要频繁访问共享资源的场景。
本教程将详细介绍如何在 Ubuntu 系统上安装 NFS 服务器与客户端软件、配置 NFS 导出目录、设置 NFS 挂载点,并通过 fstab 条目创建持久化 NFS 挂载。
注:本教程已在 Ubuntu 20.04、22.04 和 24.04 版本中验证通过,所涉及的软件包名称、命令及配置文件在这些版本中均保持兼容。
本文核心要点
- NFS 通过允许多个客户端服务器通过网络访问单个主机服务器共享的目录,实现了集中式存储。
- 搭建 NFS 需要安装两个软件包:主机端需安装 nfs-kernel-server,客户端需安装 nfs-common。
- 安全配置通过 /etc/exports 文件实现,需在该文件中指定共享的目录及允许访问的客户端 IP 地址。
- 防火墙规则对限制 NFS 仅允许授权客户端访问至关重要,通常使用 UFW 放行来自特定 IP 地址的 2049 端口。
- 持久化挂载需在 /etc/fstab`中添加相应条目,以确保系统重启后 NFS 共享能自动重连。
为实现最佳性能,建议为 NFS 服务器和客户端均配置具备 10 Gbit 网络的 DigitalOcean 高级专用服务器( Premium Dedicated Droplets)。使用 10 Gbit 网络可使 NFS 性能接近已公布的存储卷最高传输速率。
开发前的准备
本教程将使用两台服务器,其中一台将其文件系统的部分目录共享给另一台。要完成本教程,您需要:
两台 Ubuntu 服务器。每台服务器应具备以下条件:
- 拥有具备 sudo 权限的非 root 用户
- 已使用 UFW 设置防火墙
- (若可用)已配置私有网络
如需了解如何设置具备 sudo 权限的非 root 用户及防火墙,请参照我们曾经发布的文章《Ubuntu 初始服务器设置教程》。
如果您使用 DigitalOcean Droplet 作为服务器和客户端,可参阅我们关于《如何选择适合自己团队的服务器配置》的文档,了解更多私有网络设置信息。有关防火墙配置的更多说明,请查看《如何在 Ubuntu 上使用 UFW 设置防火墙》。
本教程中,我们将共享目录的服务器称为主机,挂载这些目录的服务器称为客户端。您需要知道两者的 IP 地址,并确保(若可用)使用私有网络地址。
在下文中,我们将用占位符 host_ip 和 client_ip 指代这些 IP 地址,请根据需要替换为实际地址。
步骤 1 — 下载并安装组件
我们首先在两台服务器上安装必要的 NFS 组件。
在主机上
在主机服务器上安装 nfs-kernel-server 软件包,该软件包允许您共享目录。由于这是本次会话中首次使用 apt 进行操作,请在安装前刷新本地软件包索引:
sudo apt update
sudo apt install nfs-kernel-server
安装完成后,切换到客户端服务器。
在客户端上
在客户端服务器上,我们需要安装 nfs-common 软件包(也称为 nfs-utils),它提供 NFS 客户端功能,不包含任何服务器组件。同样,请在安装前刷新本地软件包索引,以确保获取最新信息:
sudo apt update
sudo apt install nfs-common
现在两台服务器均已安装必要软件包,我们可以开始进行配置。
步骤 2 — 在主机上创建共享目录
我们将共享两个独立的目录,并采用不同的配置设置,以说明在超级用户访问权限方面配置 NFS 挂载的两种关键方式。
超级用户可以在其系统上的任何位置执行任何操作。然而,NFS 挂载的目录并非挂载它们的目标系统的一部分,因此默认情况下,NFS 服务器会拒绝执行需要超级用户权限的操作。这一默认限制意味着,客户端的超级用户无法以 root 身份写入文件、重新分配所有权或在 NFS 挂载上执行任何其他超级用户任务。
但有时,客户端系统上存在可信用户,他们需要在挂载的文件系统上执行这些操作,却不需要在主机上拥有超级用户访问权限。你可以配置 NFS 服务器来允许此类操作,尽管这会引入一定的风险,因为这样的用户可能获得对整个主机系统的 root 访问权限。
示例 1:导出通用挂载
在第一个示例中,我们将创建一个通用型 NFS 挂载,它利用默认的 NFS 行为,使得客户端机器上拥有 root 权限的用户难以利用这些客户端超级用户权限与主机进行交互。你可能使用类似这样的配置来存储通过内容管理系统上传的文件,或者为用户创建共享项目文件的空间。
首先,创建共享目录:
sudo mkdir /var/nfs/general -p
由于我们使用 sudo 创建它,该目录归主机的 root 用户所有:
ls -la /var/nfs/general
输出:
drwxr-xr-x 2 root root 4096 May 14 18:36 .
作为一种安全措施,NFS 会将客户端上的任何 root 操作转换为 nobody:nogroup 凭证。因此,我们需要更改目录的所有权以匹配这些凭证。
sudo chown nobody:nogroup /var/nfs/general
现在,该目录已准备就绪,可以导出。
示例 2:导出主目录
在我们的第二个示例中,目标是让存储在主机上的用户主目录能够在客户端服务器上可用,同时允许那些客户端服务器的可信管理员获得他们便捷管理用户所需的访问权限。
为此,我们将导出 /home 目录。由于该目录已存在,我们无需创建。我们也不会更改其权限。如果更改,可能会给主机上任何拥有主目录的用户带来一系列问题。
步骤 3 — 在主机服务器上配置 NFS 导出
接下来,我们将深入 NFS 配置文件来设置这些资源的共享。
在主机上,使用具有 root 权限的文本编辑器打开 /etc/exports 文件:
sudo nano /etc/exports
该文件包含注释,展示了每行配置的基本结构。语法如下:
/etc/exports
directory_to_share client(share_option1,...,share_optionN)
我们需要为计划共享的每个目录创建一行配置。请务必将此处的 client_ip 占位符替换为您的实际 IP 地址:
/etc/exports
/var/nfs/general client_ip(rw,sync,no_subtree_check)
/home client_ip(rw,sync,no_root_squash,no_subtree_check)
在此,我们对两个目录使用了相同的配置选项,除了 no_root_squash。让我们逐一了解这些选项的含义:
- rw:此选项赋予客户端计算机对该卷的读写权限。
- sync:此选项强制 NFS 在响应前先将更改写入磁盘。由于响应反映了远程卷的实际状态,这能带来更稳定、一致的环境,但也会降低文件操作速度。
- no_subtree_check:此选项禁用子树检查。子树检查是指在每个请求中,主机必须检查文件是否在导出树中仍然实际可用。当客户端打开文件时对其重命名,可能会导致许多问题。在几乎所有情况下,最好禁用子树检查。
- no_root_squash:默认情况下,NFS 会将远程 root 用户的请求转换为服务器上的非特权用户。这原本是作为一种安全特性,旨在防止客户端上的 root 账户以 root 身份使用主机的文件系统。no_root_squash 会为特定共享禁用此行为。
完成更改后,保存并关闭文件。然后,为了使配置的客户端能够访问共享,使用以下命令重启 NFS 服务器:
sudo systemctl restart nfs-kernel-server
但在实际使用新共享之前,您需要确保防火墙规则允许访问共享的流量。
步骤 4 — 调整主机防火墙设置
首先,我们检查防火墙状态,确认其是否已启用,并查看当前允许的规则:
sudo ufw status
输出:
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
在我们的系统中,当前仅允许 SSH 流量通过,因此需要为 NFS 流量添加规则。
对于许多应用程序,您可以使用 sudo ufw app list 并按名称启用它们,但 nfs 不在此列。不过,由于 ufw 还会检查 /etc/services 中服务的端口和协议信息,我们仍可按名称添加 NFS 规则。最佳实践建议启用限制最严格但仍允许所需流量的规则,因此我们将明确指定来源,而不是允许来自任意地址的流量。
使用以下命令在主机上开放 2049 端口(请务必将 client_ip 替换为您的客户端 IP 地址):
sudo ufw allow from client_ip to any port nfs
您可以通过以下命令验证更改:
sudo ufw status
输出中应显示允许来自 2049 端口的流量:
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
2049 ALLOW 203.0.113.24
OpenSSH (v6) ALLOW Anywhere (v6)
这确认了 UFW 将仅允许来自我们客户端机器的 2049 端口 NFS 流量。
步骤 5 — 在客户端创建挂载点并挂载目录
现在主机服务器已配置完成并开始提供共享,我们将准备客户端环境。
为了使远程共享在客户端可用,我们需要将主机上要共享的目录挂载到客户端的空目录中。
注意:如果挂载点中已存在文件和目录,在挂载 NFS 共享后它们将被隐藏。为避免重要文件丢失,请确保用于挂载的目录(如果已存在)是空的。
我们将为挂载位置创建两个目录:
sudo mkdir -p /nfs/general
sudo mkdir -p /nfs/home
现在我们已经有了存放远程共享的位置,并且防火墙已放行,接下来可以使用主机服务器的 IP 地址挂载共享:
sudo mount host_ip:/var/nfs/general /nfs/general
sudo mount host_ip:/home /nfs/home
从客户端挂载 NFS 共享时,可使用 -o nconnect=n 参数来提升特定工作负载的 IOPS。其中 "n" 代表该客户端与目标 NFS 服务器之间建立的连接数,取值范围为 1 到 16。您可以尝试不同的 nconnect 值以找到最适合您工作负载的配置,建议从 8 开始尝试。设置 nconnect 参数可能为某些工作负载(特别是小文件写入操作)带来轻微的 IOPS 提升。
这些命令会将主机上的共享目录挂载到客户端机器上。您可以通过多种方式确认挂载是否成功。虽然可以使用 mount 或 findmnt 命令检查,但 df -h 命令的输出更易读:
df -h
输出:
Filesystem Size Used Avail Use% Mounted on
udev 474M 0 474M 0% /dev
tmpfs 99M 936K 98M 1% /run
/dev/vda1 25G 1.8G 23G 8% /
tmpfs 491M 0 491M 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 491M 0 491M 0% /sys/fs/cgroup
/dev/vda15 105M 3.9M 101M 4% /boot/efi
tmpfs 99M 0 99M 0% /run/user/1000
10.132.212.247:/var/nfs/general 25G 1.8G 23G 8% /nfs/general
10.132.212.247:/home 25G 1.8G 23G 8% /nfs/home
我们挂载的两个共享都显示在输出底部。由于它们从同一个文件系统挂载,因此显示的磁盘使用情况相同。要查看每个挂载点下实际使用了多少空间,请使用磁盘使用命令 du 并指定挂载路径。-s 标志可显示使用情况摘要而非每个文件的详细使用情况,-h 标志则输出人类可读的格式。
例如:
du -sh /nfs/home
输出:
36K /nfs/home
这表明整个主目录的内容仅使用了 36K 的可用空间。
步骤 6 — 测试 NFS 访问权限
接下来,我们将通过向两个共享目录写入内容来测试访问权限。
示例 1:通用共享目录
首先,在 /var/nfs/general 共享中创建一个测试文件:
sudo touch /nfs/general/general.test
然后,检查其所有权:
ls -l /nfs/general/general.test
输出:
-rw-r--r-- 1 nobody nogroup 0 Aug 1 13:31 /nfs/general/general.test
由于我们在挂载此卷时未更改 NFS 的默认行为,并且通过 sudo 命令以客户端机器的 root 用户身份创建了文件,因此文件所有权默认归 nobody:nogroup。客户端超级用户在此 NFS 挂载的共享上将无法执行典型的管理操作,例如更改文件所有者或为用户组创建新目录。
示例 2:主目录共享
为了比较通用共享目录与主目录共享的权限差异,以相同方式在 /nfs/home 中创建一个文件:
sudo touch /nfs/home/home.test
然后查看该文件的所有权:
ls -l /nfs/home/home.test
输出:
-rw-r--r-- 1 root root 0 Aug 1 13:32 /nfs/home/home.test
我们同样使用 sudo 命令以 root 身份创建了 home.test 文件,这与创建 general.test 文件的方式完全相同。然而,在这种情况下,文件归 root 所有,因为我们在挂载时通过指定 no_root_squash 选项覆盖了默认行为。这使得客户端机器上的 root 用户可以以 root 身份操作,从而大大方便了用户账户的管理。同时,这也意味着我们无需在主机上为这些用户授予 root 访问权限。
步骤 7 — 开机自动挂载远程 NFS 目录
我们可以通过将 NFS 挂载添加到客户端的 /etc/fstab 文件来创建持久化挂载。这可以确保 NFS 共享在系统启动时自动挂载。
使用具有 root 权限的文本编辑器打开此文件:
sudo nano /etc/fstab
在文件底部,为每个共享添加一行配置。配置行如下所示:
/etc/fstab
. . .
host_ip:/var/nfs/general /nfs/general nfs auto,nofail,noatime,nolock,intr,tcp,actimeo=1800 0 0
host_ip:/home /nfs/home nfs auto,nofail,noatime,nolock,intr,tcp,actimeo=1800 0 0
注意:您可以在 NFS 手册页中找到关于此处指定的选项的更多信息。可通过运行以下命令查看:
man nfs
客户端将在启动时自动挂载远程分区,但可能需要一些时间来建立连接并使共享可用。
步骤 8 — 卸载 NFS 远程共享
如果您不再希望远程目录挂载在系统上,可以通过离开共享目录结构并执行卸载操作来移除它,方法如下:
cd ~
sudo umount /nfs/home
sudo umount /nfs/general
请注意,该命令名为 umount,而非可能预期的 unmount。
执行后将移除远程共享,仅保留本地存储可访问:
df -h
输出:
Filesystem Size Used Avail Use% Mounted on
udev 474M 0 474M 0% /dev
tmpfs 99M 936K 98M 1% /run
/dev/vda1 25G 1.8G 23G 8% /
tmpfs 491M 0 491M 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 491M 0 491M 0% /sys/fs/cgroup
/dev/vda15 105M 3.9M 101M 4% /boot/efi
tmpfs 99M 0 99M 0% /run/user/1000
如果还希望防止下次重启时重新挂载,请编辑 /etc/fstab 文件,删除对应行或在行首添加 # 字符将其注释掉。您也可以通过移除 auto 选项来防止自动挂载,这样仍可手动挂载。
生产环境使用的其他注意事项
在生产环境中部署 NFS 时,请考虑以下最佳实践以确保稳定性、性能和安全性:
1. NFS 版本兼容性
确保客户端和服务器运行兼容版本。推荐使用 NFSv4,因为它简化了防火墙要求并改进了安全特性。
在挂载时强制使用特定版本:
sudo mount -t nfs -o vers=4 host_ip:/path /mountpoint
2. 性能优化参数
除了 nconnect 外,还可考虑以下选项:
- rsize=8192,wsize=8192:增加读/写缓冲区大小以提升吞吐量。
- async:提高写入性能,但崩溃时可能导致数据丢失。
- actimeo=1800:减少属性缓存频率。
3. 安全性增强
NFS 默认不加密数据。为保护您的设置:
- 仅在受信任的私有网络或 VPN 上使用 NFS。
- 除非必要,否则应用 root_squash 选项。
- 在 /etc/exports 中限制仅允许特定 IP 访问。
4. 日志记录与监控
监控 NFS 活动以进行审计或调试:
tail -f /var/log/syslog | grep nfs
或使用:
journalctl -u nfs-server
常见问题解答 (FAQs)
1. Linux 中的 NFS 挂载是什么?
NFS 挂载允许一个系统通过网络访问另一个系统共享的目录。它实现了 Linux/Unix 系统间的无缝文件共享,使远程目录如同本地目录一样可见。这在以下场景中特别有用:
- 在多个服务器间共享应用数据
- 集中存储以便于备份和管理
- 允许多个服务器访问相同文件
- 在网络中创建分布式文件系统
2. 如何在重启后保持 NFS 挂载?
您可以在客户端的 /etc/fstab 中添加挂载配置。以下是一个详细示例:
# 格式:host_ip:/shared_directory /mount_point nfs options 0 0
192.168.1.100:/var/nfs/general /nfs/general nfs auto,nofail,noatime,nolock,intr,tcp,actimeo=1800 0 0
主要选项及其说明:
- auto:启动时自动挂载
- nofail:挂载失败时不中断启动过程
- noatime:不更新访问时间(提高性能)
- nolock:禁用文件锁定(对某些应用有用)
- intr:允许硬挂载时中断
- tcp:使用 TCP 而非 UDP
- actimeo=1800:属性缓存 30 分钟
3. NFS 工作需要哪些端口?
NFS 需要多个端口用于不同版本和功能:
- 端口 2049 (TCP/UDP):主 NFS 通信
- 端口 111 (TCP/UDP):rpcbind(尤其 NFSv3 需要)
- 端口 20048 (TCP/UDP):NFS 挂载守护进程
- 端口 20049 (TCP/UDP):NFS 锁管理器
对于 NFSv4,仅需端口 2049,便于防火墙配置。
4. NFS 有哪些替代方案?
根据需求,存在多种替代方案:
5. 如何排查 NFS 挂载问题?
常见排查步骤:
检查 NFS 服务状态:
sudo systemctl status nfs-kernel-server # 主机
sudo systemctl status nfs-common # 客户端
验证导出配置:
sudo exportfs -v
检查挂载点:
df -h
mount | grep nfs
查看 NFS 日志:
tail -f /var/log/syslog | grep nfs
6. 如何保护 NFS 设置?
NFS 安全最佳实践:
- 使用 NFSv4 以增强安全性
- 在 /etc/exports 中限制仅允许特定 IP 访问
- 使用 root_squash 防止 root 访问
实施防火墙规则:
sudo ufw allow from client_ip to any port nfs
- 使用私有网络或 VPN
- 定期审计权限安全
7. 有哪些性能优化方案?
多种提升 NFS 性能的选项:
使用 nconnect 建立并行连接:
mount -t nfs -o nconnect=8 host_ip:/share /mountpoint
调整读/写缓冲区大小:
mount -t nfs -o rsize=8192,wsize=8192 host_ip:/share /mountpoint
- 使用 async 提升写入性能(需谨慎)
- 通过 actimeo 实现适当的缓存
- 考虑使用 10 Gbit 网络以提高吞吐量
8. 如何卸载 NFS 共享?
卸载 NFS 共享:
sudo umount /mountpoint
如果共享正忙:
sudo umount -f /mountpoint # 强制卸载
sudo umount -l /mountpoint # 延迟卸载
如果不想在重启后重新挂载,请记得删除或注释掉 /etc/fstab 中的对应行。
9. NFS 各版本有何区别?
NFS 各版本关键区别:
- NFSv3:
- 使用多个端口
- 需要 rpcbind
- 性能优于 v2
- 仍被广泛使用
- NFSv4:
- 单端口(2049)
- 安全性更好
- 性能更优
- 有状态协议
- 推荐用于新部署
- NFSv4.1:
- 并行 NFS (pNFS)
- 可扩展性更好
- 会话管理
- 高级功能
10. 如何监控 NFS 性能?
可用的工具:
nfsstat 查看 NFS 统计:
nfsstat -c # 客户端统计
nfsstat -s # 服务器统计
iostat 查看 I/O 统计:
iostat -x 1
- nfsiostat 查看 NFS 专用 I/O:
系统监控工具如 Prometheus 或 Grafana 配合 NFS 导出器
11. 常见的 NFS 挂载选项有哪些?
重要的挂载选项:
- rw/ro:读-写或只读
- sync/async:同步或异步写入
- no_root_squash:允许 root 访问
- no_subtree_check:禁用子树检查
- soft/hard:处理服务器不可用的方式
- intr:允许硬挂载时中断
- tcp/udp:传输协议
- vers:使用的 NFS 版本
使用多个选项的示例:
mount -t nfs -o rw,sync,no_subtree_check,vers=4 host_ip:/share /mountpoint
结论
在本教程中,我们创建了一个 NFS 主机,并通过创建两个不同的 NFS 挂载(与 NFS 客户端共享)演示了 NFS 的一些关键行为。
如果您计划在生产环境中实施 NFS,请注意该协议本身不提供加密。在私有网络上共享时,这可能不是问题。但在其他情况下,需要使用 VPN 或其他类型的加密隧道来保护数据。对于加密替代方案,可考虑使用 SSHFS 或建立 VPN 连接。
如果你正在考虑将 NFS 应用于你的 AI、Web 应用集群、媒体存储分发、持续集成/测试环境等业务上,或者你希望进一步了解 DigitalOcean 云平台为 NFS 优化的高性能存储方案与全球网络架构,欢迎咨询 DigitalOcean 中国区独家战略合作伙伴——卓普云 AI Droplet(aidroplet.com)。我们为企业客户提供从产品选型、架构设计到技术支持的全流程服务,助力你的业务稳定高效地运行在全球云端。



