Linux NFS:网络文件系统客户端和服务器

时间:2020-03-21 11:46:06  来源:igfitidea点击:

在计算机的初期,SUN Microsystems开发了一项技术,该技术使通过网络从其他计算机访问文件变得容易。
这项技术为通过网络访问数据提供了一个新的维度,甚至在当今组织中也已广泛使用。
这项技术的优势在于,它使远程系统上的目录和分区变得可用,就好像它是本地目录或者文件系统一样。

IETF的RFC No 1094专门致力于称为网络文件系统或者NFS的这项技术。

NFS是基于IP协议的,因此可以使该协议可用于在TCP/IP上运行的任何系统。
这使得NFS在中央存储系统中起着重要作用。
尽管NFS的初始版本通过UDP而不是TCP进行工作,但后来的改进和协议的迭代使它也可以通过TCP进行工作。

最初的版本称为NFS版本1,从未发布给公众,但SUN内部使用了该版本进行实验。
像http一样,除了NFS版本4外,所有其他版本都是无状态的。

注意:无状态协议是指在不了解有关先前请求的信息的情况下发出每个请求的协议。
这意味着每个请求都彼此独立。

借助称为虚拟文件系统的API,可以在一台计算机上访问不同的文件系统。
虚拟文件系统负责处理系统上安装的所有文件系统。
同样,VFS也负责NFS。
因此,操作系统就像访问本地文件系统一样。
由于所有操作都是通过网络执行的,因此与本地文件系统相比,读写性能将较慢(但是由于网络技术的进步,即使此性能瓶颈也已得到很大改善)。

现在,让我们介绍一下有关NFS的一些值得注意的观点。

  • 挂载的NFS文件系统与计算机上的本地文件系统非常相似
  • NFS不公开文件在网络上的位置
  • NFS服务器可以由与客户端完全不同的体系结构和操作系统组成
  • 它还从不公开远程计算机上的基础文件系统

在开始使用NFS之前,对VFS稍加了解将是一个另外的优势。

什么是VFS,NFS如何在VFS上工作?

VFS为Linux内核提供了一个简单的界面来访问其下的不同文件系统。
如今,由于VFS,Linux支持大量不同的文件系统。
下图将有助于理解VFS的工作方式。

如上图所示,文件系统上所有正常操作的请求(例如查找文件大小,创建和删除文件)均由系统的VFS完成(这些操作由VFS文件完成系统称为vnode操作)。

由用户完成的这些简单操作随后会转换为基础文件系统上的实际操作。
因此,即使安装了NFS分区/共享,该分区上的所有操作也会由VFS执行。
因此,操作系统认为已挂载的NFS文件系统是本地文件系统,就像其他的一样。

诸如NFS和NIS之类的技术都依赖于称为RPC(远程过程调用)的东西。
RPC帮助将NFS安装的文件系统上的正常操作(如写入数据,更改权限等)转换为NFS服务器上的远程操作,该操作已安装在客户端上。
它的工作原理是,只要VFS(虚拟文件系统)收到在NFS挂载上执行操作的请求,NFS客户端就会将该完全相同的请求转换为NFS服务器上的等效RPC请求。

NFS客户端向服务器发出的每个RPC请求均设置了超时时间。
如果服务器未能响应请求,则在超时时间内,客户端将重新发送请求。
因此,即使NFS服务器出现故障,客户端也会继续向服务器发送RPC请求,并且一旦服务器重新联机,它就会进行正常操作,就好像什么都没发生一样。

使NFS与不同的操作系统和体系结构一起工作的另一种技术称为XDR(外部数据表示)。
该技术使不同的操作系统可以使用相同的NFS共享。
首先将请求转换为XDR格式请求,然后将其转换回服务器上的本地驻留格式。

如何设置NFS服务器?

为了设置NFS服务器和客户端,我们将使用两台计算机。
一个用于NFS客户端,另一个用于NFS服务器。

NFS服务器192.168.0.105(theitroad1)

NFS客户端192.168.0.104(theitroad2)

让我们从在Red Hat Enterprise Linux(RHEL 5)上设置NFS服务器(192.168.0.105)开始。
我们将首先在服务器上安装所需的软件包,然后将分析各种NFS协议版本和在客户端上实施该协议的方法之间的差异。

要在RHEL和Centos上设置NFS服务器,我们需要以下提到的两个重要软件包。

  • nfs-utils
  • portmap

nfs-utils软件包提供了NFS服务器功能及其必需的工具。
Portmap程序包是用于侦听基于RPC的请求的程序包。
如果运行的是nfs 1,2或者3版本,则非常需要portmap。

