目录

  • 前言
  • 初识 NFS
  • 1.1 什么是 NFS?
  • 1.2 RPC 远程调度
  • 1.3 NFS 工作过程
  • 1.4 NFS 权限
  • 1.5 NFS 相关文件
  • NFS 案例
  • 2.1 NFS server
  • 2.2 NFS client
  • 2.3 验证


前言

今天来讲讲关于 NFS 的一些知识(主要是我学习的一些笔记,就当现学现卖了!)

当然了,我的水平是有限的,可能会有一些理解错的的概念 or 知识点,还请大家不吝在评论区指正

本篇文章脑图如下:

openert nfs速度 nfs 传输速度_运维


相关文档:

http://www.tldp.org/HOWTO/NFS-HOWTO/index.html

http://cn.linux.vbird.org/linux_server/0330nfs.php#What_NFS_0

初识 NFS

1.1 什么是 NFS?

NFS 是 Network File System 的缩写,翻译成中文就是——网络文件系统

NFS 最大的功能就是可以通过网络,让不同的机器、不同的操作系统可以共享彼此的文件或目录

NFS 架构采用 C/S 模式,NFS client 可以将 NFS server 共享的目录挂载到本地的文件系统中,从 client 来看,server 的目录就好像是自己的一个磁盘分区一样

NFS文件系统架构:

openert nfs速度 nfs 传输速度_服务器_02


NFS 优点:

  • 将常用的数据放在一台可以通过网络访问的服务器上,以此来节省 client 本地存储空间
  • 部署简单快捷,上手容易
  • 维护简单

NFS 缺点:

  • 容易发生单点故障,一旦 server 宕机,那么所有的 client 就访问不到数据了
  • 因为后端只有一台 server,在高并发情况下 server 端容易出现性能瓶颈
  • NFS 数据是明文传输,而且不会对数据完整性做验证,所以安全性较差(建议在局域网内使用)

NFS 支持的功能非常多,而且不同的功能都由不同的 NFS 程序来实现

NFS 每启动一个程序,就会调用一个端口来进行数据传输,而且调用的端口是随机的,不固定的

既然调用的端口是随机的,那么NFS client 又是如何知道 NFS server 到底使用哪个端口进行文件共享的呢?

这时候就需要通过远程过程调用(Remote Procedure Call, RPC)协议来实现了!

1.2 RPC 远程调度

RPC全称是 Remote Procedure Call ,翻译过来就是——远程过程调用/调度

RPC 服务会指定一个端口(111)来对外提供服务,这个服务主要功能就是去记录 NFS server 上每个 NFS 功能所对应的端口,并且通知给 client,让 client 可以连接到正确的端口上去

那么RPC又是如何知道每个 NFS 功能的端口呢?

当 NFS server 服务启动时,会启用一些功能,然后这些功能会去随机调用一些端口

这时候 NFS server 就会向 RPC 去注册这些端口,RPC 将注册端口记录下来

并且 RPC 开启 111 去监听 client 的请求,如果 client 有请求,那么 RPC 就会将记录的 NFS 端口信息通知给 client

client 获取到 NFS server 的端口信息后就能够与 NFS server 进行通信了

PS:
1、在启动 NFS server 之前首先要启动 RPC 服务(portmap 服务)否则 NFS server 2、就无法向 RPC 服务去注册
3、如果 RPC 服务重启,原来已经注册好的 NFS 端口数据会全部丢失,因此 NFS 服务也要重启以便重新向 RPC 注册
4、一般修改 NFS 配置文档后,是不需要重启 NFS 的,直接执行 exportfs -r -v 即可

NFS 启动的 RPC daemon

我们知道 NFS server 在启动的时候需要向 RPC 注册,所以在 NFS server 上需要部署 RPC 服务

NFS 服务器也被称为 RPC server 之一

那么在 NFS server 上需要启动 RPC 的 daemons,至少需要两个,一个是管理 client 是否能够登入;另一个是管理 client 登入后的权限

  • rpc.nfsd

NFS server 的服务提供者,主要功能是管理 client 是否能够登陆到 NFS server

  • rpc.mountd

负责管理 NFS 文件系统,当 client 通过 rpc.nfsd 登录到 NFS server 后,需要通过这个 daemon 来决定 client 能否去访问共享目录

