NFS:Network File System网络文件共享服务,最大的功能就是让不同的机器、不同的操作系统、可以彼此分享个别的档案,也可以看成一个文件服务器。

由于NFS支持的功能相当多,而不同的功能都会使用不同的程序来启动,而启动一个功能就会启动一个端口来传输数据,因此NFS的功能所对应的端口口才没有固定住,而是随机开启小于1024的端口作为传输之用,但如此又造成客户端想要联机服务器时的困扰,因为客户端要知道服务器的端口才能联机。


RPC(Remote Procedure Call)协议辅助,指定每个NFS功能所对应的port number,并且回报给客户端,让客户端可以连接到正确的端口。

RPC是一种不同的网络程序设计方法,客户程序编写时只是调用了服务器程序提供的函数。

1.当客户程序调用远程的过程时,它实际调用了本机上的、由RPC程序包生成的函数,这个函数称为残桩,客户残桩将过程的参数封装成一个网络报文,将报文发送到服务器程序。

2.服务器主机上的一个服务器残桩负责接收这个网络报文,它从网络报文中提取参数,然后调用应用程序员编写的服务器过程。

3.当服务器函数返回时,它返回到服务器残桩,服务器残桩提取返回值,把返回值封装成一个网络报文,并发送给客户残桩。

4.客户残桩接收到网络报文后取出返回值,返回给客户程序。

网络程序设计是通过残桩和API的RPC库来实现的,但用户程序--客户程序与被客户程序调用的服务器过程--不会与API打交道。客户应用程序只是调用服务器的过程。

RPC有两个版本:1.建立在API基础上,与TCP、UDP打交道。2.TI-RPC独立于运输层。

image.pngimage.png

图1是RPC过程调用报文作为一个UDP数据报的格式,图2是RPC应答报文作为一个UDP数据报的格式

XID:事务标识符,由客户程序设置,由服务器程序返回。客户收到一个应答,它将服务器返回的XID与它发送的请求XID进行比较,不同则放弃。

call:调用变量,调用报文中设置为0,在应答报文中设置为1

RPC版本:当前版本为2

程序号、版本号、过程号:标识服务器上被调用的特定过程

证书:标识客户

验证:DES加密安全的RPC

过程参数:参数的格式依赖于远程过程的定义


XDR:外部数据表示,是一个标准。用来对RPC调用报文与应答报文中的值进行编码。


端口映射器

包含远程过程的RPC服务器程序使用的是临时端口,需要某种形式的“注册” 程序来跟踪哪一个RPC程序使用了哪一个临时端口,这个注册的过程称为端口映射器。

端口映射器有一个知名端口:UDP111和TCP111。端口映射器也是一个RPC服务器程序,它有一个程序号、一个版本号、一个TCP端口号、一个UDP端口号。服务器程序使用RPC调用向端口号映射器注册自身,客户程序使用RPC调用向端口映射器查询,端口映射器提供4个服务过程:

1.PMAPPROC_SET,一个RPC服务器启动时调用这个过程,注册一个程序号、一个版本号和带一个端口号的协议

2.PMAPPROC_UNSET,RPC服务器调用此过程来删除一个已经被注册的映射

3.PMAPPROC_GETPORT,一个RPC客户启动时调用此过程,根据一个给定的程序号、版本号、协议来获取注册的端口号。

4.PMAPPROC_DUMP,返回端口映射器数据库中所有的记录


一个RPC服务器启动,一个RPC客户启动时调用此过程,有以下步骤:

1.端口映射器先启动,创建一个TCP端点,主动打开TCP111端口,创建一个UDP端点,主动打开UDP111端口;

2.当RPC服务器程序启动时,它为它所支持的程序的每一个版本创建一个TCP端点和UDP端点,两个端点都绑定一个端口,服务器通过调用端口映射器的PAMAPPROC_SET过程,注册每一个程序、版本、协议和端口号。

3.当RPC客户程序启动时,它调用端口映射器的PAMAPPROC_GETPORT过程获得一个指定程序、版本和端口号。

4.客户发送一个RPC调用报文给第3步返回的端口号,如果使用UDP,客户只是发送一个包含RPC调用报文的UDP数据报到服务器相应的UDP端口,服务器发送一个包含RPC应答报文的UDP数据报到客户作为响应。


NFS协议:

NFS是一个使用sun RPC构造的客户服务器应用程序,NFS客户通过向一个NFS服务器发送RPC请求来访问其上的文件。

