集群架构 - NFS网络文件系统

1. NFS应用场景

1.1 NFS简介

NFS是Network File System的缩写,即网络文件系统。

主要功能是通过局域网络让不同的主机系统之间可以共享文件或目录。

NFS系统和Windows网络共享、网络驱动器类似,只不过Windows用于局域网,NFS用于企业集群架构中,如果是大型网站,会用到更复杂的分布式文件系统。

1.2 分布式文件系统

小文件存储系统:

  • MooseFS: 分布式文件系统
  • FastDFS: 轻量级分布式文件系统

大文件存储系统:

  • GlusterFS: 分布式文件系统
  • HDFS: Hadoop分布式文件系统

1.3 NFS工作原理

如果使用NFS客户端挂载的方式将NFS服务器端共享的数据目录挂载至NFS客户端本地系统中。从NFS客户端来看,NFS服务器端共享的目录就好像是客户端自己的磁盘分区或者目录一样,但实际上却是远端NFS服务端的目录。

1.4 集群共享存储需求

下面通过图解展示集群需要共享存储服务的理由。

问题场景:

  • A用户传图片到WEB1服务器
  • B用户访问这张图片
  • 请求分发到了WEB2
  • WEB2上没有这张图片
  • 结果无法看到A用户传的图片

解决方案:

  • 如果有共享存储的情况,A用户上传图片无论分发到WEB1还是WEB2,最终都存储至共享存储
  • 此时B用户访问图片时,无论分发到WEB1还是WEB2上,最终也都会去共享存储上访问
  • 这样就可以访问到资源了

1.5 NFS应用场景

共享存储的位置可以通过开源软件或商业硬件实现,通常互联网中小型集群架构会使用NFS网络文件系统实现。

中小型互联网企业:

  • 一般不会买硬件存储,主要因为过于昂贵

大型公司:

  • 如果业务发展很快,可能考虑购买硬件存储
  • 但当网站并发继续加大时,硬件存储的扩展相对会比较费劲

1.6 NFS存储优点

  1. 简单易用: NFS文件系统简单易用、方便部署、数据可靠、服务稳定、满足中小企业需求
  2. 数据可见: NFS文件系统内数据是在文件系统之上的,所有数据都是能看得见

1.7 NFS存储局限

  1. 单点故障: 存在单点故障,维护麻烦
  2. 性能局限: 高并发场景性能有一定局限(日PV千万)
  3. 数据明文: NFS数据明文,并不对数据做任何校验
  4. 安全性一般: 客户端挂载无需账户密码,安全性一般(内网使用)

1.8 应用建议

  1. 数据前推: 生产场景应将数据尽可能往前端推,减少后端数据库和存储压力
  2. CDN缓存: 将存储里的静态资源通过CDN缓存(jpg、css、js)
  3. 架构优化: 如果没有缓存或架构本身历史遗留问题,在多存储也无用
  4. 适用场景: NFS是中小企业集群架构中最常见的一种(日PV千万)

2. NFS实现原理

2.1 NFS架构

NFS采用客户端/服务器架构,通过RPC(Remote Procedure Call)协议进行通信。

NFS组件:

  • NFS Server: NFS服务器端
  • NFS Client: NFS客户端
  • RPC: 远程过程调用服务

2.2 NFS工作流程

  1. 客户端请求: 客户端向NFS服务器发送文件访问请求
  2. RPC服务: RPC服务将请求转发给NFS服务
  3. 文件操作: NFS服务器执行文件操作
  4. 返回结果: 将结果返回给客户端

2.3 NFS版本

版本 说明 特点
NFSv2 早期版本 功能有限
NFSv3 常用版本 支持大文件,异步写入
NFSv4 最新版本 安全性增强,支持ACL

2.4 NFS端口

NFS使用动态端口,通过RPC服务进行端口映射。

常用端口:

  • 111: RPC服务端口
  • 2049: NFS服务端口

3. NFS服务实践

3.1 环境准备

