《UNIX/Linux系统管理技术手册-读书笔记-第二十一章

网络文件系统(NFS)

1. NFS概述

1.1 NFS是什么

概念 说明 能做什么
NFS(网络文件系统) Sun Microsystems于1984年开发的分布式文件共享协议 在UNIX/Linux系统间透明地共享文件和目录
透明性 客户端应用程序使用与本地文件相同的系统调用 用户无需感知文件位于远程还是本地
并发控制 多个客户端同时访问同一文件时的冲突解决 支持共享读写(通过文件锁)

1.2 NFS vs SMB

对比 NFS SMB(Samba)
原生平台 UNIX/Linux Windows
适用场景 UNIX/Linux主导环境 混合环境(含Windows/macOS)
集成度 与UNIX权限模型天然契合 需额外软件包Samba
性能 局域网内表现优秀 同样优秀,但配置更复杂

💡 存储区域网络(SAN) 提供块级访问,而NFS/SMB提供文件级访问。SAN适合高性能需求,但并发管理需集群文件系统。

1.3 核心设计选择

设计维度 NFSv2/v3 NFSv4
状态 无状态(stateless) 状态化(stateful)
传输协议 UDP或TCP 仅TCP
挂载协议 独立(mountd) 集成在核心协议中
文件锁 外部(lockd/statd) 内置在核心协议中
安全 弱(AUTH_SYS) 强(RPCSEC_GSS/Kerberos)
防火墙友好 端口众多 单端口2049

状态化的意义:NFSv4服务器跟踪客户端打开的文件和锁,崩溃后可通过客户端恢复状态;但也增加了协议复杂性。

2. NFSv4伪文件系统

2.1 核心概念

概念 说明
伪文件系统 NFSv4服务器导出的虚拟目录树,仅包含被导出的目录,隐藏未导出部分
单根挂载 客户端只需挂载一次服务器的根,然后浏览所有导出目录
vs NFSv3 v3每个导出目录需单独挂载,需mountd守护进程

示例:服务器导出目录(粗体):

/www/domain1    ← 导出
/www/domain2    ← 导出
/www/domain3    ← 未导出
/var/logs/httpd ← 导出
/var/spool      ← 未导出

NFSv4客户端挂载后看到的伪文件系统:

/
├── www/
│   ├── domain1/
│   └── domain2/
└── var/
    └── logs/
        └── httpd/

2.2 FreeBSD特殊行为

FreeBSD的NFSv4实现并未完全遵循RFC的伪文件系统规范。如果指定了V4:根目录,该根下的所有文件和子目录(无论是否导出)都可能被客户端访问。切勿将服务器根目录/指定为V4根目录

3. 服务器端配置

3.1 导出文件位置

系统 配置文件
Linux /etc/exports
FreeBSD /etc/exports

3.2 Linux exports文件格式

基本语法directory client1(options) client2(options) ...

客户端规格

类型 示例
单个主机 hostname
通配符 *.example.com
IPv4网络 192.168.0.0/24
IPv6网络 2001:db8::/32
网络组 @groupname(NIS)

常见陷阱

1
2
3
4
5
# ❌ 错误:空格导致所有主机获得rw权限,*.example.com只读
/home *.example.com (rw)

# ✅ 正确
/home *.example.com(rw)

关键导出选项

选项 说明
ro 只读
rw 读写(默认)
root_squash 默认,将远程root映射为匿名用户(安全)
no_root_squash 危险,允许远程root正常访问
all_squash 所有用户都映射为匿名用户
anonuid=xxx / anongid=xxx 指定匿名映射的UID/GID
async 异步写入(性能↑,数据安全↓)
sync 同步写入(默认)
subtree_check 默认,验证文件在导出子树内
no_subtree_check 提高性能,但降低安全检查
sec=flavor 安全方法:sys(默认)、krb5krb5ikrb5p

3.3 FreeBSD exports文件格式

基本语法directory [options] host1 host2 ...

关键选项

