NFS(Network File System)即网络文件系统,是FreeBSD支持的文件系统中的一种,它允许网络中的计算机之间通过TCP/IP网络共享资源。在NFS的应用中,本地NFS的客户端应用可以透明地读写位于远端NFS服务器上的文件,就像访问本地文件一样。

 NFS客户端(一般为应用服务器,如web)可以通过挂载的方式将NFS服务器端共享的数据文件目录挂载到NFS客户端本地系统中。从NFS客户端的机器本地上来看,NFS服务器端共享的目录就好像是客户端自己的磁盘分区或者目录一样,而实际上是远端主机的目录。NFS文件系统已经经历了30多年的发展,它代表了一个非常稳定的、可移植的网络文件系统,它具备可扩展性、高性能等特性,并且企业级应用的质量标准。NFS网络速度的增加和延时的降低,NFS一直是通过网络提供文件系统服务的具有竞争力的选择,特别是中小型企业,应用比较广泛。

        不过NFS也有问题,就是大网站并发大的时候,它的性能不太好,中小网站还是可以胜任的,而且使用方便,数据不容易丢

NFS在企业场景中的应用:

        在企业集群架构的工作场景中,NFS网络文件系统一般被用来存储共享视频、图片、附件等静态资源文件(通常把网站用户上传的文件都放到NFS共享里,例如:论坛的图片、附件、头像,但是论坛的程序不会放到NFS共享中),NFS是当前互联网系统架构中最常用的数据存储服务之一,特别是中小型网站公司。大公司或是门户除了使用NFS外,还可能会使用MFS、GFS、FASTFS、TFS等分布式文件系统。


NFS的功能很多,而且不同额功能都会使用不同的程序来启动,每启动一个功能就会启用一些端口来 传输数据,而这些NFS的功能所对应的端口并不是固定的,而是随机启用一些未被使用的端口来作为传输数据用。端口不固定,就会造成NFS客户端和NFS服务端通信的障碍,这时候就需要用到RPC(Remote Procedure Call)服务喽。该服务可以将NFS功能所对应的端口号记录下来,并且在NFS客户端请求时将该端口和功能对应的信息传递给请求数据的NFS客户端,从而可以确保客户端可以连接到正确的NFS端口上去,达到实现数据传输交互的目的。

当访问程序通过NFS客户端向NFS服务端存取文件时,其请求数据流程如下:

1、首先用户访问网站程序,由程序在NFS客户端上发出NFS文件存取功能的询问请求,这时NFS客户端RPC服务(rpcbind)就会通过网络向NFS服务器端的RPCrpcbind)的111端口发出NFS文件存取功能的询问请求。

2NFS服务器端的RPC服务(rpcbind)找到对应的已经注册的NFS daemon端口后,通知NFS客户端的RPC服务,此时,NFS客户端就可以获取到正确的端口,然后就直接与NFS daemon通信进行数据存取。

3NFS客户端吧数据存取成功后,返回给前端访问程序,告知给用户存取结果,就这样,作为网站用户,我们就完成了一次存取操作。

  由于NFS的各项功能都需要向RPC服务注册,所以RPC服务才能获取到NFS服务的各项功能对应的端口号、PIDNFS在主机所监听的ip地址等,从而客户端才能够通过向RPC服务寻味找到正确的端口。就是说,NFS需要有RPC服务的协助才能成功对外提供服务。启动NFS之前必须要要先启动RPC,客户端和服务端都需要安装rpcnfs,但是客户端不需要启动NFS服务,只需要启动rpc就可以了。(需要强调一下的是:NFSRPC服务在Centos5.x系列叫做portmap,在Centos6.x系列叫做rpcbind

安装NFS:

服务端:192.168.4.1 Centos 6.6

客户端:192.168.4.2 Centos 6.6

[root@nfs_server ~]# lsb_release -a
LSB Version: :base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-noarch
Distributor ID: CentOS
Description: CentOS release 6.6 (Final)
Release: 6.6
Codename: Final
[
root@nfs_server ~]# uname -a
Linux nfs_server 2.6.32-504.el6.x86_64 #1 SMP Wed Oct 15 04:27:16 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

服务端部署NFS需要以下软件包:

    nfs-utile:这是NFS服务主程序,包括rpc.nfsd,rpm.mountd两个daemons和相关文档说明以及执行的命令等文件

    rpcbind

(需要注意的是服务端和客户端都必须启动rpcbind,客服端不需要启动NFS服务,但是也得安装,不然某些命令无法使用的)

   NF服务的配置文件:/etc/exports

[root@nfs_server ~]# rpm -qa  | grep nfs
nfs-utils-1.2.3-54.el6.x86_64
nfs-utils-lib-1.1.5-9.el6.x86_64
[
root@nfs_server ~]# rpm -qa  | grep rpcbind
rpcbind-0.2.0-11.el6.x86_64

我这里已经安装好了。没有的话,请自行yum进行安装:

 yum -y groupinstall "NFS file server"

或是这样:

 yum -y install nfs-utils rpcbind

ok,安装就搞定了。

客户端安装:

[root@nfs_client ~]# yum -y install rpcbind

[root@nfs_client ~]# rpm -qa rpcbind
rpcbind-0.2.0-11.el6.x86_64

服务端:启动FNS服务

root@nfs_server ~]# /etc/init.d/nfs start
Starting NFS services:                                     [  OK  ]
Starting NFS quotas: Cannot register service: RPC: Unable to receive; errno = Connection refused
rpc.rquotad: unable to register (RQUOTAPROG, RQUOTAVERS, udp).
                                                           [FAILED]
