NFS服务器的挂载结构图:
如上图示:
当我们在NFS服务器设置好一个共享目录/home/public后,其他的有权访问NFS服务器的NFS客户端就可以将这个目录挂载到自己文件系统的某个挂载点,这个挂载点可以自己定义,如上图客户端A与客户端B挂载的目录就不相同。并且挂载好后我们在本地能够看到服务端/home/public的所有数据。如果服务器端配置的客户端只读,那么客户端就只能够只读。如果配置读写,客户端就能够进行读写。挂载后,NFS客户端查看磁盘信息命令:#df –h。
既然NFS是通过网络来进行服务器端和客户端之间的数据传输,那么两者之间要传输数据就要有想对应的网络端口,NFS服务器到底使用哪个端口来进行数据传输呢?基本上NFS这个服务器的端口开在2049,但由于文件系统非常复杂。因此NFS还有其他的程序去启动额外的端口,这些额外的用来传输数据的端口是随机选择的,是小于1024的端口;既然是随机的那么客户端又是如何知道NFS服务器端到底使用的是哪个端口呢?这时就需要通过远程过程调用(Remote Procedure Call,RPC)协议来实现了.RPC服务(portmap 或rpcbind服务)
RPC(Remote Procedure Call)即远程过程调用。RPC 最主要的功能就是在指定每个 NFS 功能所对应的 port number ,并且回报给客户端,让客户端可以连结到正确的port上去
功能:主要是把RPC程序号转化为Internet的端口号。
特点:只在第一次建立连接时候帮助网络应用程序找到正确的port,当当双方正确连接时,端 口就和应用绑定,portmap就无用。相当于媒婆。
RPC:Remote Procedure Call,远程过程调用,如NFS
如:window—服务–
如打印机,是由你计算机上对应的程序去调用打印机上相应的程序来进行工作的。
1. 首先服务器端启动RPC服务,并开启111端口
2. 服务器端启动NFS服务,并向RPC注册端口信息
3. 客户端启动RPC(portmap服务),向服务端的RPC(portmap)服务请求服务端的NFS端口
4. 服务端的RPC(portmap)服务反馈NFS端口信息给客户端。
5. 客户端通过获取的NFS端口来建立和服务端的NFS连接并进行数据的传输。
a.执行顺序:1(注册端口)–à2(达成协议)-à3(直接建立联系)–à4(达成协议)–à5(建立连接)
a. 节省本地存储空间将常用的数据存放在一台服务器可以通过网络访问
b. 简单容易上手
c. 方便部署非常快速,维护十分简单
a. 局限性容易发生单点故障,及server机宕机了所有客户端都不能访问
b. 在高并发下NFS效率/性能有限
c. 客户端没用用户认证机制,且数据是通过明文传送,安全性一般(一般建议在局域网内使用)
d. NFS的数据是明文的,对数据完整性不做验证
e. 多台机器挂载NFS服务器时,连接管理维护麻烦
1)进程
rpc.nfsd NFS守护进程
rpc.mountd 管理文件系统和权限
uid,gid
[root@localhost 桌面]# rpcinfo -p localhost
rpcinfo: can’t contact portmapper: RPC: Remote system error - Connection refused
[root@localhost 桌面]# lsof -i:111
注:rpcbind安装成功后默认已经开启,并且为开机自动启动。如果没有启动的话,我们来重新启动rcpbind服务
[root@localhost ~]# systemctl restart nfs
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
100024 1 udp 48218 status
100024 1 tcp 34910 status
100005 1 udp 20048 mountd
100005 1 tcp 20048 mountd
100005 2 udp 20048 mountd
100005 2 tcp 20048 mountd
100005 3 udp 20048 mountd
100005 3 tcp 20048 mountd
100003 3 tcp 2049 nfs
100003 4 tcp 2049 nfs
100227 3 tcp 2049 nfs_acl
100003 3 udp 2049 nfs
100003 4 udp 2049 nfs
100227 3 udp 2049 nfs_acl
100021 1 udp 37619 nlockmgr
100021 3 udp 37619 nlockmgr
100021 4 udp 37619 nlockmgr
100021 1 tcp 34708 nlockmgr
100021 3 tcp 34708 nlockmgr
100021 4 tcp 34708 nlockmgr
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME (FD文件描述符Type 列提供了关于文件格式)
rpcbind 4477 rpc 6u IPv4 42123 0t0 UDP *:sunrpc
rpcbind 4477 rpc 8u IPv4 42125 0t0 TCP *:sunrpc (LISTEN)
rpcbind 4477 rpc 9u IPv6 42126 0t0 UDP *:sunrpc
rpcbind 4477 rpc 11u IPv6 42128 0t0 TCP *:sunrpc (LISTEN)
[root@localhost 桌面]# netstat -tlunp |grep rpcbind()
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 4477rpcbind
tcp6 0 0 :::111 :::* LISTEN 4477rpcbind
udp 0 0 0.0.0.0:834 0.0.0.0:* 4477rpcbind
udp 0 0 0.0.0.0:111 0.0.0.0:* 4477rpcbind
udp6 0 0 :::834 :::* 4477rpcbind
udp6 0 0 :::111 :::* 4477rpcbind
[root@localhost 桌面]# netstat -tulnp |grep -E '(rpc|nfs)'
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 4862/rpcbind
tcp 0 0 0.0.0.0:34910 0.0.0.0:* LISTEN 4476/rpc.statd
tcp6 0 0 :::111 :::* LISTEN 4862/rpcbind
tcp6 0 0 :::51920 :::* LISTEN 4476/rpc.statd
udp 0 0 0.0.0.0:797 0.0.0.0:* 4862/rpcbind
udp 0 0 127.0.0.1:836 0.0.0.0:* 4476/rpc.statd
udp 0 0 0.0.0.0:48218 0.0.0.0:* 4476/rpc.statd
udp 0 0 0.0.0.0:111 0.0.0.0:* 4862/rpcbind
udp6 0 0 :::44735 :::* 4476/rpc.statd
udp6 0 0 :::797 :::* 4862/rpcbind
udp6 0 0 :::111 :::* 4862/rpcbind
[root@localhost 桌面]# ps -ef | grep -E 'rpc|nfs'
root 723 2 0 15:29 ? 00:00:00 [rpciod]
rpcuser 4476 1 0 15:47 ? 00:00:00 /usr/sbin/rpc.statd --no-notify
rpc 4862 1 0 15:58 ? 00:00:00 /sbin/rpcbind -w
root 5030 1 0 16:07 ? 00:00:00 /usr/sbin/rpc.idmapd
root 5031 1 0 16:07 ? 00:00:00 /usr/sbin/rpc.mountd
root 5037 2 0 16:07 ? 00:00:00 [nfsd4]
root 5038 2 0 16:07 ? 00:00:00 [nfsd4_callbacks]
root 5042 2 0 16:07 ? 00:00:00 [nfsd]
root 5043 2 0 16:07 ? 00:00:00 [nfsd]
root 5044 2 0 16:07 ? 00:00:00 [nfsd]
root 5045 2 0 16:07 ? 00:00:00 [nfsd]
root 5046 2 0 16:07 ? 00:00:00 [nfsd]
root 5047 2 0 16:07 ? 00:00:00 [nfsd]
root 5048 2 0 16:07 ? 00:00:00 [nfsd]
root 5049 2 0 16:07 ? 00:00:00 [nfsd]
root 5201 3975 0 16:11 pts/0 00:00:00 grep --color=auto -E rpc|nfs
进程
nfsd最主要的NFS服务提供程序,这个daemon主要的功能就是管理客户端是否能够使用服务器文件系统挂载信息,其中还包含判断这个登录用户的ID。
rpc.mountd
这个daemon主要功能则是管理NFS的文件系统。当client端顺利通过rpc.nfsd登入主机后,在它可以使用NFS服务器提供规定文件之前,还会经过文件使用权限的认证程序。它会去读取NFS的配置 文件/etc/exports来对比客户端的权限,当通过这一关之后,client端也就取得使用NFS文件的权限。
rpc.statd(非必要)
这个daemon可以用来检查文件的一致性,若发生因为客户端同时使用同一个文件造成文件损坏时,rpc.statd可以用来检测并尝试恢复该文件
常用目录和文件
/etc/exports
/usr/sbin/exportfs
/usr/sbin/showmount
/var/lib/nfs/*tab
etab 记录NFS分享出来的目录的完整权限设定值
xtab 记录曾经链接到此NFS主机的相关客户端数据
配置文件
/etc/exports
格式
输出目录 客户端 选项 [访问权限,用户映射,其他]
输出目录: 需要共享的目录路径
客户端: 服务的用户对象
选项: 共享的权限,紧跟客户端列
cat /etc/exports
/test *(ro)
Ro
rw
#共享/test目录,*所有用户(ro)权限为只读权限
参数命令 | 参数用途 |
---|---|
rw | 表示可读写 |
ro Read-only | 表示只能读权限 |
Sync | 请求或者写入数据时,数据同步写入到NFS server的硬盘中后才会返回 |
no_root_squas | 访问nfs server共享目录的用户如果是root的话,它对该目录具有root权限。这个配置原本为无盘用户准备的。用户应避免使用! |
root_squash | 对于访问NFS server共享目录的用户,如果是root的话会被压缩成为nobody用户身份。 |
all_squash | 不管访问nfs server共享目录的用户身份如何包括root,它的权限都将被压缩成为匿名用户,同时他们的udi和gid都会变成nobody或nfsnobody账户的uid,gid。在多个nfs客户端同时读写nfs server数据时,这个参数很有用可以确保大家写入的数据的权限是一样的。但不同系统有可能匿名用户的uid,gid不同。因为此处我们需要服务端和客户端之间的用户是一样的。比如说:服务端指定匿名用户的UID为2000,那么客户端也一定要存在2000这个账号才可以 |
anonuid | anonuid就是匿名的uid和gid。说明客户端以什么权限来访问服务端,在默认情况下是nfsnobody。Uid65534. |
anongid | 同anongid,就是把uid换成gid而已 |
其他选项:
*******async | 锁涉及到文件系统i/O的操作都是异步处理,即不会同步写到磁盘,此参数会提高性能,但是会降低数据安全一般生产环境,不推荐使用,除非性能要求高,数据可靠性不高的场合 |
atime | 在每一次数据访问是,同步更新每次的访问的inode的时间,默认是atime,在高并发的情况下,建议加上noatime来取消默认这个选项,以达到IO,优化目的3,auto 能够被自动挂载 |
******defaults | 这是缺省值,rw,suid,dev,exec,auto,nouser,async |
exec | 运行可以执行二进制文件,取消这个参数会提升系统安全性 |
nodiratime | 不更新文件爱你系统上的directory inode访问时间,高并发时候建议使用此选型 |
noauto | 不自动挂载 |
noexec | 即使设置了noexec shell php 程序还是可以执行 |
nosuid | 禁止已给普通用户挂载文件系统, |
secure | :限制客户端只能从小于1024的tcp/ip端口连接nfs服务器(默认设置); |
insecure | :允许客户端从大于1024的tcp/ip端口连接服务器; |
sync | :将数据同步写入内存缓冲区与磁盘中,效率低,但可以保证数据的一致性; |
async | :将数据先保存在内存缓冲区中,必要时才写入磁盘; |
wdelay | :检查是否有相关的写操作,如果有则将这些写操作一起执行,这样可以提高效率(默认设置); |
no_wdelay | :若有写操作则立即执行,应与sync配合使用; |
subtree | :若输出目录是一个子目录,则nfs服务器将检查其父目录的权限(默认设置); |
no_subtree | :即使输出目录是一个子目录,nfs服务器也不检查其父目录的权限,这样可以提高效率; |
服务端
配置#vim /etc/exports
/data *(ro) :wq
#mkdir /data
配置完成后重启服务
#systemctl restart nfs
用以下命令来查看共享的nfs
#showmount -e 192.168.221.250
Export list for 192.168.140.250:
/data *
关闭防火墙
#systemctl stop firewalld
客户端
#mount (服务端地址)192.168.140.250:/data /mnt
服务端
[root@r ~]# exportfs -r 重新读一遍
#ehco haha >> /data/haha
客户端
[root@hehe mnt]# ll /mnt
总用量 4
-rw-r–r--. 1 root root 5 2月 11 10:28 haha
注意:在客户端如果要删除haha文件需要在服务端的主配置文件更改为
data *(rw)
将ll -d /data 权限更改为如下
[root@r ~]# ll -d /data
drwxr-xrwx. 2 root root 17 2月 11 10:28 /data
然后在客户端删除/mnt/haha
在客户端写入文件
[root@hehe mnt]# echo hehe >> /mnt/hehe.txt
[root@hehe mnt]# ll /mnt
总用量 4
-rw-r–r--. 1 nfsnobody nfsnobody 5 2月 11 10:55 hehe.txt root用户直接映射为匿名用户
如果是在客户端用普通用户创建文件在/mnt 在服务端查看/data的权限是客户端普通用户的uid,gid 如果在服务端有与客户端相对应的uid gid就显示用户名。
/data *(rw,all_squash)
exportfs -r
例子:
某公司需要在网络上共享一个文件夹,所有人都只有只读权限,且只有192.168.1.0/24子网的用户可以访问,试通过NFS共享该文件夹。NFS服务器的IP地址是192.168.1.1。
具体操作步骤如下:
/share 192.168.1.0/24(ro,root_squash)
“/share” 表示要共享的目录,192.168.1.0/24表示允许访问的主机(这里是一个子网的主机),括号内的ro表示客户机上的用户对该共享目录只有只读权 限,root_squash表示当客户机上的root用户访问该共享目录时,映射该用户为匿名用户,即当客户机上的root用户访问该共享目录时相当于服 务器上的anonymous(nobody)用户。
[root@bearzhang root]#mount 192.168.1.1:/share /mnt
上面命令行的意思是:将192.168.1.1上的/share目录作为一个分区挂接到本机的/mnt目录下。
root@bearzhang mnt]#mkdir: cannot create directory `mydir’: Permission denied
因为在步骤(2)中的命令行中加了参数ro,任何人对该共享目录都只有只读权限