nfsstat / showmount —— NFS 状态与性能
一句话定义
nfsstat 显示 NFS client / server 端的统计信息:操作类型 / 重传率 / 性能指标。 showmount 显示 NFS server 的 export 列表(哪些目录可挂、哪些客户端能挂)。
典型场景
- NFS 慢、看是不是网络重传多
- 看 client 跟 server 实际用的 mount options
- server 发现"奇怪的连接"——showmount 看谁在挂
- 监控 NFS server 线程数
- 排查 stale handle
装
通常 NFS 工具一起装:
apt install -y nfs-common # client 端
apt install -y nfs-kernel-server # server 端(含 nfsstat / exportfs)
yum install -y nfs-utils # CentOS 通用包
1. nfsstat 三种视角
nfsstat -c # client 端统计
nfsstat -s # server 端统计
nfsstat -m # 当前 mount 的状态(**最实用**)
nfsstat # 默认显示 client + server
2. nfsstat -m —— 最常用
显示每个 NFS 挂载点的详细参数:
$ nfsstat -m
/mnt/data from nfs.example.com:/exports/data
Flags: rw,relatime,vers=4.2,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.0.24.28,local_lock=none,addr=10.0.24.99
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
实际生效的所有 mount options
逐字段:
| Flag | 含义 |
|---|---|
vers=4.2 | NFS 协议版本(详见 04-nfs-deep.md) |
rsize=1048576 | 单次读 chunk = 1MB |
wsize=1048576 | 单次写 chunk = 1MB |
hard | hard mount(不放弃) |
proto=tcp | TCP |
timeo=600 | 60 秒超时(十分之一秒为单位) |
retrans=2 | 重试 2 次 |
sec=sys | 认证方式(sys / krb5) |
排查"为啥 NFS 慢"
$ nfsstat -m
Flags: ...,rsize=8192,wsize=8192,vers=3,proto=udp,...
^^^^ ^^^^ ^^^^
8K 太小 v3 老 UDP 不可靠
→ 协商出最差组合、rsize/wsize 太小 + v3 + UDP。
修:mount 时显式指定:
mount -t nfs -o vers=4.2,proto=tcp,rsize=1048576,wsize=1048576 ...
3. nfsstat -c —— Client 端统计
$ nfsstat -c
Client rpc stats:
calls retrans authrefrsh
123456 45 123456
^^^
(1)
Client nfs v4:
null read write commit open open_conf open_noat open_dgrd ...
0% 45% 30% 5% 2% 1% 0% 0% ...
^^^^ ^^^^^
(2) (3)
| 标记 | 含义 |
|---|---|
| (1) | 重传数——网络丢包 / server 慢的信号 |
| (2) | read 占总操作的 45% |
| (3) | write 占 30% |
关键:重传率
$ nfsstat -c | head -3
calls retrans authrefrsh
1000000 50000 1000000
^^^^^^
重传率 = 5%
重传率(retrans / calls):
- < 0.1% —— 正常
- 0.1-1% —— 偶尔抖动
- > 1% —— 网络问题或 server 慢
5% —— 严重
排查:
$ mtr -rn -c 30 -T -P 2049 <nfs-server>
# 看路径丢包
4. nfsstat -s —— Server 端统计
$ nfsstat -s
Server rpc stats:
calls badcalls badclnt badauth xdrcall
1234567 0 0 0 0
Server nfs v4:
null compound
0% 100%
Server nfs v4 operations:
op0-unused op1-unused op2-future access close commit ...
0 0 0 23% 5% 8%
badcalls / badclnt / badauth 持续涨:
| 字段 | 异常含义 |
|---|---|
badcalls | 协议错误 / 客户端 bug |
badclnt | client 不被允许(看 /etc/exports) |
badauth | 认证失败 |
5. NFS server 线程统计(性能瓶颈关键)
NFS server 用线程池处理客户端请求。看是否够用:
$ cat /proc/net/rpc/nfsd | head -2
th 8 1234 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
^ ^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
(1)(2) (3) (4) (5) ...
| 字段 | 含义 |
|---|---|
| (1) | 当前线程数 |
| (2) | 线程全忙过的次数(关键) |
| (3-12) | 10 个百分位桶(线程占用率分布) |
异常信号:
- (2) > 0 且持续涨 → 线程不够、需要调
- 最后 1-2 个桶(90-100% 占用)非 0 → 经常满载
修:
# /etc/default/nfs-kernel-server
RPCNFSDCOUNT=64 # 默认 8、生产调到 64-128
systemctl restart nfs-kernel-server
6. showmount —— 看 export 列表
$ showmount -e
Export list for localhost:
/exports/data 10.0.24.0/24
/exports/shared *
/exports/configs 10.0.24.5,10.0.24.6
* = 所有客户端能挂。生产里绝对不应该出现 *——安全大坑。
$ showmount -e nfs.example.com
Export list for nfs.example.com:
/exports/data 10.0.24.0/24
/exports/shared *
K8s 节点上排查 "NFS PV 挂不上" 时第一时间跑这个——验证 server 通 + 你的节点 IP 在 export 列表里。
$ showmount -a
All mount points on localhost:
10.0.24.28:/exports/data
10.0.24.29:/exports/data
10.0.24.30:/exports/shared
看哪些客户端正连着。但NFSv4 不真维护这个列表——可能空。
$ showmount -e --no-headers
/exports/data 10.0.24.0/24
/exports/shared *
$ showmount -e | awk 'NR>1 {print $1}' # 只显示路径
/exports/data
/exports/shared
7. exportfs —— 看 / 操作 NFS server exports
$ exportfs -v
/exports/data 10.0.24.0/24(sync,wdelay,hide,no_subtree_check,sec=sys,rw,secure,root_squash,no_all_squash)
/exports/shared <world>(sync,wdelay,hide,no_subtree_check,sec=sys,rw,secure,root_squash,no_all_squash)
^^^^^^^^
* 在 exportfs 里显示成 <world>
操作:
exportfs -ra # 改完 /etc/exports 后重读
exportfs -u <client>:<path> # 单独卸载某 export
exportfs -au # 卸载所有
exportfs -ar # 重新导出所有
详见 04-nfs-deep.md.
8. 实战场景
场景 1:K8s pod NFS PV 挂不上
# 节点上排查
$ ssh m4
# 1. NFS server 通吗
$ ping -c 3 nfs.example.com
$ nc -zv nfs.example.com 2049
# 2. server 的 exports
$ showmount -e nfs.example.com
Export list for nfs.example.com:
/exports/data 10.0.25.0/24 ← 不含 10.0.24.0/24
# 找到了:m4 (10.0.24.4) 不在允许列表
修:NFS server 上加 m4 网段:
# /etc/exports
/exports/data 10.0.24.0/24(rw,sync,no_subtree_check) 10.0.25.0/24(rw,sync,no_subtree_check)
# server 上
exportfs -ra
场景 2:NFS 偶发性慢
$ nfsstat -c | head -3
calls retrans authrefrsh
1000000 50000 1000000
^^^^^^
5% 重传率 → 网络问题
# 看网络路径
$ mtr -rn -c 60 -T -P 2049 nfs.example.com
HOST Loss% ... Last Avg ...
1. 10.0.24.1 0.0% 0.5 0.6
2. 10.0.0.1 0.0% 1.5 2.0
3. nfs.example.com 5.0% 5.0 6.0 ← 5% 丢包
# 看 server 端线程数
$ ssh nfs-server 'cat /proc/net/rpc/nfsd | head -1'
th 8 50000 ... ← 50000 次满载
# 调线程数
$ ssh nfs-server '
echo RPCNFSDCOUNT=64 >> /etc/default/nfs-kernel-server
systemctl restart nfs-kernel-server
'
场景 3:监控 NFS 性能(Prometheus)
# rate of NFS operations
sum by (operation) (rate(node_nfs_requests_total[1m]))
# 平均延迟
histogram_quantile(0.99, sum by (le, operation) (rate(node_nfs_request_duration_seconds_bucket[5m])))
node-exporter 暴露这些 metric(要开 --collector.nfs)。
场景 4:NFS server 端清"幽灵"连接
# 看 server 端连着的客户端
$ ss -tn '( sport = :2049 )'
ESTAB ... 10.0.0.99:54321 client-a:2049
# 如果某客户端死了但 TCP 没关
$ ss -tn '( sport = :2049 )' | head -20
# 看到 ESTAB 几小时、且 client 已不存在
server 端通常会有 keepalive 超时清理。手动清要重启 nfs-server(影响所有连接)。
9. 看 NFS 慢操作的 trace 工具
# 装 bcc-tools
apt install -y bpfcc-tools
# 跟踪 NFS 慢操作 (>1ms)
nfsslower 1 # 阈值 1ms
TIME(s) COMM PID T BYTES OFF_KB LAT(ms) FILENAME
0.000 java 1234 R 8192 1024 5.20 data.bin
0.123 python 5678 W 4096 0 3.50 out.csv
eBPF 工具、低开销。生产可以一直跑找慢调用。
10. 反面教材
反面 1:用 nfsstat -m 时看不到 mount
$ nfsstat -m
# 空?
可能:
- 没真挂上 NFS
- 进了容器 ns(nfsstat 看的是节点 / 当前 ns 的 mount)
进 pod ns 看:
PID=$(crictl inspect ... | jq '.info.pid')
nsenter -t $PID -m nfsstat -m
反面 2:showmount 通了不代表 mount 通
$ showmount -e nfs.example.com
Export list:
/exports/data 10.0.24.0/24
$ mount -t nfs nfs.example.com:/exports/data /mnt
# 失败!
showmount 走 RPC 111(rpcbind),mount 实际走 NFS 2049。
$ nc -zv nfs.example.com 111 # rpcbind
$ nc -zv nfs.example.com 2049 # NFS
# 两个都要通
NFSv4 可以只用 2049(rpcbind 不必要)。
反面 3:showmount 报"Connection refused"
$ showmount -e nfs.example.com
clnt_create: RPC: Program not registered
# 或
clnt_create: RPC: Unable to receive
可能:
- NFS server 没跑
- 防火墙挡 111 / 2049
- server 关了 rpcbind(NFSv4 only 配置)
修:
# server 上
$ systemctl status nfs-kernel-server
$ systemctl status rpcbind # 可能要起
反面 4:nfsstat 计数从开机以来累计
$ nfsstat -c
calls 1000000 retrans 5000
5000 重传是开机以来累计——可能是开机时一次抖动。看当前速率:
# 比较 1 秒前后
$ nfsstat -c > /tmp/a; sleep 60; nfsstat -c > /tmp/b
$ diff /tmp/a /tmp/b
或者用 Prometheus rate()。