Starting NFS mountd:                                       [FAILED]
Starting NFS daemon: 




^C^C^C^C^C^C^C^C^C^C^C^C^C

启动报错了,为什么呢?应为我们没有启动rpc服务,nfs没办法向rpc进行注册端口,所以想启动nfs就需要先启动rpc噢。

卡住了:直接killall掉:

[root@nfs_server ~]# killall nfs

root@nfs_server ~]# /etc/init.d/rpcbind start
Starting rpcbind:                                          [  OK  ]

[root@nfs_server ~]# netstat -antpu | grep rpcbind
tcp        0      0 0.0.0.0:111                 0.0.0.0:*                   LISTEN      4766/rpcbind        
tcp        0      0 :::111                      :::*                        LISTEN      4766/rpcbind        
udp        0      0 0.0.0.0:701                 0.0.0.0:*                               4766/rpcbind        
udp        0      0 0.0.0.0:111                 0.0.0.0:*                               4766/rpcbind        
udp        0      0 :::701                      :::*                                    4766/rpcbind        
udp        0      0 :::111                      :::*                                    4766/rpcbind  

[root@nfs_server ~]# rpcinfo -p 192.168.4.1
   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

rpc还没有收到来注册的请求,然后我们启动NFS:

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

ok,启动了rpc后再启动NFS一切ok。

再来看看rpc有没有收到注册的信息:

[root@nfs_server ~]# rpcinfo -p 192.168.4.1
   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
    100011    1   udp    875  rquotad
    100011    2   udp    875  rquotad
    100011    1   tcp    875  rquotad
    100011    2   tcp    875  rquotad
    100005    1   udp  33089  mountd
    100005    1   tcp  38530  mountd
    100005    2   udp  23191  mountd
    100005    2   tcp  35577  mountd
    100005    3   udp  15745  mountd
    100005    3   tcp  16333  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  25659  nlockmgr
    100021    3   udp  25659  nlockmgr
    100021    4   udp  25659  nlockmgr
    100021    1   tcp  63170  nlockmgr
    100021    3   tcp  63170  nlockmgr
    100021    4   tcp  63170  nlockmgr

有了,除了自己的111外,其他的都是NFS向其注册的。

然后将rpcbind和nfs加到开机自启动服务:

[root@nfs_server ~]# chkconfig nfs on
[
root@nfs_server ~]# chkconfig rpcbind on
[
root@nfs_server ~]# chkconfig --list nfs
nfs             0:off 1:off 2:on 3:on 4:on 5:on  6:off
[
root@nfs_server ~]# chkconfig --list rpcbind
rpcbind         0:off 1:off 2:on 3:on 4:on 5:on 6:off

开户端启动rpcbind:

