Orange的运维学习日记--36.NFS详解与服务部署
Orange的运维学习日记–36.NFS详解与服务部署
文章目录
- Orange的运维学习日记--36.NFS详解与服务部署
- NFS 服务介绍
- NFS 深入解析
- 协议版本演进
- 工作原理详解
- 安全与认证
- 性能优化
- 锁机制与并发
- ID 映射与用户管理
- 常见故障与诊断
- 部署服务
- 配置导出
- 监视导出
- 客户端挂载
NFS 服务介绍
NFS 全称 Network File System 由 Sun 公司最初开发 用于在 UNIX 与 Linux 系统之间共享磁盘文件 主要通过网络使不同主机之间共享文件或目录
NFS 客户端(通常为应用服务器)通过挂载方式将服务端共享的目录映射到本地系统 仿佛本地磁盘分区或目录 实际数据存放在远端 NFS 服务端
在企业集群架构场景中 常将用户上传的静态资源(视频、图片、附件等)存储在 NFS 共享目录 尤其在中小型网站公司应用频率更高 如论坛头像、图片和附件
NFS 功能众多 每项功能由独立进程启动 并占用小于 1024 的随机端口 客户端必须获知端口后才能建立连接 为此 NFS 借助 RPC 服务注册各功能端口 并将端口信息汇报给客户端
RPC(Remote Procedure Call)实现网络进程间透明通信 客户端可像调用本地函数一样调用远程服务 而无需了解底层通信协议细节
NFS 服务器 RPC 注册与端口映射 NFS 客户端
┌──────────┐ ┌──────────────┐ ┌──────────┐
│ nfsd │───┐ │ rpcbind │ │ mount │
└──────────┘ │ └──────────────┘ └──────────┘│ Register ports │ 查询并连接
┌──────────┐ │ ┌──────────────┐ ┌──────────┐
│ mountd │───┘ │ rpc.mountd │ │ client │
└──────────┘ └──────────────┘ └──────────┘
└──────────┘ └──────────────┘ └──────────┘
│ lockd │ │ rpc.lockd │ │ 操作文件 │
└──────────┘ └──────────────┘ └──────────┘
NFS 深入解析
协议版本演进
NFS 自 1984 年问世以来演进了多个版本
- NFSv2 仅支持 32 位文件大小 与时间戳 限制单个文件最大 2 GB 且只能通过 UDP 传输
- NFSv3 引入 64 位文件大小 与时间戳 支持 TCP 传输 提升可靠性 并新增异步写入与批量读写改进性能
- NFSv4 将状态管理(stateful)与锁管理(lock)协议合并到单一的 TCP 2049 端口 简化防火墙配置 支持文件锁定委托(delegation)与复合操作(compound RPC)
- NFSv4.1 在标准中加入 pNFS(parallel NFS) 扩展了客户端直接与后端存储并发交互的能力
工作原理详解
NFS 在网络上通过 RPC(远程过程调用)实现核心操作 包括挂载、读写、属性查询与锁定
- mount 协议 用于客户端向服务端请求导出列表 并完成初始挂载过程
- nfs 协议 提供基本文件系统操作 如 READ、WRITE、LOOKUP、CREATE、REMOVE
- lock 协议(NLM)及状态监视协议(NSM)管理文件锁定与死机恢复
在挂载时 客户端首先向 rpcbind 查询 mountd 服务端口 再通过 mountd 获取导出列表 并记录对应的端口号
之后所有 NFS 操作都通过 nfsd 进程与 lockd 进程 并利用对应端口完成通信
安全与认证
NFS 默认使用 UNIX 权限模型 通过客户端 UID/GID 控制访问
常见安全选项
- sec=sys(默认) 依赖客户端传递的 UID/GID 可能遭受伪造风险
- sec=krb5 利用 Kerberos 实现身份验证 提供单点登录
- sec=krb5i 在 krb5 基础上增加消息完整性保护
- sec=krb5p 进一步提供端到端数据加密
结合防火墙策略 只开放 TCP/UDP 2049 及 rpcbind、mountd、lockd 等必要端口 可将 NFSv4 配置为仅使用 TCP 2049 降低风险
性能优化
调整读写与缓存参数 可显著提升吞吐与响应
- rsize/wsize 设定客户端读写块大小 推荐 64 KB 或更高
- sync 与 async
- sync 确保每次写请求都持久化到磁盘 提高数据安全
- async 客户端返回更快 但风险在于挂载端崩溃后可能丢失数据
- attribute 缓存(actimeo、acregmin、acregmax、acdirmin、acdirmax)
通过合理设置缓存时长 降低重复查询开销 - noac 禁用 attribute 缓存 适用于对一致性要求极高的场景
- 增加 nfsd 线程数量(
RPCNFSDCOUNT
)在高并发环境中消除瓶颈
锁机制与并发
NFSv3 使用独立的 lockd 与 statd 实现文件锁与死机恢复
- lockd 负责锁定请求的转发
- statd 监视客户端状态 并在客户端崩溃时通知其他节点解锁
NFSv4 将锁管理内置到主协议中 支持字节范围锁定 与委托锁(delegation)
客户端可在独占访问时获取委托 锁定后直接在本地缓存改动 最终再回写服务端 减少网络往返
ID 映射与用户管理
NFS 在服务端与客户端之间需要统一用户身份
- v3 及以下版本通过 UID/GID 数值匹配 存在映射错误风险
- v4 引入 idmapd 守护进程 根据域名与映射规则 将用户名转换为 UID/GID
配置 /etc/idmapd.conf
- Domain 参数 要求服务端与客户端一致
- Mapping 方法 支持静态文件与 LDAP 等集中管理
通过统一域与映射策略 可避免跨集群文件访问权限不一致的问题
常见故障与诊断
- 挂载失败
检查 rpcbind、nfs-server 服务状态 与防火墙端口开放情况 - 访问权限被拒绝
确认/etc/exports
中客户端地址或网络掩码 配置是否正确 并运行exportfs -r
生效 - 写入后数据丢失
检查挂载选项 是否使用了 async 或 noac 引发缓存冲突 - 文件锁失效
NFSv3 环境中 核实 lockd 与 statd 是否正常运行
通过日志 /var/log/messages
或 journalctl -u nfs-server
获取详细错误信息 并结合 rpcinfo -p
核查端口映射状态
以上内容为对 NFS 的深度剖析 如需进一步示例或脚本 可继续补充
部署服务
部署 NFS 服务器所需软件包由 nfs-utils 提供 在 RHEL 8 系统中默认已安装
# 安装 nfs-utils
yum install -y nfs-utils
创建操作用户和共享目录 并为其分配所有者
# 创建用户 example uid 1000
useradd -u 1000 example
echo redhat | passwd --stdin example# 创建并设置共享目录
mkdir -p /shares/nfs
chown example:example /shares/nfs
启动并开启开机自启 NFS 服务
systemctl enable nfs-server --now
开放防火墙端口
firewall-cmd --permanent \--add-service=nfs \--add-service=rpc-bind \--add-service=mountd
firewall-cmd --reload
配置导出
NFS 服务端的导出配置主文件位于 /etc/exports 目录下 也可将配置拆分存于 /etc/exports.d/*.exports 文件中
建议在 /etc/exports.d 中创建或删除单独配置文件 以减少意外破坏其他导出的风险
每行语法格式
<本地目录> <客户端列表>(选项)
示例
-
DNS 主机名 导出给 client.example.cloud 挂载
/shares/nfs client.example.cloud
-
通配符域名 导出给 example.cloud 下所有主机挂载
/shares/nfs *.example.cloud
-
IPv4 单机或网段
/shares/nfs 10.1.8.11 /shares/nfs 10.1.8.0/24
-
IPv6 单机或网段
/shares/nfs fde2:6494:1e09:2::20 /shares/nfs fde2:6494:1e09:2::/64
-
多客户端共享
/shares/nfs 10.1.8.0/24 client.example.cloud *.example.net
默认导出为只读 可通过括号内选项覆盖默认行为
常用选项
- rw 允许读写 否则为只读
- no_root_squash 保持客户端 root 用户权限 否则会映射为 nobody 或 nfsnobody 用户
示例
/shares/nfs client.example.cloud(rw) client2.example.cloud
/shares/nfs client.example.cloud(rw,no_root_squash)
RHEL 7 中默认映射为 nfsnobody 用户 RHEL 8 中为 nobody 用户
修改配置后运行以下命令生效
# 重新导出
exportfs -r# 或者重载服务
systemctl reload nfs-server# 查看所有导出
exportfs -av
监视导出
使用 exportfs 命令查看当前导出的目录
exportfs
使用 -v 选项显示详细选项
exportfs -v
客户端挂载
在客户端安装 nfs-utils
yum install -y nfs-utils
创建与服务端一致的用户
useradd -u 1000 example
echo redhat | passwd --stdin example
查看服务端导出
showmount -e server
挂载共享
mkdir -p /mnt/nfs
mount -t nfs server:/shares/nfs /mnt/nfs
权限测试示例
# root 用户无法创建
touch /mnt/nfs/root-f1# example 用户可以创建
su - example
touch /mnt/nfs/example-f1
持久化挂载 编辑 /etc/fstab 添加
server:/shares/nfs /mnt/nfs nfs defaults 0 0挂载共享```bash
mkdir -p /mnt/nfs
mount -t nfs server:/shares/nfs /mnt/nfs
权限测试示例
# root 用户无法创建
touch /mnt/nfs/root-f1# example 用户可以创建
su - example
touch /mnt/nfs/example-f1
持久化挂载 编辑 /etc/fstab 添加
server:/shares/nfs /mnt/nfs nfs defaults 0 0