1. NFS介绍
NFS(Network File System),网络文件系统,它可以让不同主机能够通过 TCP/IP
网络共享
资源。它从宏观主体上简化来看,就是两部分:服务端和客户端。
服务端,可以认为它就是来存东西的,这个东西对外是共享的。
客户端,可以认为它是访问服务端上的东西的,可以对服务端共享出来的东西进行读/写。当然读还是写,这些权限在服务端是可以控制的。
举个例子的话,可以想象一下仓库和员工,仓库可以认为是服务端,员工是客户端,员工只要有访问仓库的权限,那就可以看仓库有什么东西,从仓库拿东西或者往仓库放东西。
画个草图如下:
想弄得再明白一点,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)
3.1.2 配置文件/etc/exports.d/*.exports
在目录下/etc/exports.d目录下新建一个配置文件 {自己起名字}.exports
文件内容语法和 /etc/exports
写法一样的。
这两种方法可以同时配置。
3.1.3 配置文件参数
exports配置文件中的参数说明:
参数 | 含义 |
---|---|
fsid | |
ro | 该主机对该共享目录有只读权限 |
rw | 该主机对该共享目录有读写权限 |
sync | 资料同步写入到内存与硬盘中 |
async | 资料会先暂存于内存中,而非直接写入硬盘 |
all_squash |
重点参数详解
3.1.3.1 fsid
文件系统都有id, 在NFS上伪文件系统的id称为fsid。
NFS的fsid可以不用填,通常如果文件系统有uuid的话,它会用文件系统的uuid作为fsid,或者文件系统存储在设备上的话,使用设备号作为fsid。(从官网资料【5.3】上翻译过来的,我理解这里指的是共享目录所在的文件系统或设备,也有可能不对,后面了解更多再修改补充。)
但不是所有的文件系统都存储在设备上,也不是所有的文件系统都有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中配置的目录都共享出来了。
3.2 NFS客户端
挂载NFS服务端共享出来的目录
最简单直接的挂载
mount 192.168.xx.xx:/storage/nfs_server /mnt/nfs
挂载的时候也能指定其他参数,例如:
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
参数说明:
pass
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章节。
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