1、什么是nfs

(1)NFS(Network File System)是网络文件系统,能让使用者访问网络上别处的文件就像在使用自己的计算机一样;
(2)NFS是基于UDP/IP协议的应用,其实现主要是采用远程过程调用RPC机制,RPC提供了一组与机器、操作系统以及低层传送协议无关的存取远程文件的操作;
(3)NFS可用于不同类型计算机、操作系统、网络架构和传输协议运行环境中的网络文件远程访问和共享;
(4)NFS是服务器/客户端架构,服务器可允许多个客户端访问,服务器向客户端提供对本地文件系统的访问权限,实现网络中文件共享;

2、NFS服务器的工作原理

2.1、NFS和RPC的关系

(1)RPC(Remote Procedure Call Protocol)远程过程调用协议,一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议;
(2)RPC最主要的功能就是指定每个NFS功能所对应的端口,并返回给客户端,使客户端可以连接到正确的端口上;
(3)NFS是依赖RPC才能工作:NFS是一种文件系统,RPC负责在设备间的通过网络传输信息;
(4)NFS服务端常用的端口为2049,但是NFS功能有很多,每个功能就是一个程序,按照TCP/IP协议,计算机中每个程序在传输层都需要有一个端口号,这些端口都是随机产生并且小于1024;(NFS是基于网络的应用,属于套接字程序,所以需要端口号)
(5)NFS的每个程序都先要向RPC注册端口号,所以必须在启动NFS前先启动RPC服务器;
(6)RPC服务器的端口号是111,NFS客户端挂载NFS服务器时,先通过RPC的客户端连接RPC的服务器端,获取到NFS对应程序的端口号,然后再建立连接;

2.2、NFS服务器工作流程

(1)先启动RPC服务,RPC对外的端口是111;
(2)启动NFS服务器,NFS服务器会向RPC注册相应的端口;

2.3、NFS客户端工作流程

(1)当NFS客户端需要连接到服务器上时,先启动客户端的RPC服务,客户端的RPC向服务端的RPC 111端口索要功能对应的端口号;
(2)向服务器端索要到端口号后,便连接到NFS服务对应功能的端口,随后传输数据;
补充:即使客户端已经获取了端口号,客户端仍会借助rpc做为中间人进行通信;

3、rpcbind和portmap的关系

(1)rpcbind和portmap都是在NFS中提供RPC协议层的工具,功能是类似的;
(2)目前的趋势是用rpcbind来替代portmap;

4、NFS的常用命令

(1)rpcbind:启动RPC服务;
(2)rpc.nfsd:管理客户端是否能够使用服务器文件系统挂载信息等, 其中还包含这个登入者的 ID 的判别;
(3)rpc.mountd:读NFS的配置文件/etc/exports来比对客户端的权限,管理NFS分享之目录的权限与安全设定;
(4)rpc.lockd:解决多个客户端同时操作同一份文件的问题;(同时在客户端与服务器端都开启才行)
(5)rpc.statd:监听来自其他主机的重启通知,与sm-notify配套使用,主要应用与NFS V3协议,NFS V4协议中该功能由内核来完成;
(6)exportfs:导出NFS共享目录,客户端可以通过NFS服务访问服务器的这些共享目录;
(7)showmount:显示服务器端mount相关的配置信息;(showmount -e :查看当前的共享目录)
(8)sm-notify:如果服务器和客户端的重启,向其他NFS终端发送该终端重启的通知,主要应用于NFS V3协议,NFS V4协议中该功能由内核来完成;
(9)umount:卸载网络共享目录;
(10)mount:挂载共享目录;

5、nfs服务器端搭建

5.1、开源工具的移植

5.1.1、libtirpc移植

5.1.1.1、源码下载

(1)源码下载网址:https://sourceforge.net/projects/libtirpc/;

5.1.1.2、源码编译