选项 说明
-ro 只读
-alldirs 允许挂载文件系统内任何位置
-maproot=user 将远程root映射为指定用户
-mapall=user 将所有客户端用户映射为指定用户
-network net -mask mask 网络范围(IPv4)
-network net/cidr CIDR范围(IPv4/IPv6)
-sec=flavor 安全方法列表(按优先级)

NFSv4根配置(FreeBSD特有)

V4:/exports -sec=krb5p,krb5i,krb5,sys -network *.admin.com
/export/s/www -network *.admin.com

3.4 nfsd守护进程管理

操作 Linux FreeBSD
启动/停止 systemctl start/stop nfs-server service nfsd start/stop
重载导出 exportfs -a service mountd reload
禁用旧版本 -N2 -N3参数 -N2 -N3参数

nfsstat性能监控

1
2
nfsstat -s          # 服务器端统计
nfsstat -c          # 客户端统计
  • 超时率>3% → 检查网络或调整rsize/wsize
  • badxid≈timeout → 服务器响应慢 → 增加timeo参数

nfsd线程数调优

  • 线程数过少:nfsd常处于D状态(不可中断睡眠)
  • 线程数过多:系统平均负载攀升
  • FreeBSD自动管理:--minthreads/--maxthreads

4. 客户端配置

4.1 挂载命令

1
2
3
4
5
6
7
8
# Linux - NFSv4挂载
sudo mount -o rw,hard,intr,bg server:/ /mnt/nfs

# Linux - 指定NFSv3
sudo mount -o nfsvers=3 server:/export /mnt/nfs

# FreeBSD - NFSv4挂载
sudo mount -t nfs -o nfsv4 server:/ /mnt

4.2 关键挂载选项

选项 说明
rw / ro 读写/只读(须与服务器一致)
hard 默认,服务器离线时进程挂起等待
soft 服务器离线时返回错误(可能导致数据损坏,慎用
intr 允许用户中断被阻塞的NFS操作
bg 失败后在后台重试(避免阻塞引导)
rsize=n / wsize=n 读写缓冲区大小(自动协商最大值)
nfsvers=n 指定协议版本
proto=tcp / udp 传输协议(NFSv4必须TCP)
timeo=n 超时时间(十分之一秒)
retrans=n 软挂载时重试次数

4.3 showmount(仅NFSv2/v3)

1
showmount -e server    # 查看服务器导出的目录

NFSv4无替代品,可通过挂载/手动遍历或使用exportfs -v(仅本地)。

4.4 /etc/fstab自动挂载

server:/exports /mnt/nfs nfs rw,bg,intr,hard,nodev,nosuid 0 0

4.5 卸载NFS

1
2
umount /mnt/nfs
umount -f /mnt/nfs    # 强制卸载(服务器宕机时)

5. NFSv4身份映射

5.1 工作原理

NFSv4使用user@domain格式的字符串标识符,而非UNIX UID/GID。

客户端操作 → 客户端idmapd转换UID→字符串 → 网络传输
→ 服务器idmapd转换字符串→本地UID → 访问控制

5.2 关键问题

问题 说明
UID不一致 同一用户在不同系统的UID不同 → 映射错误 → 文件属主错乱
nobody账户 映射失败时回退到nobody用户
身份映射与访问控制分离 映射仅用于显示属性(如ls -l),实际访问控制由底层RPC认证决定

务必确保所有NFS客户端和服务器的UID/GID一致(通过LDAP或同步/etc/passwd)。

5.3 守护进程配置

系统 守护进程 配置文件
Linux rpc.idmapd /etc/idmapd.conf
FreeBSD nfsuserd /etc/rc.confnfsuserd_flags

NFS域设置/etc/idmapd.conf):

[General]
Domain = example.com

6. 安全考量

6.1 认证机制

机制 安全性 说明
AUTH_NONE ❌ 无 匿名访问,绝不使用
AUTH_SYS ⚠️ 弱 基于UID/GID自我声明,易伪造
RPCSEC_GSS ✅ 强 基于Kerberos/GSSAPI,支持加密和完整性
krb5 Kerberos认证
krb5i ✅✅ 认证+完整性校验
krb5p ✅✅✅ 认证+完整性+加密(隐私)

6.2 最佳实践