[root@nfs_client ~]# /etc/init.d/rpcbind start
Starting rpcbind:                                          [  OK  ]
[
root@nfs_client ~]# netstat -antpu | grep rpcbind
tcp        0      0 0.0.0.0:111                 0.0.0.0:*                   LISTEN      3794/rpcbind        
tcp        0      0 :::111                      :::*                        LISTEN      3794/rpcbind        
udp        0      0 0.0.0.0:1001                0.0.0.0:*                               3794/rpcbind        
udp        0      0 0.0.0.0:111                 0.0.0.0:*                               3794/rpcbind        
udp        0      0 :::1001                     :::*                                    3794/rpcbind        
udp        0      0 :::111                      :::*                                    3794/rpcbin

ok,客户端rpcbind启动成功。

客户端将rpcbind加入到开机自启动中:

[root@nfs_client ~]# chkconfig rpcbind on
[
root@nfs_client ~]# chkconfig --list rpcbind
rpcbind         0:off 1:off 2:on 3:on 4:on 5:on 6:off

客户端和服务端软件都安装好了,接下来就需要在客户端配置文件中定义需要共享的文件目录了,我们来把/data目录进行共享做测试:

服务端:

root@nfs_server ~]# mkdir /data
[
root@nfs_server ~]# cd /data/
[
root@nfs_server data]# cat >nfs_shared.txt <<EOF
> this is a share text of nfs_server!!!
> EOF
[
root@nfs_server data]# cat nfs_shared.txt 
this is a share text of nfs_server!!!

然后再配置文件中定义共享目录以及其属性:

[root@nfs_server ~]# cat /etc/exports 
###shared data for client at 2015/6/27
/data   192.168.4.0/24(rw,sync)

加好注释,编辑完记得要检查一下,养成这种习惯是好的噢。

其中小括号里的是可以定义权限和数据同步时的方式,多个属性用逗号隔开进行定义:r(读),w(写),ro(只读)sync(数据同步到nfs的磁盘)、async(数据同步到nfs的内存中)

修改完配置文件之后我们需要重新加载一下服务,不要用restart而是要用reload,reload是平滑启动服务的,服务会重新读取配置文件,但是不会断:

[root@nfs_server ~]# /etc/init.d/nfs reload

(脚本中查询这个reload字段:/usr/sbin/exportfs -r)

重新加载,没有报什么信息。

然后再服务端自己检查一下定义的共享目录是否成功:

[root@nfs_server ~]# showmount -e 192.168.4.1
Export list for 192.168.4.1:
/data 192.168.4.0/24

我们这里是成功的。

然后客户端检查一下:

[root@nfs_client ~]# showmount -e 192.168.4.1
-bash: showmount: command not found

悲剧,我们客户端安装了rpcbind,但是没有安装nfs,所以没有nfs对应的一些命令,客户端还需要安装nfs-utils,但是不需要启动:

[root@nfs_client ~]# yum -y install nfs-utils

、、、、、

[root@nfs_client ~]# showmount -e 192.168.4.1
Export list for 192.168.4.1:
/data 192.168.4.0/24

ok,客户端检查服务端共享目录也ok。

如果客户端检查没有结果的话,可以检查一下网络连接状况,接着看一下远端rpc的111端口是否启用。

然后我们在客户端进行挂载:

在客户端的/mnt目录下新建一个nfs目录作为nfs的挂载点:

[root@nfs_client ~]# mkdir /mnt/nfs
[
root@nfs_client ~]# mount -t nfs 192.168.4.1:/data /mnt/nfs
[
root@nfs_client ~]# df -hT
Filesystem        Type   Size  Used Avail Use% Mounted on
/dev/sda3         ext4   9.5G  1.6G  7.5G  17% /
tmpfs             tmpfs  112M     0  112M   0% /dev/shm
/dev/sda1         ext4   283M   28M  241M  11% /boot
192.168.4.1:/data nfs     16G  2.3G   13G  16% /mnt/nfs
[
root@nfs_client ~]# 

ok,挂载好了。

[root@nfs_client ~]# cd /mnt/nfs/
[
root@nfs_client nfs]# ls
nfs_shared.txt
[
root@nfs_client nfs]# cat nfs_shared.txt 
this is a share text of nfs_server!!!

服务端的文件在客户端也有了。

我们再到服务端建立几个文件看看客户端会不会有:

服务端:

[root@nfs_server data]# touch aa bb cc
[
root@nfs_server data]# ll
total 4
-rw-r--r-- 1 root root  0 Jun 27 21:26 aa
-rw-r--r-- 1 root root  0 Jun 27 21:26 bb
-rw-r--r-- 1 root root  0 Jun 27 21:26 cc
-rw-r--r-- 1 root root 38 Jun 27 20:46 nfs_shared.txt
[
root@nfs_server data]# 

客户端:

[root@nfs_client nfs]# ll
total 4
-rw-r--r--. 1 root root  0 Jun 27 21:26 aa
-rw-r--r--. 1 root root  0 Jun 27 21:26 bb
-rw-r--r--. 1 root root  0 Jun 27 21:26 cc
-rw-r--r--. 1 root root 38 Jun 27 20:46 nfs_shared.txt

看看是否可以写东西到nfs的共享目录里:

[root@nfs_client nfs]# rm -f aa cc
rm: cannot remove `aa': Permission denied
rm: cannot remove `cc': Permission denied
[
root@nfs_client nfs]# touch ll
touch: cannot touch `ll': Permission denied

发现不行啊,为什么呢?我们来看一下NFS共享目录的权限吧:

[root@nfs_server data]# ll -d
drwxr-xr-x 2 root root 4096 Jun 27 21:26 .

原来是nfs服务端的共享目录的系统权限没有开放写的权限,我们给写的权限:

[root@nfs_server /]# chmod o+w /data/
[
root@nfs_server /]# ll -d /data/
drwxr-xrwx 2 root root 4096 Jun 27 21:26 /data/

这下客户端用户就可以修改、删除、常见文件了在nfs的共享目录中:

[root@nfs_client nfs]# touch xx
[
root@nfs_client nfs]# ls
aa  bb  cc  nfs_shared.txt  xx
[
root@nfs_client nfs]# rm cc
rm: remove regular empty file `cc'? y
[
root@nfs_client nfs]# ls
aa  bb  nfs_shared.txt  xx

去服务端看一下:

[root@nfs_server data]# pwd
/data
[
root@nfs_client nfs]# ll
total 4
-rw-r--r--. 1 root      root       0 Jun 27 21:26 aa
-rw-r--r--. 1 root      root       0 Jun 27 21:26 bb
-rw-r--r--. 1 root      root      38 Jun 27 20:46 nfs_shared.txt
-rw-r--r--. 1 nfsnobody nfsnobody  0 Jun 27 21:32 xx

这下客户端就可以在NFS的共享目录中进行:创建、修改、删除等操作了。

但是客户端创建的文件的属主和属组却是nfsnobody,这个用户是哪里来的呢?

服务端看一下:

[root@nfs_server ~]# cat /var/lib/nfs/etab 
/data 192.168.4.0/24(rw,sync,wdelay,hide,nocrossmnt,secure,root_squash,no_all_squash,no_subtree_check,secure_locks,acl,anonuid=65534,anongid=65534)

[root@nfs_server ~]# grep '65534' /etc/passwd
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
[
root@nfs_server ~]# 

懂了吧,这个nfsnobody系统默认就有定义的。

那么我们是不是可以把nfs的共享目录的属主和属组也改成nfsnobody呢,并且权限为755:

[root@nfs_server ~]# chmod  755 /data
[
root@nfs_server ~]# chown -R nfsnobody.nfsnobody /data
[
root@nfs_server ~]# ll -d /data
drwxr-xr-x 2 nfsnobody nfsnobody 4096 Jun 27 21:33 /data

我们来验证一下更改属主后的结果:

[root@nfs_client nfs]# ls
aa  bb  nfs_shared.txt  xx
[
root@nfs_client nfs]# ll
total 4
-rw-r--r--. 1 nfsnobody nfsnobody  0 Jun 27 21:26 aa
-rw-r--r--. 1 nfsnobody nfsnobody  0 Jun 27 21:26 bb
-rw-r--r--. 1 nfsnobody nfsnobody 38 Jun 27 20:46 nfs_shared.txt
-rw-r--r--. 1 nfsnobody nfsnobody  0 Jun 27 21:32 xx
[
root@nfs_client nfs]# rm -f aa bb xx
[
root@nfs_client nfs]# touch nn mm pp
[
root@nfs_client nfs]# ll
total 4
-rw-r--r--. 1 nfsnobody nfsnobody  0 Jun 27 21:43 mm
-rw-r--r--. 1 nfsnobody nfsnobody 38 Jun 27 20:46 nfs_shared.txt
-rw-r--r--. 1 nfsnobody nfsnobody  0 Jun 27 21:43 nn
-rw-r--r--. 1 nfsnobody nfsnobody  0 Jun 27 21:43 pp

