【NFS】NFS使用汇总

1. NFS介绍

NFS(Network File System),网络文件系统,它可以让不同主机能够通过 TCP/IP 网络共享资源。它从宏观主体上简化来看,就是两部分:服务端和客户端。

服务端,可以认为它就是来存东西的,这个东西对外是共享的。

客户端,可以认为它是访问服务端上的东西的,可以对服务端共享出来的东西进行读/写。当然读还是写,这些权限在服务端是可以控制的。

举个例子的话,可以想象一下仓库和员工,仓库可以认为是服务端,员工是客户端,员工只要有访问仓库的权限,那就可以看仓库有什么东西,从仓库拿东西或者往仓库放东西。

画个草图如下:

NFS

想弄得再明白一点,NFS具体是如何传输数据的?它是怎么把数据从服务端计算机A传送给客户端计算机B的?

网络传输的话,想起之前用python写过socket的demo,服务端绑定一个端口,并监听是否有客户端来连接;客户端那边通过端口向服务端发起连接;等连接建立之后,就可以发送数据了,实现计算机A和计算机B之间的数据传输。

NFS也可以类比,既然是网络传输,那就必然有传输端口,但是NFS有很多功能,每个功能都要启动端口传输数据,这些端口是随机的,那客户端那边就会疑惑到底要通过哪个端口连接服务端传输数据。于是引入了RPC。

RPC(Remote Procedure Call),远程过程调用,主要功能就是指定每个NFS功能所对应的端口,并返回给客户端,使客户端可以连接到正确的端口上。

下面画了一个简图,NFS服务端RPC和NFS服务端程序启动顺序,以及客户端是如何访问共享目录中的内容的。

在这里插入图片描述

2. NFS 安装

yum -y install nfs-utils

3. NFS配置

3.1 NFS服务端

配置文件有两个地方可以配置

3.1.1 配置文件/etc/exports

/storage/nfs_server *(fsid=0,rw,sync,all_squash)

注意: 后面的参数之间一定不要加空格,否则在使配置文件生效的时候会报错: syntax error: bad option list