文件句柄:用来引用服务器上的文件或目录,服务器创建文件句柄,把它传给客户,然后客户访问文件,使用文件句柄。

文件句柄存储:文件系统标识符、i-node号、i-node生成码。

安装协议:挂载,客户必须在访问服务器上一个文件系统中的文件时,使用安装协议安装那个文件系统。在客户主机上完成此过程,最后的结果是客户获得服务器文件系统的一个文件句柄。

使用mount命令的安装协议,如下图:

image.png

步骤:

1.服务器上的端口映射器一般在服务器启动时被启动

2.安装守护程序mountd在端口映射器之后被启动,它创建一个TCP端点和UDP端点,并分配一个端口,在端口映射器中注册这些端口

3.在客户端执行mount命令,它向服务器上端口映射器发出一个RPC调用获取服务器上安装守护程序的端口号

4.端口映射器应答以安装程序的端口号

5. mount命令向安装程序发送一个RPC调用来安装服务器上的一个文件系统

6.安装守护程序应答以指定文件系统的文件句柄

7.客户机上的mount命令发出mount系统调用将第5步返回的文件句柄与客户机上的一个本地安装点联系起来。文件句柄被存储在NFS客户代码中,从现在开始,用户进程对于那个服务器文件系统的任何引用都将从使用这个文件句柄开始。


当NFS服务启动时,会随机启动数个port,并主动想RPC注册,因此RPC知道每个port对应的NFS的功能,然后RPC又是固定port11来监听客户端的需求并回报客户端正确的端口,这样NFS就正常的工作了。

1.当客户端向服务器RPC发出NFS存取功能询问后

2.服务器找到已经注册的NFS服务端口后,会回报给客户端

3.客户端了解正确的端口后,直接连接NFS服务器


NFS客户端:一般是web服务器,通过挂载的方式将NFS服务器上的某个共享服务器挂载到客户端,看起来就像是客户端下的一个目录。

NFS服务器用于共享存储。

先启动RPC服务,再启动NFS服务,向RPC进行注册,RPC就知道每个port对应的NFS的功能。而RPC固定port111来监听客户端的请求并回报客户端正确的端口。


NFS服务器所需软件

1.RPC主程序:rpcbind

2.NFS主程序:nfs-utils

[root@www1 ~]# cat /etc/redhat-release   #查看当前系统发行版
CentOS release 6.5 (Final)
[root@www1 ~]# uname  -a    #查看系统内核信息
Linux www1 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

[root@www1 ~]#  yum install nfs-utils rpcbind -y  #安装rpcbind nfs
[root@www1 ~]# rpm -qa | grep nfs
nfs4-acl-tools-0.3.3-8.el6.x86_64
nfs-utils-lib-1.1.5-13.el6.x86_64
nfs-utils-lib-devel-1.1.5-13.el6.x86_64
nfs-utils-1.2.3-75.el6.x86_64
[root@www1 ~]# rpm -qa | grep rpcbind
rpcbind-0.2.0-13.el6_9.1.x86_64
[root@www ~]#
[root@www11 ~]# /etc/init.d/rpcbind start            #启动rpc
正在启动 rpcbind:                                         [确定]
[root@www1 ~]# netstat -lantup | grep rpcbind                                        #查看rpc的主端口111
tcp        0      0 0.0.0.0:111                 0.0.0.0:*                   LISTEN      2599/rpcbind
tcp        0      0 :::111                      :::*                        LISTEN      2599/rpcbind
udp        0      0 0.0.0.0:111                 0.0.0.0:*                               2599/rpcbind
udp        0      0 0.0.0.0:654                 0.0.0.0:*                               2599/rpcbind
udp        0      0 :::111                      :::*                                    2599/rpcbind
udp        0      0 :::654                      :::*                                    2599/rpcbind
[root@www1 ~]# rpcinfo -p    #查看rpc启动的端口,都是主程序的端口,因为nfs还未向rpcbind进行注册
   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
