纸上得来终觉浅,绝知此事要躬行。
1. NFS 协议
NFS
服务工作在TCP
的2049
端口,UDP
的2049
端口。
NFS
是Network File System
的缩写,即网络文件系统,是一种使用于分散式文件系统的协定。功能是通过网络让不同的机器、不同的操作系统能够彼此分享个别的数据,让应用程序在客户端通过网络访问位于服务器磁盘中的数据,是在类Unix
系统间实现磁盘文件共享的一种方法。
这个NFS
服务器可以让你的PC
来将网络远程的NFS
服务器分享的目录,挂载到本地端的机器当中, 在本地端的机器看起来,那个远程主机的目录就好像是自己的一个磁盘分区槽一样。
1.1 工作原理
因为 NFS
支持的功能相当的多,而不同的功能都会使用不同的程序来启动, 每启动一个功能就会启用一些端口来传输数据,因此, NFS
的功能所对应的端口才没有固定住, 而是随机取用一些未被使用的小于 1024
的端口来作为传输之用。但如此一来又造成客户端想要连上服务器时的困扰, 因为客户端得要知道服务器端的相关端口才能够联机吧!
NFS
在文件传送或信息传送过程中依赖于RPC
协议。RPC
,即远程过程调用的缩写,是能使客户端执行其他系统中程序的一种机制。RPC
最主要的功能就是在指定每个 NFS
功能所对应的端口号,并且回报给客户端,让客户端可以连结到正确的端口上去。
NFS
本身是没有提供信息传输的协议和功能的,但NFS
却能让我们通过网络进行资料的分享,这是因为NFS
使用了一些其它的传输协议。而这些传输协议用到这个RPC
功能的。可以说NFS
本身就是使用RPC
的一个程序,或者说NFS
也是一个RPC SERVER
。所以只要用到NFS
的地方都要启动RPC
服务,不论是NFS SERVER
或者NFS CLIENT
。这样SERVER
和CLIENT
才能通过RPC
来实现PROGRAM PORT
的对应。可以这么理解RPC
和NFS
的关系:**NFS
是一个文件系统,而RPC
是负责负责信息的传输**。
事实上,有很多这样的服务器都是向 RPC
注册的,举例来说,NIS
(Network Information Service
) 也是 RPC server
的一种。
那RPC
又是如何知道每个NFS
的端口呢?
- 这是因为当服务器在启动
NFS
时会随机取用数个端口,并主动的向RPC
注册,因此RPC
可以知道每个埠口对应的NFS
功能,然后RPC
又是固定使用111
端口来监听客户端的需求并报客户端正确的埠口, 所以当然可以让NFS
的启动更为轻松愉快了。 - 所以你要注意,要启动
NFS
之前,RPC
就要先启动了,否则NFS
会无法向RPC
注册。 另外,RPC
若重新启动时,原本注册的数据会不见,因此RPC
重新启动后,它管理的所有服务都要重新启动来重新向RPC
注册。
那客户端如何向NFS
服务端交换数据数据呢?
- (1) 客户端会向服务器端的
RPC
的111
端口发出NFS
档案存取功能的询问要求 - (2) 服务器端找到对应的已注册的
NFS
守护进程端口后,会回报给客户端 - (3) 客户端了解正确的端口后,就可以直接与
NFS
守护进程来联机
1.2 激活 NFS 服务
NFS
服务需要激活几个重要的RPC
守护进程
工作流程
nfs—client
=>portmapper
=>mountd
=>nfs-server(nfsd)
(1) rpc.nfsd
- 这个守护进程主要的功能,则是在管理客户端是否能够登入主机的权限,其中还包含这个登入者的
ID
的判别。
(2) rpc.mountd
- 主要功能
- 这个守护进程主要的功能,则是在管理
NFS
的档案系统,用于给用户提供访问令牌。 - 访问的令牌,由本地的
RPC
提供随机端口。本地的RPC
叫做portmapper
,可以使用rpcinfo -P
查看。 RPC
的portmapper
服务工作在1111
端口。
- 这个守护进程主要的功能,则是在管理
- 请求过程
- 当客户端顺利的通过
rpc.nfsd
而登入主机之后,在它可以使用NFS server
提供的档案之前,还会经过档案使用权限 的认证程序,就是那个-rwxrwxrwx
、owner
、group
那几个权限啦。 - 然后它会去读
NFS
的设定档/etc/exports
来比对客户端的权限,当通过这一关之后,客户端就可以取得使用NFS
档案的权限啦。
- 当客户端顺利的通过
注释:NFS
需要有两个套件
nfs-utils
NFS
服务的主要套件- 提供
rpc.nfsd
和rpc.mountd
两个NFS
守护进程和与其它相关文档与说明文件、执行档等的套件
portmap
- 主要负责
RPC
端口和守护进程的映射关系,即portmapper
- 在激活任何一个
RPC server
之前,我们都需要激活portmapper
才行
- 主要负责
1.3 各个版本之间的比较
NFS
是一种网络文件系统,从1985
年推出至今,共发布了3
个版本:NFSv2
、NFSv3
、NFSv4
,NFSv4
包含两个次版本NFSv4.0
和NFSv4.1
。经过20
多年发展,NFS
发生了非常大的变化,最大的变化就是推动者从Sun
变成了NetApp
,NFSv2
和NFSv3
基本上是Sun
起草的,NetApp
从NFSv4.0
参与进来,并且主导了NFSv4.1
标准的制定过程,而Sun
已经被Oracle
收购了。
编号 | 协议版本 | RFC | 时间 | 页数 |
---|---|---|---|---|
1 | NFSv2 |
rfc1094 | 1989 年 3 月 | 27 页 |
2 | NFSv3 |
rfc1813 | 1995 年 6 月 | 126 页 |
3 | NFSv4.0 |
rfc3530 | 2003 年 4 月 | 275 页 |
4 | NFSv4.1 |
rfc5661 | 2010 年 1 月 | 617 页 |
1. NFSv2
NFSv2
是第一个以RFC
形式发布的版本,实现了基本的功能。
2. NFSv3
- 协议特点
NFSv3
修正了NFSv2
的一些bug
,两者有如下一些差别,但是感觉没有本质的差别。
- 区别差别
- (1)
NFSv2
只支持同步写,如果客户端向服务器端写入数据,服务器必须将数据写入磁盘中才能发送应答消息。NFSv3
支持异步写操作,服务器只需要将数据写入缓存中就可以发送应答信息了。 - (2)
NFSv3
增加了ACCESS
请求,ACCESS
用来检查用户的访问权限。因为服务器端可能进行uid
映射,因此客户端的uid
和gid
不能正确反映用户的访问权限。 - (3) 一些请求调整了参数和返回信息,毕竟
NFSv3
和NFSv2
发布的间隔有6
年,经过长期运行可能觉得NFSv2
某些请求参数和返回信息需要改进。
- (1)
3. NFSv4.0
- 协议特点
- 相比
NFSv3
,NFSv4
发生了比较大的变化,最大的变化是NFSv4
有状态了。NFSv2
和NFSv3
都是无状态协议,服务区端不需要维护客户端的状态信息。 - 无状态协议的一个优点在于灾难恢复,当服务器出现问题后,客户端只需要重复发送失败请求就可以了,直到收到服务器的响应信息。
- 相比
- 区别差别
- (1)
NFSv4
增加了安全性,支持RPCSEC-GSS
身份认证。 - (2)
NFSv4
设计成了一种有状态的协议,自身实现了文件锁功能和获取文件系统根节点功能。 - (3)
NFSv4
只提供了两个请求NULL
和COMPOUND
,所有的操作都整合进了COMPOUND
中,客户端可以根据实际请求将多个操作封装到一个COMPOUND
请求中,增加了灵活性。 - (4)
NFSv4
文件系统的命令空间发生了变化,服务器端必须设置一个根文件系统(fsid=0
),其他文件系统挂载在根文件系统上导出。 - (5)
NFSv4
支持delegation
。由于多个客户端可以挂载同一个文件系统,为了保持文件同步,NFSv3
中客户端需要经常向服务器发起请求,请求文件属性信息,判断其他客户端是否修改了文件。如果文件系统是只读的,或者客户端对文件的修改不频繁,频繁向服务器请求文件属性信息会降低系统性能。NFSv4
可以依靠delegation
实现文件同步。 - (6)
NFSv4
修改了文件属性的表示方法。由于NFS
是Sun
开发的一套文件系统,设计之出NFS
文件属性参考了UNIX
中的文件属性,可能Windows
中不具备某些属性,因此NFS
对操作系统的兼容性不太好。
- (1)
4. NFSv4.1
- 与
NFSv4.0
相比,NFSv4.1
最大的变化是支持并行存储了。在以前的协议中,客户端直接与服务器连接,客户端直接将数据传输到服务器中。 - 当客户端数量较少时这种方式没有问题,但是如果大量的客户端要访问数据时,
NFS
服务器很快就会成为一个瓶颈,抑制了系统的性能。NFSv4.1
支持并行存储,服务器由一台元数据服务器(MDS
)和多台数据服务器(DS
)构成,元数据服务器只管理文件在磁盘中的布局,数据传输在客户端和数据服务器之间直接进行。由于系统中包含多台数据服务器,因此数据可以以并行方式访问,系统吞吐量迅速提升。
2. NFS 服务
CentOS7
以NFSv4
作为默认版本,NFSv4
使用TCP
协议(端口号是2049
)和NFS
服务器建立连接。
# 系统环境
系统平台:CentOS release 7.0 (Final)
NFS Server IP:192.168.10.10
防火墙已关闭/iptables: Firewall is not running.
SELINUX=disabled
2.1 安装 NFS 服务
- 服务端
- 服务端,程序包名
nfs-utils
、rpcbind
,默认都已经安装了 - 可以通过
rpm -ql nfs-utils
查看帮助文档等信息
- 服务端,程序包名
- 客户端
- 客户端,需要安装程序包名
nfs-utils
,提供基本的客户端命令工具
- 客户端,需要安装程序包名
[root@localhost ~]# yum install nfs-utils
Loaded plugins: langpacks, product-id, subscription-manager
......
Package 1:nfs-utils-1.3.0-0.el7.x86_64 already installed and latest version
Nothing to do
- 查看
NFS
服务端口NFS
启动时会随机启动多个端口并向RPC
注册,为了方便配置防火墙,需要固定NFS
服务端口。- 这样如果使用
iptables
对NFS
端口进行限制就会有点麻烦,可以更改配置文件固定NFS
服务相关端口 - 分配端口,编辑配置文件
/etc/sysconfig/nfs
# 使用rpcinfo -P会发现rpc启动了很多监听端口
[root@localhost ~]# rpcinfo -p localhost
program vers proto port service
100000 4 tcp 111 portmapper
100000 2 udp 111 portmapper
100005 1 udp 49979 mountd
100005 1 tcp 58393 mountd
100003 2 tcp 2049 nfs
100227 2 tcp 2049 nfs_acl
......
# 添加如下
[root@localhost ~]# vim /etc/sysconfig/nfs
RQUOTAD_PORT=30001
LOCKD_TCPPORT=30002
LOCKD_UDPPORT=30002
MOUNTD_PORT=30003
STATD_PORT=30004
- 启动服务
[root@localhost ~]# service nfs start
Starting NFS services: [OK]
Starting NFS quotas: [OK]
Starting NFS mountd: [OK]
Starting NFS daemon: [OK]
Starting NFS idmapd: [OK]
2.2 服务文件配置
- 相关文件和命令
文件名 | 说明 |
---|---|
/etc/exports |
NFS 服务器端需要设定的内容,其作用是设定谁拥有什么样的权限去访问此机器的哪个目录 |
/var/lib/nfs/etab |
无需设定,用于纪录 NFS 服务器完整的权限设定,exports 中没有设定的缺省值也会被列出 |
/var/lib/nfs/xtab |
纪录 NFS 连接的相关信息 |
/usr/sbin/exportfs |
NFS 设定管理命令,用于 Server 侧设定,通过此条命令使得 exports 的设定变得有效或者无效 |
/usr/sbin/showmount |
用于显示 NFS 设定的相关信息,Server 端和 Client 端均可 |
配置文件/etc/exports
- 我们可以按照“共享目录的路径 允许访问的 NFS 客户端(共享权限参数)”的格式,定义要共享的目录与相应的权限
常用参数 | 作用 |
---|---|
ro |
只读 |
rw |
读写 |
sync |
同时将数据写入到内存与硬盘中,保证不丢失数据 |
async |
优先将数据保存到内存,然后再写入硬盘;这样效率更高,但可能会丢失数据 |
root_squash |
当 NFS 客户端以 root 管理员访问时,映射为 NFS 服务器的匿名用户 |
all_squash |
无论 NFS 客户端使用什么账户访问,均映射为 NFS 服务器的匿名用户 |
no_root_squash |
当 NFS 客户端以 root 管理员访问时,映射为 NFS 服务器的 root 管理员 |
secure |
这个选项是缺省选项,它使用了 1024 以下的 TCP/IP 端口实现 NFS 的连接 |
insecure |
禁止使用了 1024 以下的 TCP/IP 端口实现 NFS 的连接 |
no_wdelay |
这个选项关闭写延时,如果设置了 async,那么 NFS 就会忽略这个选项 |
nohide |
如果将一个目录挂载到另外一个目录之上,那么原来的目录通常就被隐藏起来或看起来像空的一样。要禁用这种行为,需启用 hide 选项 |
no_subtree_check |
这个选项关闭子树检查,子树检查会执行一些不想忽略的安全性检查,缺省选项是启用子树检查 |
no_auth_nlm |
这个选项也可以作为insecure_locks 指定,它告诉 NFS 守护进程不要对加锁请求进行认证。如果关心安全性问题,就要避免使用这个选项。缺省选项是auth_nlm 或secure_locks 。 |
mp(mountpoint=path) |
通过显式地声明这个选项,NFS 要求挂载所导出的目录 |
fsid=num |
这个选项通常都在 NFS 故障恢复的情况中使用,如果希望实现 NFS 的故障恢复,请参考 NFS 文档 |
[root@localhost ~]# cat /etc/exports
/nfsfile 192.168.10.*(rw,sync,root_squash)
/tmp/serverdir 192.168.174.132(rw,sync,no_root_squash) 192.168.174.133(ro,sync,no_root_squash)
3. 实战演示
如果有兴趣,可以尝试:两台 web 服务器,共享关系型数据库,共享 NFS 服务器,利用 DNS 记录轮询提供负载均衡
- 第 1 步:机器设置
- 创建服务端和客户端
- 关闭
iptables
和selinux
服务
主机名称 | 操作系统 | IP 地址 |
---|---|---|
NFS 服务端 | RHEL 7 | 192.168.10.10 |
NFS 客户端 | RHEL 7 | 192.168.10.20 |
# 清空NFS服务器上面iptables防火墙的默认策略,以免默认的防火墙策略禁止正常的NFS共享服务
[root@localhost ~]# iptables -F
[root@localhost ~]# service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[ OK ]
第 2 步:创建共享目录
- 在
NFS
服务器上,建立用于NFS
文件共享的目录 - 在
NFS
服务器上,设置足够的权限确保其他人也有写入权限
[root@localhost ~]# mkdir /nfsfile
[root@localhost ~]# chmod -Rf 777 /nfsfile
[root@localhost ~]# echo "welcome to localhost.com" > /nfsfile/readme
- 第 3 步:编辑配置文件/etc/exports
- 定义要共享的目录与相应的权限
- 请注意,NFS 客户端地址与权限之间没有空格
# 把/nfsfile目录共享给192.168.10.0/24网段内的所有主机,让这些主机都拥有读写权限
[root@localhost ~]# vim /etc/exports
/nfsfile 192.168.10.*(rw,sync,root_squash)
第 4 步:启动和启用 NFS 服务程序
- 在启动
NFS
服务之前,还需要顺带重启并启用rpcbind
服务程序,并将这两个服务一并加入开机启动项中
[root@localhost ~]# systemctl restart rpcbind
[root@localhost ~]# systemctl enable rpcbind
[root@localhost ~]# systemctl start nfs-server
[root@localhost ~]# systemctl enable nfs-server
ln -s '/usr/lib/systemd/system/nfs-server.service' '/etc/systemd/system/nfs.target.wants/nfs-server.service'
第 5 步:NFS 客户端的配置
- 使用
showmount
命令查询NFS
服务器的远程共享信息 showmount
命令输出格式为“共享的目录名称 允许使用客户端地址”
showmount
命令
参数 | 作用 |
---|---|
-e |
显示 NFS 服务器的共享列表 |
-a |
显示本机挂载的文件资源的情况 NFS 资源的情况 |
-v |
显示版本号 |
exportfs
命令
- 维护
exports
文件导出的文件系统表的专用工具,可以修改配置之后不重启NFS
服务 export -ar
:重新导出所有的文件系统export -au
:关闭导出的所有文件系统export -u FS
::关闭指定的导出的文件系统
# 查看NFS服务器端共享的文件系统
# showmount -e NFSSERVER_IP
[root@localhost ~]# showmount -e 192.168.10.10
Export list for 192.168.10.10:
/nfsfile 192.168.10.*
# NFS客户端创建一个挂载目录,挂载服务端NFS文件系统到本地
# mount -t nfs SERVER:/path/to/sharedfs /path/to/mount_point
[root@localhost ~]# mkdir /nfsfile
[root@localhost ~]# mount -t nfs 192.168.10.10:/nfsfile /nfsfile
# 挂载成功后就应该能够顺利地看到在执行前面的操作时写入的文件内容了
[root@localhost ~]# cat /nfsfile/readme
welcome to linuxprobe.com
# 如果希望NFS文件共享服务能一直有效,则需要将其写入到fstab文件中
# SERVER:/PATH/TO/EXPORTED_FS /mount_point nfs defaults,_netdev 0 0
[root@localhost ~]# vim /etc/fstab
/dev/mapper/rhel-root / xfs defaults 1 1
UUID=812b1f7c-8b5b-43da-8c06-b9999e0fe48b /boot xfs defaults 1 2
/dev/mapper/rhel-swap swap swap defaults 0 0
/dev/cdrom /media/cdrom iso9660 defaults 0 0
192.168.10.10:/nfsfile /nfsfile nfs defaults 0 0