./configure  --disable-gssapi --prefix=/home/root/NFS/libtirpc/bin --host=aarch64-mix410-linux
make
make install

(1)–disable-gssapi:禁止gssapi功能,改功能不影响主体功能,编译环境不支持可以禁止;
(2)–prefix:指定安装目录,将来执行"make install"命令,会将生成的动态库、静态库、头文件安装到该目录;
(3)–host:指定编译工具;

5.1.2、rpcbind移植

5.1.2.1、源码下载

(1)源码下载网址:https://www.linuxfromscratch.org/blfs/view/8.3/basicnet/rpcbind.html

5.1.2.2、源码编译
./configure TIRPC_CFLAGS="-I/home/root/NFS/libtirpc/bin/include/tirpc" TIRPC_LIBS="-L/home/root/NFS/libtirpc/bin/lib -ltirpc" --without-systemdsystemunitdir --host=aarch64-mix410-linux --prefix=/home/310793/phoneGate/nfs/rpcbind/bin
make
make install

(1)TIRPC_CFLAGS:指定libtirpc库的头文件路径;
(2)TIRPC_LIBS:指定libtirpc.a的路径;
(3)–prefix:指定安装目录,将来执行"make install"命令,会将生成的动态库、静态库、头文件安装到该目录;
(4)–host:指定编译工具;
总结:得到rpcbind和rpcinfo命令;

5.1.3、nfs-utils移植

5.1.3.1、源码下载

(1)源码下载地址:https://www.linuxfromscratch.org/blfs/view/8.3/basicnet/nfs-utils.html;

5.1.3.2、源码编译
./configure  TIRPC_CFLAGS="-I/home/root/NFS/libtirpc/bin/include/tirpc" TIRPC_LIBS="-L/home/root/NFS/libtirpc/bin/lib -ltirpc" --disable-nfsv4 --disable-nfsv41 --disable-gss --disable-uuid  --disable-ipv6 --with-tirpcinclude=/home/root/NFS/libtirpc/bin/include/tirpc --host=aarch64-mix410-linux --prefix=/home/root/NFS/utils/bin --disable-mount
make
make install

(1)TIRPC_CFLAGS:指定libtirpc库的头文件路径;
(2)TIRPC_LIBS:指定libtirpc.a的路径;
(3)–prefix:指定安装目录,将来执行"make install"命令,会将生成的动态库、静态库、头文件安装到该目录;
(4)–host:指定编译工具;
总结:得到rpc.mountd、rpc.nfsd、rpc.statd、sm-notify、showmount等命令;

5.2、内核修改

File systems  --->
	[*] Network File Systems  ---> 
		<*> NFS server support                                                                                           
			-*- NFS server support for NFS version 3                                                                        
			[*] NFS server support for the NFSv3 ACL protocol extension                                                       
			[*]     NFS server support for NFS version 4                                                                     
			[*]   NFSv4.1 server support for pNFS block layouts                                                              
			[*]   NFSv4.1 server support for pNFS SCSI layouts                                                                
			[*]   NFSv4.1 server support for pNFS Flex File layouts

修改内核的配置文件,支持NFS server功能;

5.3、文件系统修改

5.3.1、启动脚本中开启nfs服务

mkdir /var/lib/nfs
chmod 777 -R /var/lib
mkdir /var/run
touch /var/run/rpcbind.lock
rpcbind
exportfs -av
rpc.mountd
rpc.statd --no-notify
rpc.nfsd
sm-notify

在内核启动脚本中添加上面的脚本开启nfs服务器,可以加在/etc/rcS文件中;

5.3.2、设置nfs共享目录

/data/appdata/ *(rw,no_root_squash,sync)
/mnt/ 192.168.1.1(rw,no_root_squash,sync)

(1)增加/etc/exports文件,设置nfs共享目录的路径;
(2)上面的设置中nfs共享目录有两个,都是可读写、同步、允许非root用户去挂载;
(3)/data/mnt/目录做了额外限制,只允许ip地址是192.168.1.1的设备去挂载,增加安全性;