[root@nfs_client nfs]# mkdir client
[
root@nfs_client nfs]# cd client/
[
root@nfs_client client]# vim cc.txt
[
root@nfs_client client]# ls
cc.txt
[
root@nfs_client client]# cd ..
[
root@nfs_client nfs]# ll
total 8
drwxr-xr-x. 2 nfsnobody nfsnobody 4096 Jun 27 21:44 client
-rw-r--r--. 1 nfsnobody nfsnobody    0 Jun 27 21:43 mm
-rw-r--r--. 1 nfsnobody nfsnobody   38 Jun 27 20:46 nfs_shared.txt
-rw-r--r--. 1 nfsnobody nfsnobody    0 Jun 27 21:43 nn
-rw-r--r--. 1 nfsnobody nfsnobody    0 Jun 27 21:43 pp

再去客户端看看:

[root@nfs_server data]# ll 
total 8
drwxr-xr-x 2 nfsnobody nfsnobody 4096 Jun 27 21:44 client
-rw-r--r-- 1 nfsnobody nfsnobody    0 Jun 27 21:43 mm
-rw-r--r-- 1 nfsnobody nfsnobody   38 Jun 27 20:46 nfs_shared.txt
-rw-r--r-- 1 nfsnobody nfsnobody    0 Jun 27 21:43 nn
-rw-r--r-- 1 nfsnobody nfsnobody    0 Jun 27 21:43 pp
[
root@nfs_server data]# cat client/cc.txt 
sdfasdfasdfad
[
root@nfs_server data]# 

ok,一切搞定。

这样我们只是手动挂载了nfs的共享目录,如果断开了当前的shell,或是重启就没有了,我们有两个方式可以解决这个问题:

第一个方法:就是把命令 mount -t nfs 192.168.4.1:/data /mnt/nfs写到客户端/etc/rc.local中,这样只要开机就会自动挂载

第二个方法:就是写到/etc/fstab中进行开机自动挂载 192.168.4.1:/data       /mnt/nfs                ntfs    defaults        0 0

我们来采用第二个:

    先卸载掉原来的挂载:

 [root@nfs_client ~]# umount /mnt/nfs/

[root@nfs_client ~]# df -hT


Filesystem     Type   Size  Used Avail Use% Mounted on


/dev/sda3      ext4   9.5G  1.6G  7.5G  17% /


tmpfs          tmpfs  112M     0  112M   0% /dev/shm


/dev/sda1      ext4   283M   28M  241M  11% /boot

然后编辑/etc/fstab文件:

192.168.4.1:/data       /mnt/nfs                nfs     defaults        0 0

然后保存,退出。

检查一下:

[root@nfs_client ~]# cat /etc/fstab 

#
# /etc/fstab
# Created by anaconda on Sat Jun  6 08:15:46 2015
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
UUID=e7b96259-0783-4193-9d39-04c8cb1ad71d /                       ext4    defaults        1 1
UUID=e4a10a1b-d71f-4f59-bd19-ba45e9640a38 /boot                   ext4    defaults        1 2
UUID=3a3dba78-3f30-44f5-bae6-435749d7afc6 swap                    swap    defaults        0 0
tmpfs                   /dev/shm                tmpfs   defaults        0 0
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
sysfs                   /sys                    sysfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0
192.168.4.1:/data /mnt/nfs nfs defaults 0 0

[root@nfs_client ~]# mount -a

执行mount -a是让新添加的挂载项生效,看一下是否成功:
[
root@nfs_client ~]# df -hT
Filesystem        Type   Size  Used Avail Use% Mounted on
/dev/sda3         ext4   9.5G  1.6G  7.5G  17% /
tmpfs             tmpfs  112M     0  112M   0% /dev/shm
/dev/sda1         ext4   283M   28M  241M  11% /boot
192.168.4.1:/data nfs     16G  2.3G   13G  16% /mnt/nfs

ok,成功通过fstab文件进行nfs挂载。