该进程会去读取 NFS 的配置文件( /etc/exports )来对比客户端的权限

  • rpc.lockd (非必要)

负责给共享目录加锁,当多个 client 同时尝试写入某个共享文件时,就会出现问题

  • rpc.lockd 可以解决这个问题,但 rpc.lockd 必须要同时在 client 与 server 都开启才行。此外, rpc.lockd 也常与 rpc.statd 同时启用
  • rpc.statd (非必要)

负责检查共享文件的一致性,与 rpc.lockd 有关

若发生因为 client 同时操作同一文件造成文件可能有所损毁时, rpc.statd 可以用来检测并尝试恢复该文件。

与 rpc.lockd 同样的,这个功能必须要在 server 与 client 都启动才会生效

1.3 NFS 工作过程

openert nfs速度 nfs 传输速度_运维_03

  • 首先 server 启动 RPC 服务,并开启 111 端口
  • 接着 server 启动 NFS 服务,并向 RPC 注册端口信息
  • client 启动 RPC(portmap服务),向 server 的 RPC (portmap) 服务发送请求,请求 server 的 NFS 端口
  • server 的 RPC(portmap) 服务返回 NFS 端口信息给 client
  • client 通过获取的 NFS 端口来建立和 server 的 NFS 连接并进行数据的传输

1.4 NFS 权限

我们首先要知道, Linux 系统会主动以自己的 /etc/passwd, /etc/group 目录来查询对应的账号名、组名

也就是说系统是不认你的用户名,它只认用户名所对应的 UID 和 GID

有没有想过这个问题:假如 client 以 user1 这个身份去对 NFS server 提供的共享目录进行操作时,共享目录会让 client 以什么身份去操作,user1 还是其他?

这是因为 NFS 并不提供身份识别功能,所以说当 client 以 user1 的身份来对共享目录进行操作时,server 会以 client 当前用户(即 user1)的 UID 和 GID 所对应的 server 端用户来操作共享目录(这段有点难理解,多看几遍)

这时候就会有一个问题产生:如果相同 UID 和GID 下 client 与 server 用户身份不一致怎么办,由于共享目录是在 server 端,client 去操作共享目录的话必须按照 server 端的用户权限

举个例子,client 以 user1 (UID 为666)这个身份去操作来自 server 的共享目录时,就会出现以下几种情况:

1、server 和 client 刚好有相同的账号与群组(即 server 端 UID 为 666 的用户对应 user1)

答:此时 client 可以直接以 user1 的身份对共享目录进行操作

2、server 的 666 这个 UID 对应的用户为 test

答:意味着 client 的 user1 用户可以对 server 端 test 用户的共享目录进行操作;因为这两个用户具有相同的 UID

这会造成严重的安全问题,会导致共享目录的数据被错误的用户乱改

3、server 没有 666 这个 UID

答:在 server 端并没有666这个 UID,那么 user1 在该共享目录下会被压缩成匿名用户(也会有特殊的情况,例如共享目录是 /tmp 的情况下, user1 的身份被压缩成 nobody 用户)

一般 NFS 的匿名用户 UID 为 65534

4、root用户

如果 client 操作共享目录的用户 UID 在 server 端对应为 root 用户,那就毫无数据安全可言

所以可以通过设置将 root 用户压缩成匿名用户

总的来讲,client 的权限是与 UID 和 GID 相关的,当 client 与 server 的 UID 对应的用户不一致时,就有可能造成一些问题

NFS配置权限设置,即 /etc/exports 文件配置格式中小括号()里的参数集

openert nfs速度 nfs 传输速度_网络_04

1.5 NFS 相关文件

  • 主要配置文件:/etc/exports

NFS 的配置文件

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