5.3.3、在网络初始化中增加nfs

nfs 2049/tcp nfsd
nfs 2049/udp nfsd

(1)在/etc/services中保存了主机中所有网络服务的端口号,需要确认文件中是否已经添加上面两句;
(2)不添加上面的代码,执行rpc.nfsd会报错:Starting NFS daemon: rpc.nfsd: unable to resolve ANYADDR:nfs: Servname not supported for ai_socktype;

5.3.4、增加/etc/netconfig文件

#
# The network configuration file. This file is currently only used in
# conjunction with the TI-RPC code in the libtirpc library.
#
# Entries consist of:
#
#       <network_id> <semantics> <flags> <protofamily> <protoname> \
#               <device> <nametoaddr_libs>
#
# The <device> and <nametoaddr_libs> fields are always empty in this
# implementation.
#
udp        tpi_clts      v     inet     udp     -       -
tcp        tpi_cots_ord  v     inet     tcp     -       -
udp6       tpi_clts      v     inet6    udp     -       -
tcp6       tpi_cots_ord  v     inet6    tcp     -       -
rawip      tpi_raw       -     inet      -      -       -
local      tpi_cots_ord  -     loopback  -      -       -
unix       tpi_cots_ord  -     loopback  -      -       -

(1)不添加/etc/netconfig文件,rpcbind命令会异常退出;
(2)netconfig文件可以去已经搭建完成nfs服务器的虚拟机里拷贝出来;

6、nfs客户端搭建

6.1、内核修改

File systems  --->
	[*] Network File Systems  ---> 
		<*>   NFS client support                                                                                       
			<*>     NFS client support for NFS version 2                                                                     
			<*>     NFS client support for NFS version 3                                                                     
			[*] NFS client support for the NFSv3 ACL protocol extension                                                       
			< >     NFS client support for NFS version 4                                                                     
			[*]   NFS: Disable NFS UDP protocol support

内核开启nfs客户端的支持;

6.2、挂载命令

mount -t nfs 192.168.2.100:/data/appdata/ /tmp/share -o nolock,tcp

7、调试的注意事项

(1)如果nfs共享的目录本身就是只读文件系统,就算以可读写方式挂载,最后也是只读;
(2)客户端挂载不上服务器端的共享目录,检查服务器端是否关闭防火墙、是否允许非root用户挂载;
(3)查看服务器端当前的共享目录:showmount -e;
(4)修改共享目录后要刷新:exportfs -rv;
(5)查看rpc的端口号:rpcinfo -p;

8、nfs版本不匹配引起的报错

8.1、报错信息

unable to get mount port number from server, using default
VFS: Unable to mount root fs via NFS, trying floppy.

8.2、查看支持的nfs版本

# 服务器端
~ # cat /proc/fs/nfsd/versions 
-2 +3 +4 +4.1 +4.2

#客户端:在内核的配置表里可以查看(make menuconfig)
File systems  --->
	[*] Network File Systems  ---> 
		<*>   NFS client support                                                                                       
			<*>     NFS client support for NFS version 2                                                                     
			<*>     NFS client support for NFS version 3                                                                     
			[*] NFS client support for the NFSv3 ACL protocol extension                                                       
			< >     NFS client support for NFS version 4                                                                     
			[*]   NFS: Disable NFS UDP protocol support

从上面的信息可以看出,服务器端和客户端同时支持3和4版本的nfs;

8.3、解决办法:指定一个同时支持的nfs版本

mount -t nfs 192.168.2.100:/data/appdata/ /tmp/share -o nolock,tcp,nfsvers=3

(1)在用mount命令挂载时,一般是不用指定nfs版本的,会默认使用一个版本;
(2)当出现上面报错,并查看服务器/客户端有同时支持的nfs版本时,可用“nfsvers”关键字在mount时指定nfs版本;