如前所述,客户端发出的请求首先转换为RPC等效请求,然后由NFS服务器上的RPC守护程序接受(由rhel/centos中的portmap包提供)。
让我们验证服务器上是否安装了这两个软件包。

[root@theitroad1 ~]# rpm -qa | grep portmap
portmap-4.0-65.2.2.1
[root@theitroad1 ~]# rpm -qa | grep nfs
nfs-utils-1.0.9-40.el5
nfs-utils-lib-1.0.8-7.2.z2
[root@theitroad1 ~]#

我们已经在服务器计算机上安装了这些软件包。
如果没有这些,则可以使用yum软件包管理器来安装它们,如下所示。

[root@theitroad1 ~]# yum install nfs-utils portmap

在linux中配置某些内容的简便性在于要编辑的配置文件的数量。
NFS在这方面做得很好,因为我们只需要编辑一个名为/etc/exports的文件即可上手。
该文件最初为空白,需要根据要求进行配置。

/etc/exports文件中的条目非常容易理解。
让我们看一下在该文件中进行输入的方法。

共享路径:客户端(选项)客户端(选项)

共享路径这里提到要共享的文件夹。
例如,如果要共享名为/data的文件夹,则需要在此处输入/data。

CLIENT Client指定将被允许访问此共享的主机名/IP地址。
换句话说,此处提到的计算机将能够安装此共享。

选项这是NFS中的主要部分,需要特别注意,因为此处提到的选项会影响性能以及客户端访问共享的方式。

有多个可用选项。
让我们浏览其中的一些,并了解它们的作用。

ro:此选项代表只读。
这意味着客户端仅具有从共享中读取数据的权限,而没有写许可。

rw:此选项代表“读取”和“写入”。
这允许客户端计算机对目录具有读取和写入权限

no_root_squash:需要非常仔细地理解此选项,因为它可能成为服务器上的安全瓶颈。
如果客户端计算机上的用户“ root”从服务器安装了特定共享,则默认情况下,由root用户发出的请求将以名为“ nobody”的用户(而不是root)的身份得到满足。
就安全性而言,这是一个加分点,因为客户端计算机上没有root用户可以损害服务器,因为请求不是以root用户身份而是没有人可以满足。

使用no_root_squash选项将禁用此功能,并且请求将以root身份而不是无人身份执行。
这意味着客户端根用户将与服务器根用户在共享上具有完全相同的可访问性。

除非出于某些明确的原因需要使用此选项,否则我绝不建议我们使用此选项。

异步:如我在VFS(虚拟文件系统)部分所述,从客户端到nfs服务器的每个请求都首先转换为RPC调用,然后提交到服务器上的VFS。
VFS将处理对基础文件系统的请求,以完成请求。

现在,如果我们使用async选项,则将在基础文件系统上处理请求以使其满足后,nfs服务器将回复客户端,说明请求已完成。
在回复客户端之前,NFS服务器不会等待在基础物理介质上完成写入操作。

