资讯动态

Linux NFS共享安装配置、挂载与权限排错指南

发布时间:2026/10/26 18:48:43 来源:尧图企业网站定制
NFS 这套东西我第一次接触的时候觉得它特别朴素——不就是把一台机器上的目录共享出去让别的机器挂上来用吗跟插个 U 盘差不多。真到线上用起来才发现安装和挂载这两步只占整个工作量的三成剩下七成都花在权限对不上、版本协商失败、防火墙端口没开、写入卡顿这些地方。这篇就把 NFS 的安装配置和挂载这条链路从头到尾捋一遍重点讲清楚每个参数为什么这么写、出问题的时候该往哪儿看。适合的读者是手上有一组 Linux 机器需要做一个共享的数据目录又不想上分布式文件系统那种重家伙的运维和开发人员。新手上手照着能跑通有过一两次踩坑经验的人可以重点看后面的排错部分。1. 先给 NFS 找准位置它能干的事和干不了的事在动手装包之前我建议先花两分钟想清楚你到底需不需要 NFS。很多团队上来就架 NFS结果发现自己的场景其实用对象存储或者干脆定时同步更合适白折腾一轮。NFS 的本质是把远端的文件系统通过内核层面的协议挂载到本地目录树上对应用程序来说它就跟本地磁盘一样open、read、write这些系统调用可以直接用不需要改任何代码。这个特性是它最大的价值也是它最大的坑——正因为看起来像本地盘很多人会拿它去跑本来不该跑在共享文件系统上的东西。1.1 几种跨机共享数据方式的横向对比同样是让多台机器看到同一份数据市面上常见的做法有好几种各自的适用面差别挺大。我把它们放在一张表里对照你对着自己的场景挑就行。方案访问方式一致性语义性能量级典型适用场景NFS内核挂载POSIX 语义依赖服务端有缓存延迟千兆/万兆网卡接近线速多机共享配置、日志、静态资源、训练数据Samba/CIFS内核挂载或用户态访问类似 NFSWindows 兼容好略低于 NFS跨 Windows 与 Linux 的混合环境定时 rsync/scp无实时性最终一致有时间窗口受带宽限制离线备份、单向分发对象存储HTTP API强一致或最终一致看实现单流不一定快并发好海量非结构化文件、图片视频分布式文件系统内核挂载或客户端强一致多副本需要专门集群大规模生产、高可用要求高NFS 的位置很明确中小规模的、对 POSIX 语义有要求的、机器数量在几十台以内的共享场景它是性价比最高的选择。再往上节点数上百、要求高可用和横向扩展的就得上分布式文件系统了NFS 单点的问题会很突出。1.2 哪些东西千万别往 NFS 上放这一条我觉得比上面那张表还重要因为踩过一次就够记一辈子的。数据库的数据目录绝对不要放在 NFS 上。数据库对文件锁、fsync 语义、随机写的延迟极其敏感NFS 的锁机制和缓存行为跟本地盘完全不是一回事。我见过有人图省事把某轻量数据库的数据目录挂到 NFS 上平时跑着没事一到大事务提交就开始报各种诡异的损坏错误。高并发追加写的大日志文件也要谨慎。多个进程同时对同一个文件做追加在本地盘上靠O_APPEND能保证原子性但在 NFS 上这个保证要经过服务端协调性能会掉得很厉害而且不同版本的行为还不完全一致。需要 mmap 随机写的大文件同样不推荐。NFS 对内存映射写的支持一直是个灰色地带尤其是多机同时映射同一个文件的时候缓存一致性很容易出问题。真正适合放 NFS 的是这些东西多台 Web 服务器共享的静态资源目录、应用的配置文件、机器学习场景下的训练数据集只读为主、集中收集的日志落盘目录、构建产物的中转站。这些场景的共同点是读多写少或者写入是各写各的文件尽量不冲突。2. 装包前的环境确认版本选型和前置条件很多人装 NFS 出问题根子不在 NFS 本身而在装之前没确认清楚几件事发行版是哪个系、内核支持到哪个版本、防火墙和 SELinux 现在是什么状态。这几项没搞清楚就往下走后面每一步都可能卡住。2.1 服务端与客户端的软件包并不一样这里有个新手常犯的错以为服务端和客户端装同一个包。实际上绝大多数发行版是把两者拆开的服务端装服务端包客户端只装客户端包。在 RHEL、CentOS、Rocky、Fedora 这一系上服务端和客户端都包含在nfs-utils这一个包里装完就有了。启动的服务名是nfs-server。# RHEL 系服务端 dnf install -y nfs-utils systemctl enable --now nfs-server # RHEL 系客户端只需要 utils 和 rpcbind dnf install -y nfs-utils在 Debian、Ubuntu 这一系上包是分开的服务端叫nfs-kernel-server客户端叫nfs-common。这个命名差异坑过不少人尤其是在 Ubuntu 上照着 CentOS 的教程敲yum install nfs-utils的时候。# Debian 系服务端 apt update apt install -y nfs-kernel-server systemctl enable --now nfs-kernel-server # Debian 系客户端 apt install -y nfs-common关于版本我的建议是能用 NFSv4 就别用 v3。原因有三个v4 只需要一个 2049 端口防火墙规则简单v4 内置了用户身份映射不再依赖单独的rpc.idmapd去跟 NIS/LDAP 打交道v4.1 之后支持并行多连接nconnect单机吞吐能明显提上去。内核 2.6.39 以后就支持 v4 了现在主流的发行版内核版本都在 4.x、5.x 以上完全没问题。只有在对接一些老旧的存储设备或者特殊嵌入式环境时才需要退回 v3。2.2 端口、防火墙和 SELinux 的预处理这一步是排错成本最高的一环因为症状往往表现为命令卡住不动或者连接超时而不是明确的报错。先看端口。NFSv4 只依赖2049/TCP一个端口UDP 2049 可选。而 NFSv3 要复杂得多rpcbind占 111 端口nfsd占 2049此外mountd、statd、lockd都是动态分配端口的除非你在/etc/nfs.conf或者/etc/sysconfig/nfs里把它们固定下来否则每次重启都可能换端口防火墙规则根本没法写死。这也是我说能上 v4 就上 v4的现实理由之一。用 firewalld 的系统上把 NFS 相关的 service 加进去就行# NFSv4 场景只需要这一个 firewall-cmd --permanent --add-servicenfs firewall-cmd --reload # 如果必须用 v3还得加上这两个 firewall-cmd --permanent --add-servicemountd firewall-cmd --permanent --add-servicerpc-bind firewall-cmd --reload用 ufw 的系统ufw allow 2049/tcp # v3 还需要 ufw allow 111/tcp ufw allow 111/udp再看 SELinux。RHEL 系默认是 enforcing 状态如果不放行即使 exports 写得完全正确客户端挂载成功后也会在访问具体文件时收到 Permission denied。放行方式有两种# 方式一直接打开 NFS 导出的布尔开关 setsebool -P nfs_export_all_rw 1 # 方式二给共享目录打上正确的上下文标签 semanage fcontext -a -t public_content_rw_t /srv/share(/.*)? restorecon -Rv /srv/share提示不要图省事直接setenforce 0。临时关掉确实能让问题消失但下次重启又回来了而且这属于把安全机制整个拆掉。用布尔开关或者上下文标签解决才是正路。最后一个容易被忽略的前置条件是时间同步。NFS 的锁机制和文件时间戳都依赖两端时间大致一致如果偏差超过几分钟会出现文件明明刚写的却显示很久以前、锁申请莫名超时这类怪现象。上生产之前把 chrony 或 systemd-timesyncd 配好成本很低收益很大。3. 服务端exports 文件里每一列都在决定访问结果服务端的核心配置文件就一个/etc/exports但它的语法密度很高一行里几个选项的组合就能决定谁能访问、以什么身份访问、写的时候同步还是异步。这一节的篇幅值得给足因为线上 80% 的权限问题都出在这几行的理解偏差上。3.1 exports 的字段结构与最小可用写法一行的结构是共享路径 客户端标识 括号里的选项组。客户端标识可以是单个 IP、网段、主机名也可以写*表示所有人生产环境不建议。# /etc/exports 示例 /srv/share 192.168.10.0/24(rw,sync,no_subtree_check) /srv/data 192.168.10.21(rw,sync,no_root_squash) /srv/readonly *(ro,sync)几个关键选项的含义值得逐一说清楚rw/ro读写还是只读。注意这只是允许层面实际能不能写还要看文件系统本身的权限位和用户映射两个条件都满足才行。sync/asyncsync表示服务端把数据真正落盘之后才给客户端返回成功async是先回成功、后台再写盘。async性能好很多但服务端断电或崩溃时有丢数据的风险。默认行为在不同版本上不完全一致建议显式写出来不要靠默认值。no_subtree_check默认开启的subtree_check会让服务端每次请求都去验证文件是否还在导出的子树里代价是额外的stat开销而且文件被重命名后容易报Stale file handle。现在普遍建议关掉它。root_squash/no_root_squash这是权限部分的重头戏下一节单独讲。改完 exports 之后必须让它生效。很多人改完文件就直接去客户端挂载然后报 access denied回头查半天。正确做法是# 重新加载所有导出不影响已有连接 exportfs -ra # 查看当前生效的导出列表 exportfs -v # 或者从客户端侧验证 showmount -e 192.168.10.10exportfs -ra里的-r是重新导出-a是全部。如果只想临时加一条不写进配置文件可以用exportfs -o rw,sync 192.168.10.0/24:/srv/share重启后失效适合调试。3.2 root_squash 与用户映射权限问题的真正源头NFS 的权限模型跟本地文件系统有一个根本差异它不传递用户身份只传递数字 UID 和 GID。服务端拿到一个请求看到的是UID 1000 想写这个文件然后拿 1000 去跟本地文件的属主比对。至于客户端上这个 1000 对应的是张三还是李四服务端完全不知道也不关心。这个设计带来两个直接后果。第一两端的 UID 必须对得上。客户端上 UID 1000 的用户 ssh 登录后写文件服务端上文件属主也是 UID 1000那就成功如果服务端那个 UID 1000 对应的是另一个账号名义上就变成了那个人在写。第二root 默认是被压缩的。root_squash是默认行为意思是客户端的 rootUID 0访问时服务端会把它映射成匿名用户nobody通常是 UID 65534。这个设计的初衷是安全不能让任何一台客户端机器的 root 凭一个挂载就把服务端的文件系统当自己家。但实际操作中如果你在客户端用 root 去chown、chmod就会收到Operation not permitted很多人第一次遇到会以为是权限位写错了其实是 squash 在起作用。几个选项的对照选项客户端 root 的实际身份适用场景root_squash默认映射为 nobody绝大多数共享场景推荐默认保持no_root_squash保持 root仅限受控的运维管理机、备份机all_squash所有用户都映射为匿名公共只读资源、匿名上传目录anonuid/anongid指定匿名映射到哪个 UID/GID需要多人写入同一目录时统一身份all_squash配合anonuid是多人协作写入场景的一个实用组合。比如一个团队要往同一个上传目录写文件与其把每个人的 UID 在服务端都建一遍不如统一压成同一个 UID/srv/upload 192.168.10.0/24(rw,sync,all_squash,anonuid1500,anongid1500,no_subtree_check)这样不管客户端是谁写进来的文件属主都是服务端的 1500。代价是你失去了按人区分的审计能力所以只适合那种共享池性质的目录。注意no_root_squash一旦开到网段级别等于把这台机器的文件系统权限交给了该网段内任意一台机器的 root。真要开客户端标识就精确到单个 IP并且这个 IP 所在的机器本身要严格管控。3.3 服务启动与本地自检配置写好后按顺序做几件事。# 启动并设为开机自启 systemctl enable --now nfs-server # 看导出列表是否如预期 exportfs -v # 确认 rpc 相关服务在监听v3 场景必须看 rpcinfo -p localhost # 确认 2049 端口在监听 ss -lntp | grep 2049一个很实用的自检手法先在服务端本机挂载自己。如果本机挂载都失败那问题肯定在服务端配置跟网络无关排查范围立刻缩小一半。mkdir -p /mnt/selftest mount -t nfs 127.0.0.1:/srv/share /mnt/selftest ls /mnt/selftest umount /mnt/selftest这里有个细节如果本机挂载时报access denied by server先确认 exports 里有没有包含127.0.0.1或者写的是网段。只写了192.168.10.0/24的话回环地址是不在范围内的本机自测会失败但这不代表配置错了。另外服务端导出的目录本身要有合适的权限位。导出/srv/share但目录权限是700且属主是 root那么在有root_squash的情况下客户端任何用户都进不去。通常的做法是把目录权限设成755或775属主属组按需求分配。4. 客户端挂载参数决定了实际使用体验服务端配好了客户端这一侧的工作看起来只有一条mount命令但参数选得对不对直接决定了后面几个月会不会隔三差五出状况。我这里按临时挂载 → 持久化 → 验证的顺序讲。4.1 mount 命令的参数取舍# 最基础的 v4 挂载 mount -t nfs -o vers4.2 192.168.10.10:/srv/share /mnt/share几个参数值得展开说vers显式指定版本。不写的话客户端会去协商协商本身要花时间而且遇到服务端只支持 v3 的情况某些老客户端会卡在探测阶段比较久。生产上直接写死vers4.2或vers4.1行为可预期。hard/soft这是最重要的一对参数也是最容易配错的。hard表示服务端不响应时客户端的操作会一直重试、永不放弃soft表示重试若干次后返回错误。默认是hard我建议绝大多数场景保持hard。原因很直接soft会在网络抖动时悄悄把错误返回给应用而很多应用对 I/O 错误的处理是写失败就算了结果就是数据静默丢失事后完全查不出来。hard虽然会导致应用卡住但卡住至少是可见的能触发告警不会丢数据。只有一类场景适合soft纯只读、可以随时重试的查询类挂载比如一台机器只是临时读一下配置。即便如此也要配合合理的timeo和retrans。timeo超时时间单位是十分之一秒。这个单位非常容易看错timeo600是 60 秒不是 600 秒。默认值通常是 60060 秒。retrans重试次数。跟soft配合才有意义hard下会无限重试。rsize/wsize单次读写的数据块大小。NFSv4.1 之后默认能协商到 1MB基本不用手动调。如果发现吞吐上不去可以试试显式指定但前提是两端都支持。noatime不更新访问时间。这个参数在只读为主的场景比如 Web 静态资源下收益很明显因为它能省掉大量的元数据写回。relatime是大多数文件系统的默认值已经比atime好很多但noatime更彻底。nosuid、noexec、nodev安全加固三件套。nosuid让共享目录里的 setuid 程序失效noexec禁止直接执行上面的二进制nodev禁止解析设备文件。如果共享的只是数据文件把这三个全加上几乎没成本。一个相对稳妥的生产挂载写法mount -t nfs \ -o vers4.2,hard,timeo600,retrans2,noatime,nosuid,nodev \ 192.168.10.10:/srv/share /mnt/share4.2 写进 fstab 还是交给 autofs/etc/fstab适合这台机器开机就必须有这个挂载的场景。关键点有三个类型写nfs或nfs4选项里加_netdev表示依赖网络、等网络就绪后再挂载再加bg表示如果第一次挂载失败就转后台继续重试避免开机卡死在挂载这一步。# /etc/fstab 192.168.10.10:/srv/share /mnt/share nfs vers4.2,hard,timeo600,retrans2,noatime,_netdev,bg 0 0如果不加_netdev在某些启动顺序下系统会在网络还没起来的时候尝试挂载失败后进入紧急模式或者卡住很久。这个问题在云主机上尤其常见。加了bg之后即使第一次失败系统也能正常启动完后台继续重试。autofs适合按需挂载的场景。它的好处是不访问就不挂载节省服务端连接数服务端临时不可用时不会拖慢开机闲置超时后自动卸载。多台客户端共享同一个大目录、但实际访问频率不高的场景用 autofs 比写 fstab 优雅得多。配置分两个文件。/etc/auto.master里登记挂载点的父目录和规则文件# /etc/auto.master /mnt/nfs /etc/auto.nfs --timeout300/etc/auto.nfs里写具体的映射格式是挂载点子目录 挂载选项 服务端路径# /etc/auto.nfs share -vers4.2,hard,noatime 192.168.10.10:/srv/share data -vers4.2,hard,noatime 192.168.10.10:/srv/data装好 autofs 服务并启动后只要有人cd /mnt/nfs/share它就会自动挂上300 秒没人访问就自动卸掉。apt install -y autofs # Debian 系 dnf install -y autofs # RHEL 系 systemctl enable --now autofs提示autofs 的父目录上面的/mnt/nfs是 autofs 自己管理的你手动往里面放文件会在下次触发时消失别往里面存东西。4.3 挂载之后该做哪些验证mount命令不报错不代表一切正常。我习惯按顺序做这几个检查# 1. 确认挂载类型和参数 mount | grep /mnt/share # 输出里应该能看到 vers4.2 之类的参数 # 2. 看实际可用容量和已用 df -hT /mnt/share # 3. 写权限实测不是看权限位是真写一个文件 touch /mnt/share/.write_test rm /mnt/share/.write_test # 4. 确认落盘的用户身份 touch /mnt/share/uid_test ls -ln /mnt/share/uid_test第 4 步特别有用。它直接告诉你服务端看到的 UID 是多少一旦后面出现权限问题拿这个 UID 跟服务端上文件的属主一比对问题定位能快很多。ls -ln里的-n就是以数字形式显示 UID/GID避免客户端和服务端的用户名解析不一致造成误判。还有一个检查项是针对 NFSv4 的看看.nfs*这类隐藏文件是不是出现在目录里了。正常情况下这些是 NFS 用来占位、防止文件被删除时句柄失效的属于预期行为不需要清理也清理不掉rm会报 Operation not permitted 或者又冒出来。5. 排错实录几类高频故障的完整排查链路前面都是正常路径这一节讲不出意外的时候该怎么办。我按症状来组织每个症状给出从外到内的检查顺序你照着走一般能定位到根因。5.1 挂载成功但读写报 Permission denied这是出现频率最高的一类。注意前提挂载本身成功了说明网络通、exports 里的客户端标识匹配、端口没问题问题只可能出在权限层面。检查顺序如下。第一步看服务端目录本身的权限。# 服务端执行 ls -ldn /srv/share getfacl /srv/share 2/dev/null如果目录是700且属主是 root那在root_squash下客户端谁都进不去。这是最常见的一种。第二步在客户端确认自己用的 UID。id # 假设输出 uid1001(user1) gid1001(user1)第三步回服务端看这个 UID 有没有对应权限。# 服务端 getent passwd 1001 ls -ln /srv/share如果服务端上1001是另一个用户或者根本没有这个 UID那就要么在服务端建一个同 UID 的账号要么在 exports 里用all_squashanonuid统一映射。第四步检查 SELinux。getenforce # 如果是 Enforcing看审计日志 ausearch -m avc -ts recent | grep nfs这一步很容易漏。因为 SELinux 的拒绝不会体现在文件权限位上ls -l看着完全正常就是不给访问。第五步检查上级目录的权限。文件权限检查是逐级下钻的/srv/share权限对但如果/srv是700一样进不去。这条同样适用于 NFS 导出的路径。namei -l /srv/sharenamei -l会把路径上每一级的权限都列出来一眼就能看到哪一级断了。我遇到过一个比较隐蔽的案例目录权限完全正确UID 也对得上但就是写不进去。最后发现是服务端磁盘满了写入时返回的是No space left on device但经过 NFS 协议层转换后客户端看到的报错变成了Permission denied。所以如果前面几步都排干净了还是不通去看一眼df -h和服务端的dmesg。5.2 客户端挂载超时或者 showmount 卡住症状是mount命令敲下去半天没反应或者showmount -e一直挂在那里。这类问题的排查方向跟上一类完全不同指向网络和守护进程。先确认 2049 端口通不通这一步用最底层的工具验证# 从客户端测 timeout 3 bash -c cat /dev/null /dev/tcp/192.168.10.10/2049 echo 2049 open || echo 2049 blocked如果端口不通按顺序查服务端服务有没有起来systemctl status nfs-server、服务端本地能不能监听ss -lntp | grep 2049、中间有没有防火墙或安全组拦截。云环境里安全组是最常见的原因很多人只配了机器上的 firewalld忘了控制台里还有一层。如果 2049 通但showmount卡住那基本可以确定是rpcbind 的问题。showmount在 v3 场景下要连 111 端口去问mountd在哪而mountd的端口是动态的。检查方法# 服务端 systemctl status rpcbind rpcinfo -p localhost | grep -E mountd|nfs如果rpcinfo输出里mountd的端口每次重启都在变那就是没固定。在/etc/nfs.conf里加上[mountd] port20048然后在防火墙放行 20048/TCP。同样的方式可以固定statd和lockd的端口。不过说实话如果你不需要兼容老设备直接上 v4 就能一次性绕开这整类麻烦因为 v4 所有的服务都跑在 2049 上。还有一种情况能 ping 通、2049 也开着但挂载就是不行报Connection timed out。这时候看看客户端的路由表确认去服务端走的是哪张网卡。有双网卡的机器上回程路径不一致去包走 A 网卡回包走 B 网卡会导致 TCP 握手成功但后续数据传输中断表现为连上又断、挂载超时。5.3 写入慢、文件锁异常和 Stale file handle这几类问题平时不出现一旦出现就特别影响使用体验值得单独讲。写入慢如果排除网络带宽因素最常见的原因是用了sync而业务又是大量小文件写入。每次写都要真正落盘并等待确认在机械盘或者网络存储上延迟会非常明显。可以考虑在能接受少量数据丢失风险的目录上换成async或者把大量小文件写入改成先写本地再整体搬移。另一个常被忽略的因素是客户端缓存。读多写少的场景可以适度加大ac系列参数属性缓存时间但调太大又会导致多机之间看到的文件状态不一致。这块需要根据实际业务权衡一般默认值够用不建议乱调。文件锁异常的表现是某个应用报无法获取锁或者多个进程莫名其妙同时进入临界区。NFSv4 的锁是由服务端统一管理的理论上比 v3 那套基于lockd的机制可靠得多。如果是在 v3 上出现先确认rpc.statd和lockd在两端都正常运行。如果是在 v4 上出现检查一下是不是有客户端在机器休眠或者网络闪断后没有正确释放锁——这种情况在虚机迁移、笔记本合盖休眠之后比较常见。Stale file handle的触发条件是客户端手里拿着一个文件句柄但服务端那边这个文件对应的 inode 已经不存在了或者导出的范围变了。典型诱因有三个服务端重启后用exportfs -r重导出了某个文件被删除后又立刻创建了同名文件服务端导出的子目录结构发生了变化。处理办法分两步。先卸载再重启挂载umount -l /mnt/share # -l 是 lazy unmount有进程占用时先脱开 mount -t nfs vers4.2 192.168.10.10:/srv/share /mnt/share如果umount死活卸不掉提示 device is busy用lsof或者fuser找出占用的进程lsof D /mnt/share | head fuser -mv /mnt/share注意umount -f在hard挂载的服务端不可达时可能长时间卡住。这种情况先umount -l把挂载点从命名空间里摘出去再处理残留的进程。预防措施是在 exports 里用no_subtree_check能明显降低文件重命名后出现 stale handle 的概率。6. 调优与日常巡检让这套东西能长期稳定跑配好跑通只是开始真正花时间的是后面让它稳定。这一节讲几个我在实际环境里觉得收益比较明显的点。6.1 nconnect 与传输层参数如果你的内核和 NFS 版本都支持NFSv4.1 及以上内核 5.3 之后比较稳nconnect是个几乎无脑的优化项。它让客户端对同一个服务端建立多条 TCP 连接并行传输单机吞吐能提升明显尤其是在高延迟链路上。mount -t nfs -o vers4.2,nconnect4 192.168.10.10:/srv/share /mnt/sharenconnect4是个比较稳妥的起点加到 8 也行但再往上收益递减还会占用更多文件描述符和服务端连接资源。注意它是**按客户端-服务端对**生效的同一个客户端挂载同一个服务端的多个目录只有第一次挂载时能设置后续挂载会沿用。多数用nconnect却看不到提升的情况是把rsize/wsize调得过大结果单条 TCP 流被拥塞窗口卡住。建议nconnect4的时候rsize/wsize保持默认 1M 就行别再往上调。另外如果链路的 MTU 有特殊情况比如走了隧道或者有中间设备jumbo frame 没端到端打通会导致大量分片性能反而比标准 1500 差很多。改 MTU 之前一定要端到端确认别只改两端主机。6.2 日常该盯哪几个指标NFS 出问题往往不是突然的而是资源慢慢逼近上限。我一般会关注这几项。连接数和活跃客户端数。服务端上看# 当前有多少客户端连着 ss -tn state established ( sport :2049 ) | wc -l # 或者用 nfsstat 看客户端列表 cat /proc/fs/nfsd/clients/*/info 2/dev/null客户端数量超过预期时要警惕可能是某些机器在反复重连网络不稳也可能是配置泄漏导致旧连接没释放。RPC 重传率。nfsstat -r里retrans那一列如果持续增长说明有丢包或者服务端处理不过来。nfsstat -r nfsstat -s # 服务端视角 nfsstat -c # 客户端视角服务端线程数。nfsd的线程数决定了并发处理能力默认值在 8 到 16 之间。客户端一多线程数不够会表现为请求排队、延迟上升cat /proc/fs/nfsd/threads # 调整RHEL 系 echo 32 /proc/fs/nfsd/threads在/etc/nfs.conf里改[nfsd] threads32可以持久化。注意别盲目调大线程越多内存占用越高要根据实际并发和内存余量来定。容量和 inode。共享目录写满是最常见的生产事故之一。df -h看空间df -i看 inode。有些场景下空间还剩很多但 inode 用光了大量小文件一样写不进去而且报错同样可能是Permission denied或者No space left on device看着很懵。df -hT /srv/share df -i /srv/share我个人的习惯是给共享目录单独划一个逻辑卷不要跟系统盘混在一起。这样一是容量告警清晰二是写满的时候不会连带影响系统本身三是扩容方便lvextendxfs_growfs或者resize2fs不需要停服务。还有一点值得提不要把 NFS 当备份用。我见过不止一次有人觉得共享目录就是集中存储把唯一一份数据放在 NFS 上然后服务端磁盘挂掉全没了。NFS 解决的是多台机器看到同一份数据它不解决数据冗余和持久性这两件事得靠底层存储的 RAID、快照或者另外的备份机制来做。6.3 升级内核或重启服务端的注意事项服务端重启会让所有客户端短暂中断。hard挂载的客户端会自动重试服务端恢复后连接能自动恢复应用那边的表现通常是卡了一会儿又好了不会报错。这算是hard参数的一个额外好处——它让短暂的服务端重启对业务来说是可以容忍的。但有两件事要提前做。第一重启前把服务端的导出配置备份一下cp /etc/exports /etc/exports.bak.$(date %F)改坏了能快速回滚。第二升级内核之后确认 nfsd 模块正常加载lsmod | grep nfsd modprobe nfsd有些定制内核或者裁剪过的镜像里nfsd 模块可能没编进去升级后服务起不来。这种情况在云厂商的定制镜像上偶尔会遇到提前验一遍能省不少事。客户端的升级相对简单只要版本参数写死vers4.2重启后行为是一致的。唯一需要注意的是从老内核升到新内核时默认挂载版本可能会变如果 fstab 里没写vers可能出现升级前能挂、升级后挂不上的情况。所以我一再强调fstab 里的挂载选项要写全别依赖默认值。配 NFS 这事配置本身不难难的是把权限模型和版本差异这两件事想透。我自己最早的一套环境就是因为 exports 里漏了no_subtree_check加上客户端用 root 去改目录属主来回折腾了大半天最后发现是两个完全独立的问题叠在一起。后来养成一个习惯任何一次共享目录上线前都先在服务端本机挂一次、再从一台干净的客户端挂一次两次都跑一遍写测试和 UID 检查确认没问题再交给业务用。这几分钟的自测比事后在生产上慢慢排查要划算得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