[root@www1 ~]# /etc/init.d/nfs start            #启动nfs
启动 NFS 服务:                                            [确定]
启动 NFS mountd:                                          [确定]
启动 NFS 守护进程:                                        [确定]
正在启动 RPC idmapd:                                      [确定]
[root@www1 ~]# rpcinfo -p                        #再看rpcbind管理的端口
   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  37383  mountd
    100005    1   tcp  59846  mountd
    100005    2   udp  54635  mountd
    100005    2   tcp  48766  mountd
    100005    3   udp  58293  mountd
    100005    3   tcp  40313  mountd
    100003    2   tcp   2049  nfs
    100003    3   tcp   2049  nfs
    100003    4   tcp   2049  nfs
    100227    2   tcp   2049  nfs_acl
    100227    3   tcp   2049  nfs_acl
    100003    2   udp   2049  nfs
    100003    3   udp   2049  nfs
    100003    4   udp   2049  nfs
    100227    2   udp   2049  nfs_acl
    100227    3   udp   2049  nfs_acl
    100021    1   udp  34573  nlockmgr
    100021    3   udp  34573  nlockmgr
    100021    4   udp  34573  nlockmgr
    100021    1   tcp  54386  nlockmgr
    100021    3   tcp  54386  nlockmgr
    100021    4   tcp  54386  nlockmgr
[root@www1 ~]# 
[root@www1 ~]# ps aux | grep -E "nfs|rpcbind"        #查看启动的进程有哪些?
rpc       2599  0.0  0.0  18976   904 ?        Ss   16:40   0:00 rpcbind
root      2648  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd4]
root      2649  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd4_callbacks]
root      2650  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd]
root      2651  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd]
root      2652  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd]
root      2653  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd]
root      2654  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd]
root      2655  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd]
root      2656  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd]
root      2657  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd]

NFS软件结构

1.主要配置文件:/etc/exports,配置方法语法及参数

需要共享的目录   单个主机/主机名/IP地址

需要共享的目录   使用通配符指定机器系列

需要共享的目录   IP网络 192.168.1.1/24

/tmp    172.16.4.5(rw)小括号内是权限

2.NFS文件系统维护指令:/usr/sbin/exportfs

维护NFS分享资源的指令,可以用这个指令重新分享/etc/exports变更的目录资源