虽然这会使操作更快一些,但是会导致数据损坏。
我们可以说nfs服务器在向客户端撒谎,即数据已写入磁盘(如果此时服务器被重新引导,将会发生什么情况。

sync:sync选项执行相反的操作。
在这种情况下,仅在将数据完全写入基础介质后,NFS服务器才会回复客户端。
这将导致轻微的性能滞后。

如何在Linux中共享NFS

安装完所需的软件包后,还介绍了用于共享的方法和选项。
现在,我们进行共享并将其安装在客户端计算机上。

[root@theitroad1 ~]# cat /etc/exports
/data 192.168.0.104(rw)
[root@theitroad1 ~]#

从上面的共享中可以清楚地看到,我们已经将/data共享给了一个名为192.168.0.104的NFS客户端,并且授予了读取和写入权限。

现在,让我们在NFS服务器上启动所需的服务,以使此共享正常工作。

[root@theitroad1 ~]# /etc/init.d/nfs start
Starting NFS services:                                     [  OK  ]
Starting NFS quotas:                                       [  OK  ]
Starting NFS daemon:                                       [  OK  ]
Starting NFS mountd:                                       [  OK  ]
[root@theitroad1 ~]# /etc/init.d/portmap start
Starting portmap:                                          [  OK  ]

不用担心,我们将处理那些与nfs一起启动的另外服务(NFS配额,NFS守护程序,NFS挂载)等。
建议将这些服务添加到启动服务中,因为客户端重启服务器后不会遇到任何问题。

让我们使用chkconfig命令将这些服务放入启动脚本。

[root@theitroad1 ~]# chkconfig nfs on
[root@theitroad1 ~]# chkconfig portmap on

现在,让我们借助mount命令将此共享安装在客户端(theitroad2 192.168.0.104)上。

[root@theitroad2 ~]# mount 192.168.0.105:/data /mnt
[root@theitroad2 ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1              38G  5.6G   31G  16% /
tmpfs                 252M     0  252M   0% /dev/shm
192.168.0.105:/data    38G  2.8G   34G   8% /mnt
[root@theitroad2 ~]#

注意:我们需要在服务器和客户端上都运行portmap服务,才能通过NFS挂载文件。
大多数发行版都默认启用了该功能。

因此,我们已经从/mnt上的服务器192.168.0.5安装了NFS导出。
客户端现在可以在共享上执行正常操作,就好像它在任何本地硬盘上一样。
在没有指定任何选项的情况下,在客户机上挂载目录时,默认情况下,红帽企业Linux使用NFS版本3.

让我们在服务器上执行启用NFS的不同过程。

rpc.mountd:这是服务器上等待来自客户端的安装请求的进程。
此过程将确认服务器上的导出。
在服务器上启动nfs服务也将启动此服务。

rpc.statd:此过程使nfs客户端随时了解nfs服务器的当前状态。
如果从init脚本启动nfslock服务,此过程也将开始。

rpc.quotad:此过程在本地系统上为远程用户实现与配额相关的相同详细信息。

直到版本3(默认)为止,NFS中的所有通信都是通过称为端口映射的服务进行的。
因此,要列出服务器上正在运行的NFS服务,我们需要查看通过RPC为哪个服务运行的端口。
这还将列出与NFS不相关的服务,因为许多其他服务都使用RPC。

[root@theitroad1 ~]# rpcinfo -p
   program vers proto   port
    100000    2   tcp    111  portmapper
    100000    2   udp    111  portmapper
    100024    1   udp    880  status
    100024    1   tcp    883  status
    100011    1   udp    620  rquotad
    100011    2   udp    620  rquotad
    100011    1   tcp    623  rquotad
    100011    2   tcp    623  rquotad
    100003    2   udp   2049  nfs
    100003    3   udp   2049  nfs
    100003    4   udp   2049  nfs
    100021    1   udp  60385  nlockmgr
    100021    3   udp  60385  nlockmgr
    100021    4   udp  60385  nlockmgr
    100003    2   tcp   2049  nfs
    100003    3   tcp   2049  nfs
    100003    4   tcp   2049  nfs
    100021    1   tcp  54601  nlockmgr
    100021    3   tcp  54601  nlockmgr
    100021    4   tcp  54601  nlockmgr
    100005    1   udp    649  mountd
    100005    1   tcp    652  mountd
    100005    2   udp    649  mountd
    100005    2   tcp    652  mountd
    100005    3   udp    649  mountd
    100005    3   tcp    652  mountd
[root@theitroad1 ~]#

上面显示的rpcinfo命令可用于列出通过RPC运行的服务和端口。
因此,所有安装远程共享的初始请求都到达服务器上的端口111(该端口是RPC的默认端口),该端口提供与不同NFS服务关联的端口号。

通过RPC运行的服务在每次启动时都会通知其端口图,该端口图将为该进程分配端口号和程序号。
需要连接到其中一个RPC服务的客户端的端口111上的端口映射,该实习生将提供所请求程序的端口号。

如前所述,除非我们在客户端安装时指定TCP,否则Linux机器默认情况下将UDP用于NFS。
因此,我们可以通过portmap看到服务器上运行的TCP和UDP端口。
NFS版本4单独实现了这一点,我们将在本文后面讨论。
如果由于某种原因,我们看不到在端口映射中注册的NFS端口和程序号,则重新启动nfs服务将在端口映射中重新注册该服务。

NFS客户端挂载选项

在客户端上安装共享时,NFS提供了多种选择。
讨论此问题的主要原因是,直到客户端在安装过程中使用显式参数指定了大多数选项后,大多数选项才会启用。

让我们看一下在NFS挂载期间可以应用的一些选项。

让我们回到之前在客户端计算机上挂载的共享,并通过添加fstab条目使其成为永久共享。

192.168.0.105:/data             /mnt                    nfs     defaults        0 0

上面显示的fstab条目将在引导时使用默认选项挂载远程nfs共享。
但是,有些高级选项可以应用于此安装。

NFS中有所谓的软安装和硬安装。
让我们了解它们,并在我们的nfs挂载中实现它们。

NFS中的软安装

假设我们在客户端计算机上进行了一次处理,例如,Apache Web服务器正在访问其中安装的共享和文件。
但是由于NFS服务器上的某些问题,Apache对NFS共享上的文件的请求无法完成。
在这种情况下,NFS客户端将以错误消息答复进程(在本例中为Apache)。

大多数进程将接受该错误。
但是,这完全取决于处理这些错误的流程的设计方式。
有时,它可能导致不良行为,甚至可能损坏文件。

可以通过以下方法完成软安装。

192.168.0.105:/data             /mnt        nfs     rw,soft       0 0

在NFS中硬安装

硬安装与软安装有点不同。
如果需要从nfs共享中获取文件的进程由于nfs服务器上的某些问题而无法访问该文件,则该进程将等待(有点像get挂起),直到nfs服务器变得正确并完成其请求为止。
NFS服务器正确响应后,该过程将从停止的位置恢复。

等待操作完成的过程不能中断。
是的,我们可以使用kill -9命令杀死该进程,也可以借助名为intr的选项来中断该进程。

可以通过添加以下fstab中所示的选项来完成硬安装。

192.168.0.105:/data             /mnt                    nfs     rw,hard,intr    0 0

这完全取决于需求和我们在已挂载共享上运行的过程的类型。
但是,与软安装相比,建议使用带intr选项的硬安装。

fstab中可以使用一些与性能相关的安装选项。
但是我将在NFS中称为性能调整的专门文章中讨论它们。

正如我在本教程开始时提到的那样,NFS有4个不同的版本。
默认情况下,RHEL/Centos使用nfs版本3.
我们可以在安装期间在不同nfs版本之间切换。
因此,它决定了安装时使用哪个NFS版本的客户端。
但是服务器当然必须支持它。

我们可以在名为vers和mount的参数的帮助下使用NFS版本2,如下所示。

[root@theitroad2 ~]# mount -o vers=2 192.168.0.105:/data /mnt

请注意,nfs版本1现在已过时,大多数新的nfs服务器计算机均不支持该版本。

如何在Redhat/CentOS Linux上挂载NFS版本4

NFS版本4与nfs版本3和其他先前版本的实现方式不同。
它在根文件系统上工作。
让我们举一个例子来理解这一点。

[root@theitroad1 ~]# cat /etc/exports
/data 192.168.0.104(rw,fsid=0,sync)
[root@theitroad1 ~]#

在上面显示的导出文件中,我为nfs版本4添加了一个添加选项。
使用该选项,fsid = 0,我们指定这是此服务器提供的导出的根文件系统。
这意味着客户端只需通过指定“ /”而不是/data来挂载默认共享。
让我们看看如何

要挂载nfs4共享,我们需要在mount命令中使用选项nfs4.

[root@theitroad2 ~]# mount -t nfs4 -o rw 192.168.0.105://mnt

如果我们注意到我在安装时使用了192.168.0.105:/而不是使用192.168.0.105:/data。
这仅仅是因为,我们在服务器导出中提到/data是此服务器上nfs共享的默认根文件系统。
任何带有fsid = 0参数的共享都将成为服务器的根共享。

客户还可以使用绝对路径将子目录安装在共享bu中。
例如。

[root@theitroad2 ~]# mount -t nfs4 -o rw 192.168.0.105:/test /test

在上面显示的示例中,我们通过将/data保留为根目录,在/data内安装了一个子目录(该共享是服务器在其导出文件中拥有的共享目录)。
这意味着我们已经直接挂载了/data/test。

NFS版本4与版本3相比具有很多优点。
其中之一是,它默认情况下可以通过TCP进行工作,并且可以在Internet上供主机使用,因为它可以在2049 TCP端口上运行而无需端口映射。

是的,我们不需要服务器上的端口映射服务即可运行nfs版本4.
它直接与服务器上的TCP端口2049联系。
NFS版本4中包含其他安全性和性能改进功能(我们将在另一篇有关NFS安全性的专门文章中进行讨论。

有关NFS版本3和版本4的注意事项

  • NFS的版本3开始支持大于2 GB的文件。
  • 是版本3,它启动了async的性能选项(我们在前面已经看到过)来提高性能。
  • NFS版本4是为了更好,更轻松地通过Internet访问而制作的
  • NFS版本4不需要运行portmap(这是一个易受攻击的服务)
  • 我们已经在fsid = 0的帮助下实现了虚拟根目录概念,该参数提高了安全性
  • NFS版本4默认情况下使用TCP,以提高Internet上的可靠性
  • 与默认的1024字节相比,NFS版本4能够使用32KB的页面大小,从而大大提高了性能。