实践 说明
禁用NFSv2/v3 仅使用NFSv4(-N2 -N3选项)
使用Kerberos 生产环境强制sec=krb5p
防火墙单端口 仅开放TCP 2049(NFSv4)
限制导出范围 使用/etc/exports限制客户端IP/子网
不要将/设为V4根 尤其是FreeBSD(安全风险)

7. 自动挂载器(autofs)

7.1 为什么需要autofs

问题 autofs解决方案
大量NFS挂载导致引导缓慢 按需挂载,不用时不挂
依赖多台服务器 支持复制文件系统(failover)
fstab维护困难 集中化映射配置

7.2 核心组件

组件 功能
autofs 内核文件系统驱动程序,拦截挂载请求
automountd 读取配置,执行实际挂载/卸载
映射文件 定义自动挂载规则

7.3 映射类型

主映射/etc/auto.master Linux,/etc/auto_master FreeBSD):

# 间接映射
/harp    /etc/auto.harp
# 直接映射
/-       /etc/auto.direct

间接映射(共享父目录):

users   harp:/harp/users
devel   -soft harp:/harp/devel
info    -ro harp:/harp/info

直接映射(独立路径):

/usr/src    harp:/usr/src
/cs/tools   -ro monk:/cs/tools

7.4 可执行映射

映射文件设置可执行权限后,可作为脚本动态生成映射条目:

1
2
3
#!/bin/sh
# 键为子目录名,输出适合的映射条目
echo "$1" harp:/export/$1"

7.5 复制文件系统(failover)

/usr/man -ro harp:/usr/share/man monk(1):/usr/man
/cs/tools -ro leopard,monk:/cs/tools
  • 优先级:数字越小优先级越高(默认0)
  • automount根据响应时间、路由等选择最优副本

7.6 自动发现(-hosts,FreeBSD)

主映射中指定-hosts,自动挂载/net/hostname/export

/net -hosts -nosuid,soft

访问/net/harp/usr/share/man时会自动触发挂载。

8. 本章核心命令速查表

命令 功能 平台
showmount -e server 查看NFSv3导出目录 全平台(v3)
exportfs -a 重新读取exports文件 Linux
exportfs -v 显示当前导出状态 Linux
service nfsd restart 重启NFS服务器 FreeBSD
systemctl restart nfs-server 重启NFS服务器 Linux
mount -t nfs -o nfsv4 server:/ /mnt 挂载NFSv4 全平台
umount -f /mnt/nfs 强制卸载NFS Linux/FreeBSD
nfsstat -c / nfsstat -s 客户端/服务器端统计 Linux/FreeBSD
automount -v 显示自动挂载配置 Linux
automount -L 预演(dry run) Linux
systemctl restart autofs 重启自动挂载器 Linux
service automountd restart 重启自动挂载器 FreeBSD
/etc/exports NFS导出配置 Linux/FreeBSD
/etc/idmapd.conf NFSv4身份映射配置 Linux
/etc/auto.master / /etc/auto_master autofs主映射 Linux/FreeBSD

DBA视角补充

  • 数据库文件存储:NFS可用于共享数据库备份目录或归档日志,但不建议将数据库数据文件或事务日志直接存放在NFS上(除非是经过认证的NFS实现,如Oracle的Direct NFS)。NFS锁和延迟可能引发数据损坏。
  • 备份与恢复:NFS是数据库备份到异地服务器的常用方式。确保NFS挂载使用hard,intr选项,避免备份过程中因网络抖动失败。
  • Kerberos认证:生产环境数据库服务器与NFS存储之间应启用sec=krb5p,确保备份数据传输的加密和完整性。
  • NFSv4性能优势COMPOUND RPC将多个操作合并到一个请求中,减少网络往返,适合数据库备份这类大文件传输。
  • autofs在DBA场景:自动挂载器可用于按需挂载数据库备份卷、归档日志卷,避免在生产数据库中永久挂载大量外部存储,减少风险暴露面。
  • 身份映射调试:数据库服务器上的文件属主映射错误可能导致备份脚本权限失败。使用nfs4_getfacl检查NFSv4 ACL,确保数据库用户的UID在NFS客户端和服务器端一致。