3.1.2 配置文件/etc/exports.d/*.exports

在目录下/etc/exports.d目录下新建一个配置文件 {自己起名字}.exports

文件内容语法和 /etc/exports 写法一样的。

这两种方法可以同时配置。

3.1.3 配置文件参数

exports配置文件中的参数说明:

参数含义
fsid伪文件系统id,共享的多个目录,该值不能重复。格式:一个小整数或者32位的uuid
ro该主机对该共享目录有只读权限
rw该主机对该共享目录有读写权限
sync资料同步写入到内存与硬盘中
async资料会先暂存于内存中,而非直接写入硬盘
all_squash将发起请求的所有用户都映射为anonymous用户
no_all_squash不将发起请求的所有用户都映射为anonymous用户

重点参数详解

3.1.3.1 fsid

文件系统都有id, 在NFS上伪文件系统的id称为fsid。

NFS的fsid可以不用填,通常如果文件系统有uuid的话,它会用文件系统的uuid作为fsid;或者文件系统存储在设备上的话,使用设备号作为fsid;否则就要自己指定了,用一个小整数或者32位的uuid指定。(从官网资料【5.3】上翻译过来的,我理解这里指的是共享目录所在的文件系统或设备。)

这里对官网上说的文件系统的uuid作为fsid做个个人理解,可能不对,有懂的大佬可以指点下:
比如下图中,共享的目录是/mnt/nfs,那么NFS会把/mnt/nfs目录所在的文件系统的ID作为fsid。
如果共享的目录是/mnt/nfs1,发现/mnt/nfs1所在文件系统的ID是0,这个时候就要手动在配置文件里指定fsid了。
在这里插入图片描述

但不是所有的文件系统都存储在设备上,也不是所有的文件系统都有uuid,这个时候就需要手动明确fsid了。

针对NFS4,fsid=0有特殊含义

fsid=0 或 fsid=root, 表示共享的这个目录为根目录,啥意思?下方给个例子:

服务端的配置文件里,我设置了一个目录: /mnt/nfs,参数中加了fsid=0

在这里插入图片描述

在客户端如果我想挂载这个目录到/mnt/test,会怎么去挂载?一般会这样写:mount -t nfs4 {server_ip}:/mnt/nfs /mnt/test,这样写的执行效果如下,服务端传过来的报错是:没有/mnt/nfs这个目录,不死心又看了下服务端共享的目录,发现存在的,怎么挂不上呢?原因就在于服务端把/mnt/nfs这个目录的共享参数中加了fsid=0。

在这里插入图片描述

似乎知道fsid=0的效果是啥了,当做根目录,那挂载命令换成: mount -t nfs4 192.168.13.37:/ /mnt/test,执行效果如下,发现挂载上了,内容都可以访问到。【5.2

在这里插入图片描述

验证一

如果我在配置文件里设置了两个目录,fsid都设置为root或0,客户端挂载根目录会有什么效果呢?

测试了下如果配置2个root,挂载也不会报错,哪个目录配置在前面,挂载的根目录就是哪个,如下图所示,客户端挂载根目录后,展示的是/mnt/nfs1下的内容。

在这里插入图片描述

验证二

这里我又有疑惑了,fsid不设置为0,假设共享两个目录/mnt/nfs和/mnt/nfs1,fsid我都设置为1,在客户端挂载会有什么效果呢?会不会和上面都设置为root效果一样呢?

在这里插入图片描述

于是我在客户端这边建了两个目录分别挂载试试:

客户端将服务端的/mnt/nfs挂载到本地 /mnt/test

mount -t nfs4 192.168.13.37:/mnt/nfs /mnt/test

挂载效果符合预期

在这里插入图片描述

客户端将服务端的/mnt/nfs1挂载到本地 /mnt/test1

mount -t nfs4 192.168.13.37:/mnt/nfs1 /mnt/test1

发现异常了,挂载不会报错,但是通过 df -h 查不到挂载目录/mnt/test1,查看/mnt/test1目录展示的又是服务端/mnt/nfs目录下的内容,这里明显不符合预期。效果看起来和验证一是一样的,配置文件中只有第一个目录/mnt/nfs是生效的。

在这里插入图片描述

通过这个验证可以得出一个结论:配置共享目录时,如果指定fsid,编号不能重复,否则生效的目录永远是靠前的目录。

3.1.4 使配置文件生效

exportfs -r

导出目录之后会在文件中 /var/lib/nfs/etab 中写入记录。

3.1.5 查看服务端共享出来的目录

showmount -e {服务端ip}

给个例子:

如下图所示: /etc/exports和/etc/exports.d/*.exports中配置的目录都共享出来了。

在这里插入图片描述

如果把软连接目录配置到exportfs文件中,NFS还是只能看到共享的真实目录路径,看不到配置的软连接路径,如下图所示:

在这里插入图片描述

3.2 NFS客户端

挂载NFS服务端共享出来的目录

最简单直接的挂载

mount 192.168.xx.xx:/storage/nfs_server  /mnt/nfs

挂载的时候也能指定其他参数,例如:

例子1:

mount -tnfs4 -o rw,nfsvers=4.1,sync,lookupcache=positive,hard,timeo=600,wsize=1048576,rsize=1048576,namlen=255 192.168.xx.xx:/storage/nfs_server  /mnt/nfs

例子2:指定NFS服务端口

mount -o port=0,hard 192.168.xx.xx:/storage/nfs_server  /mnt/nfs

mount -o 参数

参数含义默认
rw
nfsvers用于连接NFS服务端的NFS协议版本号,如果服务端不支持指定的版本,会挂载失败。如果没有指明版本号,首先会试4.1,然后逐个降低版本号,直到服务端支持。nfsvers=4.1
sync
lookupcache指定内核如何管理给定挂载点的目录条目缓存。可选值:all,none, pos, positive。该选项支持内核2.6.28及以上。NFS客户端会缓存LOOKUP请求的结果,如果请求的内容在Server上存在,结果为正数(叫做正条目),不存在,结果为负数(叫做负条目)。
all: NFS客户端认为缓存目录内容的两种类型(正条目,负条目)都有效,直到父目录的缓存属性过期。
pos/positive: NFS客户端认为正条目在父目录缓存属性过期前都是有效的。
none: 应用使用缓存前,都会重新校验目录的两种条目。能快速地检测到其他客户端创建/删除的文件,但是会影响到应用程序和服务器的性能。
all
soft / hard该决定了NFS客户端请求超时后客户端恢复的行为。如果明确填了hard,或者没有指定是soft还是hard,NFS请求将无限期重试。如果指定了soft选项,NFS请求超时的话,超过指定的请求次数,此次请求将会失败,并且向应用返回错误。hard
timeoNFS客户端请求等待响应的时间。如果NFS通过TCP传输,默认是 600分秒(60秒)
wsizeNFS客户端读每次向服务端写数据时的最大bytes。范围:1024-10485761048576
rsizeNFS客户端读每次从个服务端读数据时请求的最大bytes。NFS客户端最大读取大小是1,048,576bytes,即1MB。范围是1024-1048576。如果填的不是1024倍数,会四舍五入到最接近1024的倍数的值。1048576
namlen挂载点路径名最大长度。最大是255.255
retransNFS客户端请求重试次数。3
port指定服务器NFS端口,如果不指定或者指定为0,默认使用20492049

4. 常见问题

4.1 exportfs: /mnt/nfs1 requires fsid= for NFS export

在/etc/exports中的目录权限中添加fsid参数。

4.2 mount.nfs4: mounting 192.168.xx.xx:/storage/nfs_server failed, reason given by server: No such file or directory

修改服务端配置文件/etc/exports中的fsid,不要设置为0,可能是设置成根目录导致的。参考3.1.3.1 fsid章节。

4.3 卸载目录时报错:目标忙或target is busy

  • 检查是不是cd到挂载点下没有退出来,有的话退出挂载点目录,重写卸载。
  • 看下是不是有进程正在占用目标挂载点,查出来后,对应进程杀掉,重新卸载。

查看目录被哪些进程占用:

fuser -mv /mnt/nfs

5. 参考资料

5.1 man exportfs(exportfs命令中文手册) 骏马金龙

https://www.cnblogs.com/f-ck-need-u/p/7302589.html

5.2 The /etc/exports Configuration File

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/deployment_guide/s1-nfs-server-config-exports

5.3 exports(5) - Linux man page

https://linux.die.net/man/5/exports

5.4 NFS基本应用 骏马金龙 (大佬)

https://www.cnblogs.com/f-ck-need-u/p/7305755.html#auto_id_5

6. 遗留问题

6.1 遇到过一种场景:NFS客户端挂载服务端共享目录时,很久都没有反应,挂载命令是:sudo mount -tnfs4 -o rw,nfsvers=4.1,sync,lookupcache=positive,hard,timeo=600,wsize=1048576,rsize=1048576,namlen=255 xxx.xxx.xxx.xxx:/data/nfs_server /data/nfs ,换了几个客户端都会有这个现象。当我把NFS服务端重启后,客户端重新挂载正常了,不再hung了。猜测可能是服务端那边有什么标志位状态改不了什么的,重启复位好了。有知道原因的,可以讨论下哈。

  • 23
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值