服务器规划:

  • NFS服务器: 192.168.56.11
  • NFS客户端: 192.168.56.12, 192.168.56.13

3.2 关闭防火墙和SELinux

不要忘记关闭防火墙,以免默认的防火墙策略禁止正常的NFS共享服务。

1
2
3
4
5
6
7
8
9
10
11
# 关闭Firewalld防火墙
[root@liyanzhao ~]# systemctl disable firewalld
[root@liyanzhao ~]# systemctl stop firewalld

# 关闭selinux防火墙
[root@liyanzhao ~]# sed -ri '/^SELINUX=/cSELINUX=Disabled' /etc/selinux/config
[root@liyanzhao ~]# setenforce 0

# 验证SELinux状态
[root@liyanzhao ~]# getenforce
Disabled

3.3 安装NFS服务

1
2
# 安装nfs服务主程序
[root@nfs-server ~]# yum -y install nfs-utils rpcbind

软件包说明:

  • nfs-utils: NFS服务程序
  • rpcbind: RPC服务程序

3.4 配置NFS共享

NFS服务程序的配置文件为/etc/exports,默认里面没有任何内容。

我们可以按照”共享目录的路径 允许访问的NFS客户端(共享权限参数)”格式,定义要共享的目录与相应的权限。

配置示例

如果想要把/data目录共享给192.168.56.0/24网段内的所有主机:

  1. 主机都拥有读写权限
  2. 在将数据写入到NFS服务器的硬盘中后才会结束操作,最大限度保证数据不丢失
  3. 将所有用户映射为本地的匿名用户

注意: NFS客户端地址与权限之间没有空格。

1
2
3
4
5
# 编辑NFS配置文件
[root@nfs-server ~]# vim /etc/exports

# 添加共享配置
/data 192.168.56.0/24(rw,sync,all_squash)

创建共享目录

1
2
3
# 在NFS服务器上建立用于NFS文件共享的目录,并设置对应权限
[root@nfs-server ~]# mkdir /data
[root@nfs-server ~]# chown -R nfsnobody.nfsnobody /data

验证配置

NFS共享目录会记录至/var/lib/nfs/etab,如果该目录不存在共享信息,请检查配置。

1
2
# 查看共享配置
[root@nfs-server ~]# cat /var/lib/nfs/etab

3.5 启动NFS服务

在使用NFS服务进行文件共享之前,需要使用RPC(Remote Procedure Call,远程过程调用)服务将NFS服务器的IP地址和端口号信息发送给客户端。

因此,在启动NFS服务之前,需要先重启并启用rpcbind服务程序,同时都加入开机自启动。

1
2
3
4
5
6
7
8
9
10
11
# 启动rpcbind服务
[root@nfs-server ~]# systemctl restart rpcbind
[root@nfs-server ~]# systemctl enable rpcbind

# 启动NFS服务
[root@nfs-server ~]# systemctl restart nfs-server
[root@nfs-server ~]# systemctl enable nfs-server

# 检查服务状态
[root@nfs-server ~]# systemctl status rpcbind
[root@nfs-server ~]# systemctl status nfs-server

3.6 NFS共享权限参数

参数 说明
ro 只读权限
rw 读写权限
sync 同步写入,数据安全
async 异步写入,性能好
root_squash 将root用户映射为匿名用户
no_root_squash 不映射root用户
all_squash 将所有用户映射为匿名用户
no_all_squash 不映射用户
anonuid 指定匿名用户的UID
anongid 指定匿名用户的GID

4. NFS客户端挂载

4.1 安装客户端工具

NFS客户端的配置步骤也十分简单。先使用showmount命令,查询NFS服务器的远程共享信息,其输出格式为”共享的目录名称 允许使用客户端地址”。

1
2
3
4
5
6
# 安装客户端工具,仅启动rpcbind服务
[root@nfs-client ~]# yum -y install nfs-utils rpcbind

# 启动rpcbind服务
[root@nfs-client ~]# systemctl restart rpcbind
[root@nfs-client ~]# systemctl enable rpcbind