维护 NFS 共享资源的命令,可以对共享资源进行更新、删除等

  • 共享资源的登录文件:/var/lib/nfs/*tab

在 NFS server的登录文件都放置到 /var/lib/nfs/ 目录里面,在该目录下有两个比较重要的登录文件

一个是 etab ,主要记录了 NFS 所共享出来的目录的完整权限设定值;

另一个 xtab 则记录曾经连接到此 NFS 服务器的相关客户端数据

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

showmount 则主要用在 Client 端, 可以用来查看 NFS server 共享出来的目录资源

NFS 案例

学习 NFS 的重点不在部署,在于要搞懂相关原理

下面我将搭一个简单的架构来实现 NFS 的部署

有两台 web 服务器通过 NFS 将后端存储服务器的数据挂载到本地

用户去访问 web 服务器上的资源,其实访问的是后端存储服务器的资源

架构图如下:

openert nfs速度 nfs 传输速度_linux_05

- web1:192.168.149.130
- web2:192.168.149.131
- NFS server:192.168.149.129

2.1 NFS server

安装 NFS、RPC 服务

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

创建共享目录作为客户端挂载的远端入口

[root@server ~]# mkdir /data/{web1,web2} -pv

修改 NFS 配置文件

[root@server ~]# vim /etc/exports
/data/web1  192.168.149.130(rw,sync,insecure,no_subtree_check,no_root_squash)
/data/web2  192.168.149.131(rw,sync,insecure,no_subtree_check,no_root_squash)
一般修改 NFS 配置文档后,是不需要重启 NFS 的,直接执行 exportfs -r -v 即可

启动 rpc 服务

[root@server ~]# systemctl start rpcbind.service

注意:此时我们还没有启动 NFS 服务,只监听了 111 端口,接着我们来启动 NFS 服务

[root@server ~]# systemctl start nfs.service

启动了 NFS 服务后,rpc 注册的端口列表明显增多。现在服务端都启动起来了,在服务端看下是否正确加载了设置的 /etc/exports 配置

[root@server ~]# showmount -e localhost
Export list for localhost:
/data/web2 192.168.149.131
/data/web1 192.168.149.130

接着我们在共享目录下存放web资源

[root@server ~]# cat /data/web1/test.html 
<h1> I am NFS server</h1>
<h2> This is web1 </h2>
[root@server ~]# cat /data/web2/test.html 
<h1> I am NFS server</h1>
<h2> This is web2 </h2>

2.2 NFS client

安装nginx提供web服务

yum install epel-release -y
yum install -y nginx

安装 nfs 服务

yum install -y nfs-utils

nginx配置

#web1
vim /etc/nginx/conf.d/web.conf
server{
        listen 8080;
        root         /mnt/html/;
        index test.html;
}

#web2
vim /etc/nginx/conf.d/web.conf
server{
        listen 8080;
        root         /mnt/html/;
        index test.html;
}

web1、web2 分别创建挂载目录

mkdir /mnt/html/

我们可以在客户端查看下 NFS server ( IP 为:192.168.149.129 ) 设置可共享的目录信息

[root@web1 ~]# showmount -e 192.168.149.129
Export list for 192.168.149.129:
/data/web2 192.168.149.131
/data/web1 192.168.149.130
[root@web2 ~]# showmount -e 192.168.149.129
Export list for 192.168.149.129:
/data/web2 192.168.149.131
/data/web1 192.168.149.130

web1挂载 NFS server 的 /data/web1 共享目录

[root@web1 ~]# mount -t nfs 192.168.149.129:/data/web1 /mnt/html

[root@web1 ~]# df -Th
文件系统                   类型      容量  已用  可用 已用% 挂载点
192.168.149.129:/data/web1 nfs4       17G  2.1G   15G   12% /mnt/html

web2挂载 NFS server 的 /data/web2 共享目录

[root@web2 ~]# mount -t nfs 192.168.149.129:/data/web2 /mnt/html

[root@web2 ~]# df -Th
文件系统                   类型      容量  已用  可用 已用% 挂载点
192.168.149.129:/data/web2 nfs4       17G  2.1G   15G   12% /mnt/html

2.3 验证

我们分别访问web1、web2,看下是否能够正确读取并修改

[root@server ~]# curl 192.168.149.131:8080
<h1> I am NFS server</h1>
<h2> This is web2 </h2>


[root@server ~]# curl 192.168.149.130:8080
<h1> I am NFS server</h1>
<h2> This is web1 </h2>
[root@web1 ~]# echo "hello" >> /mnt/html/test.html

#在 NFS server 上查看,可以看到成功修改了
[root@server ~]# cat /data/web1/test.html 
<h1> I am NFS server</h1>
<h2> This is web1 </h2>
hello

最后,如果客户端要卸载 NFS 挂载(挂载目录为 /mnt/html)的话,使用如下命令即可

umount /mnt/html