3.分享资源的登录档:/var/lib/nfs/*tab

 a. etab 记录NFS所分享出来的目录的完整权限设定值

 b.xtab 记录曾经连接到此NFS服务器的相关客户端数据,centos6已经没有了。。

[root@www1 ~]# cat /var/lib/nfs/etab
/nfs_share      192.168.146.133(rw,sync,wdelay,hide,nocrossmnt,secure,root_squash,no_all_squash,no_subtree_check,secure_locks,acl,anonuid=65534,anongid=65534)
/nfs_share      192.168.146.134(rw,sync,wdelay,hide,nocrossmnt,secure,root_squash,no_all_squash,no_subtree_check,secure_locks,acl,anonuid=65534,anongid=65534)

4.客户端查询服务器分享资源的指令:/usr/sbin/showmount

[root@www1 ~]# vim /etc/exports
#share
/nfs_share 192.168.146.133(rw,sync) 192.168.146.134(rw,sync)
[root@www1 ~]# /etc/init.d/nfs reload    #需要平滑重启已加载配置文件exports

#NFS服务器www1使用showmount
[root@www1 ~]# showmount -e        #在nfs服务器看可挂载的目录
Export list for www1:
/nfs_share 192.168.146.134,192.168.146.133

#NFS客户端web1使用showmount
[root@web1 ~]# showmount -e 192.168.146.132
Export list for 192.168.146.132:
/nfs_share 192.168.146.134,192.168.146.133

启动NFS

[root@www1 ~]/etc/init.d/nfs start

设置开机自启动

[root@www1 ~]# chkconfig --level 235 nfs on
[root@www1 ~]# chkconfig --level 235 rpcbind on

手动挂载NFS服务器分享的资源

1.确定客户端开启了rpcbind服务

2.扫描NFS服务器分享的的目录有哪些?并了解我们是否可以使用showmount -e nfs-ip命令

3.在客户端建立预计要挂载的挂载点或目录

4.利用mount将nfs服务器的直接挂载到相关目录

netstat -tulp | grep -E '(rpc|nfs)'
showmount -e 192.168.146.132
mount -t nfs 192.168.146.132:/nfs_share /data/nfs

5.自动挂载设置

    1.放在rc.local中

[root@www1 ~]# cat /etc/rc.local
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.

mount -t nfs 192.168.146.132:/nfs_share /data/nfs

    2.在/etc/fstab中设置,但是由于linux开机是先挂载/etc/fstab中设备,再开启网卡。所以会无法自动挂载,但我们可以启动netfs服务,也可以实现。

[root@web2 ~]# tail -1 /etc/fstab
192.168.146.132:/nfs_share /data/nfs            nfs     defaults        0 0

6.nfs服务器配置文件中权限介绍

rw(readwrite):可读可写

ro(readonly):只读

sync:请求或写入数据时,数据同步到nfs服务器的硬盘才返回。优点数据不丢失,安全,性能差

async:先写入数据缓冲区,硬盘有空档才会写入,从而提供效率。但要保持服务器不当机不断电

no_root_squash:登陆到NFS主机,使用共享目录的用户,如果是root,那么对于这个目录他就具有root的权限了

root_squash:登陆到NFS主机,使用共享目录的用户如果是root,那么这个用户就被贬为匿名使用者,他的uid,gid都会变成nobody

all_squash:不管访问共享目录的身份如何,都是用nfsnobody

anonuid:指定匿名用户的uid

anongid:指定匿名组的gid

#以上用于统一指定访问目录和使用目录的用户和用户组。

7.查看客户端的挂载参数(mount -t nfs的额外参数)

[root@web1 nfs]# cat /proc/mounts
192.168.146.132:/nfs_share/ /data/nfs nfs4 rw,relatime,vers=4,rsize=131072,wsize=131072,namlen=255,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=192.168.146.133,minorversion=0,local_lock=none,addr=192.168.146.132 0 0

    hard:客户端会一直尝试与NFS服务器连接,直到挂载成功。在后台不给出任何提示。

    soft: 会在前台尝试与NFS服务器的连接,当收到错误信息后终止mount尝试,并给出相关信息。

    rsize/wsize: 文件传输尺寸设定:V3没有限定传输尺寸,V2最多只能设定为8k,可以使用-rsize and -wsize 来进行设定。这两个参数的设定对于NFS的执行效能有较大的影响

    bg:在执行mount时如果无法顺利mount上时,系统会将mount的操作转移到后台并继续尝试mount,直到mount成功为止。(通常在设定/etc/fstab文件时都应该使用bg,以避免可      能的mount不上而影响启动速度) 

    fg:和bg正好相反,是默认的参数

    port:根据server端export出的端口设定,例如如果server使用5555端口输出NFS,那客户端就需要使用这个参数进行同样的设定 

    timeo=n:设置超时时间,当数据传输遇到问题时,会根据这个参数尝试进行重新传输。如果网络连接不是很稳定的话就要加大这个数值,并且推荐使用HARD MOUNT方式,同时最好也加上INTR参数,这样你就可以终止任何挂起的文件访问。 

    intr : 允许通知中断一个NFS调用。当服务器没有应答需要放弃的时候有用处。 

    udp:使用udp作为nfs的传输协议(NFS V2只支持UDP) 

    tcp:使用tcp作为nfs的传输协议    

    vers=n:设定要使用的NFS版本

    mountport:设定mount的端口

    namlen=n:设定远程服务器所允许的最长文件名。这个值的默认是255 

    acregmin=n:设定最小的在文件更新之前cache时间,默认是3 

    acregmax=n:设定最大的在文件更新之前cache时间,默认是60 

    acdirmin=n:设定最小的在目录更新之前cache时间,默认是30 

    acdirmax=n:设定最大的在目录更新之前cache时间,默认是60 

    actimeo=n:将acregmin、acregmax、acdirmin、acdirmax设定为同一个数值,默认是没有启用。

    retry=n:设定当网络传输出现故障的时候,尝试重新连接多少时间后不再尝试。默认的数值是10000 minutes 

    noac:关闭cache机制

8.当然也可以有mount命令的额外参数哦~

-o options:(挂载文件系统的选项)

      async:异步模式(提高性能,但数据安全有所降低,生产环境不建议使用)

      sync:同步模式(数据安全又保障)

      atime/noatime:每次访问数据时,会同步更新 访问文件的inode时间戳,会减低性能。高并发时建议使用noatime

      diratime/nodiratime:目录的访问时间戳

      auto/noauto:是否支持自动挂载

      exec/noexec:是否支持文件系统执行二进制文件

      dev/nodev:是否支持在此文件系统上使用设备文件

      suid/nosuid:是否支持在此文件系统上使用特殊权限

      remount:重新挂载

      ro:只读

      rw:可读写

      user/nouser:是否允许普通用户挂载此设备

      acl:启用此文件系统上的acl功能


注:每次修改完配置文件/etc/exports后要使用平滑重启nfs.或使用命令exportsfs -rv。