4.2 查看远程共享信息

1
2
3
4
# 客户端查看远程服务器提供可挂载信息
[root@nfs-client ~]# showmount -e 192.168.56.11
Export list for 192.168.56.11:
/data 192.168.56.0/24

showmount命令参数:

  • -e: 显示NFS服务器的导出列表
  • -a: 显示所有挂载的客户端
  • -d: 显示被挂载的目录

4.3 挂载NFS共享

在NFS客户端创建一个挂载目录,使用mount命令并结合-t参数,指定要挂载的文件系统的类型,并在命令后面写上服务器的IP地址,以及服务器上的共享目录,最后需要写上要挂载到本地系统(客户端)的目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 创建挂载点
[root@nfs-client ~]# mkdir /nfsdir

# 挂载NFS共享
[root@nfs-client ~]# mount -t nfs 192.168.56.11:/data /nfsdir

# 查看挂载信息(mount也可以查看)
[root@nfs-client ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 62G 845M 58G 2% /
tmpfs 244M 0 244M 0% /dev/shm
/dev/sda1 190M 26M 155M 14% /boot
192.168.56.11:/data 62G 880M 58G 2% /nfsdir

4.4 测试NFS共享

挂载成功后可以进行增删改操作。

1
2
3
4
5
6
# 使用客户端往nfs存储写入
[root@nfs-client ~]# echo "nfs-client" >> /nfsdir/test.txt

# 检查nfs服务端是否存在客户端创建的新文件
[root@nfs-server ~]# cat /data/test.txt
nfs-client

4.5 配置开机自动挂载

如果希望NFS文件共享服务能一直有效,则需要将其写入到fstab文件中。

1
2
3
4
5
# 编辑fstab文件
[root@nfs-client ~]# vim /etc/fstab

# 添加以下内容
192.168.56.11:/data /nfsdir nfs defaults 0 0

fstab格式说明:

1
设备名    挂载点    文件系统类型    挂载选项    备份    检查

NFS挂载选项:

  • defaults: 使用默认选项
  • _netdev: 网络设备,等待网络就绪后再挂载
  • soft: 软挂载,超时后返回错误
  • hard: 硬挂载,超时后重试

4.6 卸载NFS共享

如果不希望使用NFS共享,可进行卸载。

1
2
# 卸载NFS共享
[root@nfs-client ~]# umount /nfsdir

注意: 卸载的时候如果提示”umount.nfs: /nfsdir: device is busy”:

  1. 切换至其他目录,然后再进行卸载:

    1
    2
    cd /
    umount /nfsdir
  2. NFS Server宕机,强制卸载:

    1
    umount -lf /nfsdir

5. AutoFS自动挂载

5.1 AutoFS概述

无论是Samba服务还是NFS服务,都要把挂载信息写入到/etc/fstab中,这样远程共享资源就会自动随服务器开机而进行挂载。

问题:

  1. 虽然很方便,但挂载资源过多会造成网络带宽以及服务器硬件资源带来很大的负载
  2. 如果在资源挂载后长期不使用,也会造成服务器硬件资源的浪费
  3. 每次使用之前执行mount手动挂载,这是个不错的选择,但每次都需要先挂载在使用,会非常的麻烦

解决方案: autofs自动挂载服务可以帮我们解决这一问题。

autofs服务程序是一种守护进程,当检测到用户试图访问一个尚未挂载的文件系统时,将自动挂载该文件系统。

autofs服务程序是在用户需要使用该文件系统时才去动态挂载,从而节约了网络资源和服务器的硬件资源。

5.2 AutoFS挂载方式

autofs自动挂载服务,有两种挂载方式:

挂载方式 说明 特点
直接(direct) /- 子配置文件必须写本地绝对路径 挂载点是绝对路径
间接(indirect) /path 子配置文件写相对于/path的子目录 挂载点是相对路径

5.3 安装AutoFS服务

1
2
3
4
5
6
# 客户端安装autofs自动挂载
[root@nfs-client ~]# yum install autofs -y

# 启动并加入开机自启动
[root@nfs-client ~]# systemctl enable autofs
[root@nfs-client ~]# systemctl start autofs

5.4 直接挂载方式

本地的挂载点是绝对路径。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 不要将设备挂载信息都写入到autofs服务的主配置/etc/auto.master文件中
# 可以将文件写入/etc/auto.master.d目录下,该目录已被主配置文件包含
[root@http-server ~]# grep "dir" /etc/auto.master
+dir:/etc/auto.master.d

# 名称后缀必须是autofs,/-代表这是一个直接挂载定义,根据/etc/auto.nfs_direct进行挂载
[root@nfs-client ~]# vim /etc/auto.master.d/nfs.autofs
/- /etc/auto.nfs_direct

# 子配置文件中,按照"挂载目录 挂载文件类型及权限 :设备名称"的格式进行填写
[root@nfs-client ~]# vim /etc/auto.nfs_direct
/nfsdir -fstype=nfs,rw,sync,soft,nosuid,nodev 192.168.56.11:/data

# 重启autofs服务
[root@nfs-client ~]# systemctl restart autofs

配置说明:

  • /-: 表示直接挂载
  • /nfsdir: 本地挂载点(绝对路径)
  • -fstype=nfs: 文件系统类型为NFS
  • rw,sync,soft,nosuid,nodev: 挂载选项

5.5 间接挂载方式

本地路径和服务端的路径都没有直接写绝对路径。

1
2
3
4
5
6
7
8
9
10
11
# 名称后缀必须是autofs,访问本地对应目录自动远端nfs
[root@nfs-client ~]# vim /etc/auto.master.d/nfs.autofs
#/- /etc/auto.nfs_direct
/nfsdir /etc/auth.nfs_share

# 子配置文件
[root@nfs-client ~]# vim /etc/auth.nfs_share
* -rw,sync,soft,nosuid,nodev,'sec=krb5p' 192.168.56.11:/data/&

# 重启autofs服务
[root@nfs-client ~]# systemctl restart autofs

配置说明:

  • /nfsdir: 本地挂载点目录
  • *: 匹配所有子目录
  • &: 代表通配符匹配的内容
  • sec=krb5p: Kerberos安全选项

注意: 如果有kerberos验证则需要启动nfs-secure,并加入开机自启动。

1
2
systemctl start nfs-secure
systemctl enable nfs-secure

5.6 验证AutoFS挂载

1
2
3
4
5
6
7
8
# 使用df命令无法查看具体挂载内容,使用mount命令可以
[root@nfs-client ~]# mount | grep nfs

# 访问挂载点会自动挂载
[root@nfs-client ~]# ls /nfsdir

# 查看autofs挂载信息
[root@nfs-client ~]# systemctl status autofs

6. NFS共享系统实践

6.1 项目需求

准备3台虚拟机服务器(VM)NFS服务端(A)、NFS客户端(B)、NFS客户端(C),并且请按照要求搭建配置NFS服务。

需求:

  1. 在NFS服务端A上共享/data/w_share/data/r_share两个文件目录,允许NFS客户端B、C上分别挂载共享目录后可实现从B、C上对/data/r_share目录只读权限、对/data/w_share拥有可写权限
  2. NFS客户端(B)挂载NFS至本地站点对应的目录 /data/b_w(写)、/data/b_r(读)
  3. NFS客户端(C)挂载NFS至本地站点对应的目录/data/w_liyanzhao/data/r_xuliangwei

6.2 环境规划

服务器规划:

  • NFS服务端A: 192.168.56.11
  • NFS客户端B: 192.168.56.12
  • NFS客户端C: 192.168.56.13

规划图:

1
2
3
4
5
6
7
8
9
10
11
NFS服务端A (192.168.56.11)
├── /data/w_share (读写)
└── /data/r_share (只读)

├── 客户端B (192.168.56.12)
│ ├── /data/b_w (挂载w_share)
│ └── /data/b_r (挂载r_share)

└── 客户端C (192.168.56.13)
├── /data/w_liyanzhao (挂载w_share)
└── /data/r_xuliangwei (挂载r_share)

6.3 NFS服务端配置

步骤1: 环境准备

1
2
3
4
5
# 关闭防火墙和SELinux
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -ri '/^SELINUX=/cSELINUX=Disabled' /etc/selinux/config

步骤2: 安装NFS服务

1
2
# 安装NFS服务
yum -y install nfs-utils rpcbind

步骤3: 创建共享目录

1
2
3
4
5
6
7
8
9
10
# 创建共享目录
mkdir -p /data/{w_share,r_share}

# 设置目录权限
chown -R nfsnobody.nfsnobody /data/w_share
chown -R nfsnobody.nfsnobody /data/r_share

# 设置目录权限(只读目录设置只读权限)
chmod 755 /data/r_share
chmod 777 /data/w_share

步骤4: 配置NFS共享

1
2
# 编辑NFS配置文件
vim /etc/exports
1
2
3
# 添加以下配置
/data/w_share 192.168.56.12(rw,sync,all_squash) 192.168.56.13(rw,sync,all_squash)
/data/r_share 192.168.56.12(ro,sync,all_squash) 192.168.56.13(ro,sync,all_squash)

配置说明:

  • w_share: 读写共享目录
  • r_share: 只读共享目录
  • rw: 读写权限
  • ro: 只读权限
  • sync: 同步写入
  • all_squash: 映射所有用户为匿名用户

步骤5: 启动NFS服务

1
2
3
4
5
6
7
8
9
10
# 启动rpcbind服务
systemctl restart rpcbind
systemctl enable rpcbind

# 启动NFS服务
systemctl restart nfs-server
systemctl enable nfs-server

# 验证共享配置
exportfs -v

6.4 NFS客户端B配置

步骤1: 安装客户端工具

1
2
3
4
5
6
# 安装NFS客户端工具
yum -y install nfs-utils rpcbind

# 启动rpcbind服务
systemctl restart rpcbind
systemctl enable rpcbind

步骤2: 查看共享信息

1
2
# 查看NFS服务器共享信息
showmount -e 192.168.56.11

步骤3: 创建挂载点并挂载

1
2
3
4
5
6
7
8
9
10
11
# 创建挂载点
mkdir -p /data/{b_w,b_r}

# 挂载读写共享目录
mount -t nfs 192.168.56.11:/data/w_share /data/b_w

# 挂载只读共享目录
mount -t nfs 192.168.56.11:/data/r_share /data/b_r

# 验证挂载
df -h | grep nfs

步骤4: 配置开机自动挂载

1
2
3
4
5
6
# 编辑fstab文件
vim /etc/fstab

# 添加以下内容
192.168.56.11:/data/w_share /data/b_w nfs defaults,_netdev 0 0
192.168.56.11:/data/r_share /data/b_r nfs defaults,_netdev 0 0

步骤5: 测试读写权限

1
2
3
4
5
6
# 测试写入(应该成功)
echo "test from B" > /data/b_w/test.txt

# 测试只读目录写入(应该失败)
echo "test" > /data/b_r/test.txt
# 提示:Read-only file system

6.5 NFS客户端C配置

步骤1: 安装客户端工具

1
2
3
4
5
6
# 安装NFS客户端工具
yum -y install nfs-utils rpcbind

# 启动rpcbind服务
systemctl restart rpcbind
systemctl enable rpcbind

步骤2: 查看共享信息

1
2
# 查看NFS服务器共享信息
showmount -e 192.168.56.11

步骤3: 创建挂载点并挂载

1
2
3
4
5
6
7
8
9
10
11
# 创建挂载点
mkdir -p /data/w_liyanzhao /data/r_xuliangwei

# 挂载读写共享目录
mount -t nfs 192.168.56.11:/data/w_share /data/w_liyanzhao

# 挂载只读共享目录
mount -t nfs 192.168.56.11:/data/r_share /data/r_xuliangwei

# 验证挂载
df -h | grep nfs

步骤4: 配置开机自动挂载

1
2
3
4
5
6
# 编辑fstab文件
vim /etc/fstab

# 添加以下内容
192.168.56.11:/data/w_share /data/w_liyanzhao nfs defaults,_netdev 0 0
192.168.56.11:/data/r_share /data/r_xuliangwei nfs defaults,_netdev 0 0

步骤5: 测试读写权限

1
2
3
4
5
6
# 测试写入(应该成功)
echo "test from C" > /data/w_liyanzhao/test.txt

# 测试只读目录写入(应该失败)
echo "test" > /data/r_xuliangwei/test.txt
# 提示:Read-only file system

6.6 验证共享功能

在客户端B测试

1
2
3
4
5
# 在客户端B写入文件
echo "Hello from B" > /data/b_w/from_b.txt

# 在客户端C查看文件(应该能看到)
cat /data/w_liyanzhao/from_b.txt

在客户端C测试

1
2
3
4
5
# 在客户端C写入文件
echo "Hello from C" > /data/w_liyanzhao/from_c.txt

# 在客户端B查看文件(应该能看到)
cat /data/b_w/from_c.txt

在服务端验证

1
2
3
# 在服务端查看共享目录内容
ls -l /data/w_share/
ls -l /data/r_share/

7. NFS性能优化

7.1 挂载选项优化

1
2
# 性能优化挂载选项
mount -t nfs -o rw,sync,noatime,nodiratime,vers=3 192.168.56.11:/data /nfsdir

优化选项说明:

  • noatime: 不更新访问时间
  • nodiratime: 不更新目录访问时间
  • vers=3: 使用NFSv3协议
  • rsize=32768: 读缓冲区大小
  • wsize=32768: 写缓冲区大小

7.2 服务端优化

1
2
3
4
5
6
# 编辑NFS服务配置
vim /etc/sysconfig/nfs

# 优化参数
RPCNFSDCOUNT=32
RPCSVCGSSDARGS="-n 4"

7.3 网络优化

1
2
3
4
5
6
7
8
# 优化网络参数
cat >> /etc/sysctl.conf <<EOF
# NFS优化
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
EOF

sysctl -p

8. NFS故障排查

8.1 常见问题

问题1: 无法挂载

1
2
3
4
5
6
7
8
9
# 检查网络连通性
ping NFS服务器IP

# 检查端口
telnet NFS服务器IP 111
telnet NFS服务器IP 2049

# 检查防火墙
firewall-cmd --list-all

问题2: 权限被拒绝

1
2
3
4
5
6
7
8
# 检查共享配置
cat /etc/exports

# 检查目录权限
ls -ld /data/w_share

# 重新导出共享
exportfs -rv

问题3: 读写权限问题

1
2
3
4
5
# 检查挂载选项
mount | grep nfs

# 检查服务端配置
cat /etc/exports

8.2 调试命令

1
2
3
4
5
6
7
8
9
10
11
# 查看NFS共享状态
exportfs -v

# 查看RPC服务状态
rpcinfo -p NFS服务器IP

# 查看NFS连接
netstat -an | grep :2049

# 查看NFS日志
tail -f /var/log/messages

9. NFS安全加固

9.1 安全建议

  1. 使用内网: NFS仅在内网使用
  2. 限制访问: 使用防火墙限制访问来源
  3. 使用NFSv4: 启用NFSv4增强安全性
  4. 使用Kerberos: 启用Kerberos认证
  5. 定期备份: 定期备份NFS数据

9.2 防火墙配置

1
2
3
4
5
# 配置防火墙允许NFS
firewall-cmd --permanent --add-service=nfs
firewall-cmd --permanent --add-service=rpc-bind
firewall-cmd --permanent --add-service=mountd
firewall-cmd --reload

9.3 NFSv4配置

1
2
3
4
5
# 编辑NFS配置
vim /etc/sysconfig/nfs

# 启用NFSv4
RPCNFSDARGS="-V 4"

实战优化