介绍
NFS(Network File System)是一种用于在网络上共享文件和目录的协议,已成为UNIX和Linux系统中最常用的网络文件系统之一。 它允许客户端透明地访问远程的文件和目录。它使用客户端-服务器架构和RPC协议进行通信,提供了透明访问、安全性和权限控制等功能。
NFS最早是在1984年由Sun Microsystems开发出来的,作为Sun的一项研究项目。该项目的目标是通过网络共享文件系统,使计算机能够透明地访问远程文件,就像访问本地文件一样。 Sun在1989年发布了NFS的第一个公开版本,它成为了Unix系统中的一个重要组成部分。之后,NFS的规范逐渐发展和完善,并成为了网络文件系统的事实标准。
大致原理
NFS在实现中依赖于rpcbind(在一些系统中也被称为portmap)。rpcbind是一个系统服务,它在UNIX和Linux系统中提供了远程过程调用(RPC)的端口映射功能。 rpcbind的主要作用是为远程过程调用(RPC)程序提供端口映射服务。RPC是一种机制,允许程序在网络上的不同计算机之间进行通信和调用。 每个RPC程序都需要绑定到一个特定的端口号,以便其他程序能够找到并与之通信。rpcbind维护一个端口号到RPC程序的映射表,并在需要时提供该映射信息给其他程序。
关于RPC:(Remote Procedure Call)远程过程调用协议。简单说,就是本地需要执行一个程序函数(Procedure),但受限于本地CPU,内存或其他等因素,本地执行需要花费较长时间, 而网络上有其他机器,它执行该函数非常快,那么可以将本地需要执行的该函数交付给网络上的机器,让他们执行,然后把结果传回来。对于程序逻辑而言,函数的调用就和在本地执行没有区别。这就是RPC, 一般可以实现分布式计算,具有分布式服务提供,部署灵活,解构服务,可扩展性好等特点。
要实现RPC,也需要解决一些问题,如传输信息需要序列化和编解码,保证双方获取到的程序参数和结果的二进制结构正确无误,并应能实现高效传输。;服务注册,本地机器如何知道网络上存在机器 能够支持本地机器需要执行的函数(过程,服务),需要能正确的发现支持的服务。
RPC在应用层的使用,一般可以可以使用一些厂商实现的RPC框架。比如谷歌的gRPC框架,Apache的Thrift框架等,国内大厂也都有自己实现的RPC框架。不同的RPC框架,性能,支持的开发语言也略有不同。
为什么NFS依赖rpcbind ?
NFS使用RPC协议进行客户端和服务器之间的通信。在NFS的架构中,客户端通过RPC调用向服务器发送NFS请求。然而,NFS服务器通常会绑定到动态分配的端口号,这使得客户端很难在连接时确定NFS服务器的端口号。这就是rpcbind的作用。 当NFS客户端启动时,它会向rpcbind发送一个请求,询问指定的RPC程序(例如NFS)绑定到哪个端口号。rpcbind会查找映射表,并返回相应的端口号给NFS客户端。然后,NFS客户端就可以使用该端口号与NFS服务器建立连接,并进行文件系统的操作。 NFS通过rpcbind解决NFS服务器端口号动态分配的问题。rpcbind充当一个中间层,提供了端口映射服务,使得NFS客户端能够找到NFS服务器的正确端口号,并与之建立通信。 需要注意的是,随着技术的发展,一些新的实现中,如NFSv4版本,可以通过其他方式(如使用固定端口号)来避免对rpcbind的依赖。但对于传统的NFS实现,rpcbind仍然是必需的组件。
系统服务rpcbind
的默认端口是111
。在nfs服务器上,可以通过命令 rpcinfo -p
查看系统中的使用rpc的服务以及使用的端口。如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ rpcinfo -p
program vers proto port service
100000 4 tcp 111 portmapper
100000 3 tcp 111 portmapper
100000 2 tcp 111 portmapper
100000 4 udp 111 portmapper
100000 3 udp 111 portmapper
100000 2 udp 111 portmapper
100005 1 udp 41841 mountd
100005 1 tcp 59695 mountd
100005 2 udp 59948 mountd
100005 2 tcp 59847 mountd
100005 3 udp 39637 mountd
100005 3 tcp 38405 mountd
100003 3 tcp 2049 nfs
100003 4 tcp 2049 nfs
100227 3 tcp 2049
100003 3 udp 2049 nfs
100227 3 udp 2049
100021 1 udp 40211 nlockmgr
100021 3 udp 40211 nlockmgr
100021 4 udp 40211 nlockmgr
100021 1 tcp 42137 nlockmgr
100021 3 tcp 42137 nlockmgr
100021 4 tcp 42137 nlockmgr
nfs
服务器的默认端口是2049
,不确定是否是通过 /etc/services
文件修改的。
1
2
3
$ cat /etc/services | grep nfs
nfs 2049/tcp # Network File System
nfs 2049/udp # Network File System
读写基本过程
当NFS客户端挂载了NFS共享目录后,对共享目录中的文件操作,并最终到服务器上读写磁盘的过程大致如下:
首先,对共享的nfs目录中的文件操作,通过系统调用 read,write
等发起请求,OS内核首先检查该文件在本地缓存中是否存在,没有则需要从NFS服务器获取数据。内核将发起一个NFS请求,该请求被封装成RPC消息,包括NFS的操作(如读取或写入)以及相关的文件和路径信息等。 然后将该RPC消息发送到NFS服务器。NFS服务器接收RPC消息,并进行解析处理。随后,服务器端根据NFS请求中指定的操作类型和相关信息在本地执行相对应的文件系统操作。如果是读取,NFS服务器将读取文件的数据块,并封装成NFS响应消息返回给客户端,如果是写入,服务器将客户端发送的数据写入相应的文件。 NFS服务器处理完成后,向客户端发送响应。
这个操作的过程主要都是在内核中完成的,对于用户程序而言,和读写本地磁盘文件没有差别,因为文件系统这一层,抽象掉了磁盘,只能看到对文件和目录的操作,所以用户程序感觉不到差异。
安装配合和使用
在ubuntu系统上测试。先准备服务器。
先进行安装
1
2
sudo apt-get update
sudo apt-get install nfs-kernel-server
安装完毕后,可以通过rpcinfo -p
或$ sudo netstat -pnl | grep 2049
命令查看nfs服务器是否启动,nfs服务器是在内核空间的,所以netstat中看不到程序名。
配置
编辑nfs配置文件/etc/exports
,用于配置哪些目录被共享,以及相关共享参数设置等。这里共享的目录为 /nfshare
。 配置信息的编写,详情和其他示例参考 man 5 exports
,这里简写几个示例
1
2
3
/nfshare *(rw,sync,no_root_squash,no_subtree_check)
# /nfshare 192.168.1.0/24(rw,sync,no_root_squash,no_subtree_check)
# /nfshare master(rw) trusty(rw,no_root_squash)
第一个字段为共享的目录,后面是共享的客户端机器。客户端机器可以有多个,可以使用指定某主机,IP网段,支持通配符的域名等。 上例中,第一行的*
即为允许所有机器来访问共享目录。第二行则是允许192.168.1.xxx
这个网段的所有机器,第三行指定特定主机。 机器后面填写共享参数,上例中 rw,sync,no_root_squash,no_subtree_check
,指定了4个参数,分别表示客户端可读写,同步 修改到本地磁盘,允许客户端使用root权限,不进行子文件树检查。具体解释参考手册,这是一个比较开放的配置。
然后运行以下命令,让nfs共享的目录重新生效。
1
2
sudo exportfs -a
systemctl status nfs-server.service # 查看状态
防火墙
开启防火墙时,确认对应用到的端口保持开放。
随后客户端可以挂载该目录使用了。
先安装客户端必要组件
1
2
sudo apt-get update
sudo apt-get install nfs-common
之后可以挂载了。
先使用命令 showmount
查看nfs-server的共享目录信息,该工具也属于nfs-common软件包,可以查看nfs服务器共享的目录。
1
showmount -e [nfs-server]
挂载,并查看
1
2
3
sudo mkdir -p /root/host1_share/
sudo mount.nfs 192.168.1.12:/nfshare /root/host1_share/
sudo df -h
将nfs服务器192.168.1.12
的/nfshare
共享目录挂载到本地的/root/host1_share/
目录,然后使用df -h
查看,包含如下内容
1
192.168.1.12:/nfspub 1.8T 1.4T 375G 79% /root/host1_share
可以读写测试下。
自动挂载
通过编辑文件 /etc/fstab
,添加挂载项即可。
1
2
3
4
NFS_Server:/path/to/shared/directory /path/to/local/mount/point nfs defaults 0 0
# 参考示例
192.168.1.100:/shared /mnt/nfs nfs defaults 0 0
可以使用moount -a
立即生效。
优缺点
NFS文件系统具有一些优点和缺点,下面是它们的总结:
优点:
易于使用和部署:NFS的配置和使用较为简单,易于在网络上共享文件和目录,并且可以快速部署在多个客户端和服务器之间。
透明性和互操作性:NFS提供了透明访问的能力,使得客户端可以像访问本地文件一样访问远程文件。另外,它是跨平台的,可以在不同的操作系统之间进行文件共享,包括Linux、UNIX和Windows等。
性能:NFS在网络上提供了高性能的文件共享。它可以有效地处理大量的并发读写请求,并在多个客户端之间提供高速数据传输。
缺点:
安全性问题:NFS最初设计时没有考虑到安全性问题,因此它在默认配置下可能存在安全风险。未经适当配置和保护的NFS共享可能容易受到未经授权的访问和数据泄露的风险。 为确保安全,必须进行适当的配置和安全性措施,如访问控制列表(ACL)、防火墙规则和数据加密等。
性能受网络条件影响:NFS的性能取决于网络的带宽和延迟等因素。较差的网络连接可能导致较慢的文件访问速度和延迟问题。对于跨地理区域或高延迟网络的远程访问,性能可能会受到更大的影响。
单点故障:NFS服务器成为整个文件系统的单点故障。如果NFS服务器出现故障或不可用,将无法访问共享的文件和目录。为了提高可靠性和容错性,需要使用冗余和备份策略,如使用多个NFS服务器和数据镜像等。
文件一致性问题:由于NFS的延迟和缓存机制,可能会导致在多个客户端之间的文件一致性问题。当一个客户端修改了一个文件时,其他客户端可能不会立即看到该修改,直到缓存刷新或使用特定的同步机制。这需要在应用程序中进行适当的处理和管理,以确保文件一致性和数据完整性。
综上所述,NFS适合在需要简单的文件共享、跨平台共享和高并发读写操作的场景下使用,特别是在需要快速部署和扩展的情况下。它为多个用户和计算机提供了方便的文件访问和共享能力。
其他相关工具
nfsstat
nfs统计信息。
nfsiostat
查看NFS的共享性能。
exportfs
管理和导出的NFS文件系统的共享目录。
showmount
获取nfs服务器的共享目录信息。