1.NFS 基本概述
NFS 是 Network File System 的缩写及网络文件系统。NFS 主要功能是通过局域网络让不同的主机系统之间可以共 享文件或目录。
NFS 系统和 Windows 网络共享、网络驱动器类似, 只不过 windows 用于局域网, NFS 用于企业集群架构中, 如果是大型网站, 会用到更复杂的分布式文件系统 FastDFS,glusterfs,HDFS
那么我们为什么要使用数据存储共享服务
实现多台服务器之间数据共享
实现多台服务器之间数据一致
2.NFS 应用场景
1.A 用户上传图片经过负载均衡,负载均衡将上传请求调度至 WEB1 服务器上。
2.B 用户访问 A 用户上传的图片,此时 B 用户被负载均衡调度至 WEB2 上,因为 WEB2 上没有这张图片,所以 B 用户无法看到 A 用户传的图片。

如果有共享存储的情况
1.A 用户上传图片无论被负载均衡调度至 WEB1 还是 WEB2, 最终数据都被写入至共享存储
2.B 用户访问 A 用户上传图片时,无论调度至 WEB1 还是 WEB2,最终都会上共享存储访问对应的文件,这样就可以访问到资源了

3.NFS实现原理

本地文件操作方式
1.当用户执行 mkdir 命令, 该命令会调用 shell 解释器翻译给内核
2.内核解析完成后会驱动对应的硬件设备,完成相应的操作
NFS 实现原理(需要先了解[程序|进程|线程])
1..用户进程访问 NFS 客户端,使用不同的函数对数据进行处理
2.NFS 客户端通过 TCP/IP 的方式传递给 NFS 服务端。
3.NFS 服务端接收到请求后,会先调用 portmap 进程进行端口映射。
4.nfsd 进程用于判断 NFS 客户端是否拥有权限连接 NFS 服务端。
5.Rpc.mount 进程判断客户端是否有对应的权限进行验证。
6.idmap 进程实现用户映射和压缩
7.最后 NFS 服务端会将对应请求的函数转换为本地能识别的命令,传递至内核,由内核驱动硬件。
注意: rpc 是一个远程过程调用,那么使用 nfs 必须有 rpc 服务
4.NFS 服务安装
准备两台机器
服务端
[root@nfs ~]$ hostname -I | cut -f2 -d ' '
172.16.1.16
客户端
[root@web01 ~]$ hostname -I | cut -f2 -d ' '
172.16.1.45
安装nfs,rpcbind(服务端和服务端都需要)
[root@nfs ~]$ yum install -y nfs-utils rpcbind
[root@web01 ~]$ yum install -y nfs-utils rpcbind
启动rpc服务
[root@nfs ~]$ systemctl start rpcbind
[root@nfs ~]$ systemctl enable rpcbind
检查rpc服务状态
[root@nfs ~]$ rpcinfo -p
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
启动nfs服务
[root@nfs ~]$systemctl start nfs
[root@nfs ~]$ systemctl enable nfs
检查rpc服务状态
[root@nfs ~]$ rpcinfo -p
program vers proto port service
100024 1 tcp 38296 status
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
配置 nfs 服务,nfs 服务程序的配置文件为/etc/exports,需要严格按照共享目录的路径 允许访问的 NFS 客户端(共 享权限参数)格式书写,定义要共享的目录与相应的权限,具体书写方式如下图所示

配置场景,将 nfs 服务端的/dmxsp目录共享给 172.16.1.0/24 网段内的所有主机
所有客户端主机都拥有读写权限
在将数据写入到 NFS 服务器的硬盘中后才会结束操作,最大限度保证数据不丢失
将所有用户映射为本地的匿名用户(nfsnobody)
nfs服务端,共享参数
rw | 可以读写 |
ro | 只读 read only |
sync | 同步读写 |
async | 异步读写 |
anonuid | anonymous uid 指定用户uid 压缩之后用户的uid |
anongid | anonymous gid 指定用户gid 压缩之后的用户的gid |
root_squash | 只对root用户进行压缩 |
no_root_squash | 不对root用户进程压缩 |
all_squash | 所有用户被压缩为 指定的匿名用户 |
no_all_squash | 不对普通用户压缩 |
[root@nfs ~]$ vim /etc/exports
[root@nfs ~]$ cat /etc/exports
/dmxsp 172.16.1.0/24(rw)
创建共享目录
[root@nfs ~]$ mkdir -p /dmxsp
查看用户(安装nfs给的用户)
[root@nfs ~]$ id nfsnobody
修改文件用户
[root@nfs ~]$ chown nfsnobody.nfsnobody /dmxsp/
[root@nfs ~]$ ll /dmxsp/ -d
drwxr-xr-x 2 nfsnobody nfsnobody 6 Jul 9 14:53 /dmxsp/
重启nfs服务
[root@nfs ~]$ systemctl restart nfs
查询NFS服务器的相关信息
[root@nfs ~]$ showmount -e 172.16.1.16
Export list for 172.16.1.16:
/dmxsp 172.16.1.0/24
[root@nfs ~]$ showmount -e
Export list for dmxsp:
/dmxsp 172.16.1.0/24
本地测试挂载
[root@nfs ~]$ df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 475M 0 475M 0% /dev
tmpfs 487M 0 487M 0% /dev/shm
tmpfs 487M 7.7M 479M 2% /run
tmpfs 487M 0 487M 0% /sys/fs/cgroup
/dev/mapper/centos-root 37G 20G 18G 53% /
/dev/sda1 1014M 137M 878M 14% /boot
tmpfs 98M 0 98M 0% /run/user/0
[root@nfs ~]$ mount -t nfs 172.16.1.16:/dmxsp /mnt
[root@nfs ~]$ df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 475M 0 475M 0% /dev
tmpfs 487M 0 487M 0% /dev/shm
tmpfs 487M 7.7M 479M 2% /run
tmpfs 487M 0 487M 0% /sys/fs/cgroup
/dev/mapper/centos-root 37G 20G 18G 53% /
/dev/sda1 1014M 137M 878M 14% /boot
tmpfs 98M 0 98M 0% /run/user/0
172.16.1.16:/dmxsp 37G 20G 18G 53% /mnt
[root@nfs ~]$ touch /mnt/cs.txt
[root@nfs ~]$ ll /dmxsp/
total 0
-rw-r--r-- 1 nfsnobody nfsnobody 0 Jul 9 15:32 cs.txt
客户端测试挂载
[root@web01 ~]$ df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 898M 0 898M 0% /dev
tmpfs 910M 0 910M 0% /dev/shm
tmpfs 910M 9.6M 901M 2% /run
tmpfs 910M 0 910M 0% /sys/fs/cgroup
/dev/mapper/centos-root 47G 5.4G 42G 12% /
/dev/sda1 1014M 151M 864M 15% /boot
tmpfs 182M 0 182M 0% /run/user/0
[root@web01 ~]$ mount -t nfs 172.16.1.16:/dmxsp /opt/
[root@web01 ~]$ df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 898M 0 898M 0% /dev
tmpfs 910M 0 910M 0% /dev/shm
tmpfs 910M 9.6M 901M 2% /run
tmpfs 910M 0 910M 0% /sys/fs/cgroup
/dev/mapper/centos-root 47G 5.4G 42G 12% /
/dev/sda1 1014M 151M 864M 15% /boot
tmpfs 182M 0 182M 0% /run/user/0
172.16.1.16:/dmxsp 47G 2.0G 46G 5% /opt
[root@web01 ~]$ touch /opt/khdcs.txt
[root@web01 ~]$ ll /opt/
total 0
-rw-r--r-- 1 nfsnobody nfsnobody 0 Jul 9 15:32 cs.txt
-rw-r--r-- 1 nfsnobody nfsnobody 0 Jul 9 15:35 khdcs.txt
服务端查看
[root@nfs ~]$ ll /dmxsp/
total 0
-rw-r--r-- 1 nfsnobody nfsnobody 0 Jul 9 15:32 cs.txt
-rw-r--r-- 1 nfsnobody nfsnobody 0 Jul 9 15:35 khdcs.txt
挂载ro
修改配置文件
[root@nfs ~]$ vim /etc/exports
[root@nfs ~]$ cat /etc/exports
/dmxsp/rw 172.16.1.0/24(rw)
/dmxsp/ro 172.16.1.0/24(ro)
创建文件
[root@nfs ~]$ mkdir -p /dmxsp/{rw,ro}
修改文件用户
[root@nfs ~]$ chown -R nfsnobody.nfsnobody /dmxsp/
重启服务
[root@nfs ~]$ systemctl restart nfs
本地挂载测试
[root@nfs ~]$ umount /mnt
[root@nfs ~]$ mount -t nfs 172.16.1.16:/dmxsp/ro /opt/
[root@nfs ~]$ touch /opt/rocs.txt
touch: cannot touch ‘/opt/rocs.txt’: Read-only file system
客户端测试挂载
[root@web01 ~]$ umount /opt
[root@web01 ~]$ mount -t nfs 172.16.1.16:/dmxsp/rw /opt/
[root@web01 ~]$ touch /opt/123.txt
[root@web01 ~]$ ll /opt/
total 0
-rw-r--r-- 1 nfsnobody nfsnobody 0 Jul 9 21:25 123.txt
[root@web01 ~]$ umount /opt
[root@web01 ~]$ mount -t nfs 172.16.1.16:/dmxsp/ro /opt/
[root@web01 ~]$ ll /opt/
total 0
[root@web01 ~]$ touch /opt/123.txt
touch: cannot touch ‘/opt/123.txt’: Read-only file system
(在服务端nfs配置文件里是挂载/dmxsp目录下的)
[root@web01 ~]$ mount -t nfs 172.16.1.16:/dmxsp/ /mnt/
[root@web01 ~]$ touch /mnt/dmxsp.txt
touch: cannot touch ‘/mnt/dmxsp.txt’: Read-only file system
服务端查看
[root@nfs ~]$ ll /dmxsp/rw/
total 0
-rw-r--r-- 1 nfsnobody nfsnobody 0 Jul 9 21:25 123.txt
验证 all_squash、anonuid、anongid 权限
NFS 服务端配置
[root@nfs ~]$ cat /etc/exports
/dmxsp/rw 172.16.1.0/24(rw,sync,all_squash,anonuid=666,anongid=666)
/dmxsp/ro 172.16.1.0/24(ro)
服务端需要创建对应的用户
[root@nfs ~]$ groupadd ‐g 666 www
[root@nfs ~]$ useradd -s /sbin/nologin -M -u 666 -g 666 www
[root@nfs ~]$ id www
uid=666(www) gid=666(www) groups=666(www)
重启 nfs-server
[root@nfs ~]$ systemctl restart nfs‐server
(记录NFS分享出来的目录的完整权限设定值)
[root@nfs ~]$ cat /var/lib/nfs/etab
/dmxsp/ro 172.16.1.0/24(ro,sync,wdelay,hide,nocrossmnt,secure,root_squash,no_all_squash,no_subtree_check,secure_locks,acl,no_pnfs,anonuid=65534,anongid=65534,sec=sys,ro,secure,root_squash,no_all_squash)
/dmxsp/rw 172.16.1.0/24(rw,sync,wdelay,hide,nocrossmnt,secure,root_squash,all_squash,\no_subtree_check,secure_locks,acl,no_pnfs,anonuid=666,anongid=666,\sec=sys,secure,root_squash,all_squash)
修改目录所有者
[root@nfs ~]$ chown ‐R www.www /dmxsp/rw
[root@nfs ~]$ ll ‐d /dmxsp/rw
drwxr‐xr‐x 3 www www 53 Sep 3 02:08 /dmxsp/rw
客户端验证
[root@web01 ~]$ umount /mnt/
[root@web01 ~]$ mount ‐t nfs 172.16.1.16:/dmxsp/rw /mnt
建议:将客户端也创建一个 uid 为 666,gid 为 666,统一身份,避免后续出现权限不足的情况
[root@web01 ~]$ groupadd ‐g 666 www
[root@web01 ~]$ useradd -s /sbin/nologin -M -u 666 -g 666 www
[root@web01 ~]$ id www
uid=666(www) gid=666(www) groups=666(www)
5.nfs客户端挂载选项
客户端挂载 mount
/proc/mounts
[root@nfs ~]$ grep 172.16.1.16 /proc/mounts
172.16.1.16:/dmxsp/ro /opt nfs4 rw,relatime,vers=4.1,rsize=131072,wsize=131072,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=172.16.1.22,local_lock=none,addr=172.16.1.22 0 0
mount
-t:指定文件系统类型 xfs,ext4/ext3, nfs
-o:指定挂载详细参数
-a:卸除/etc/mtab中记录的所有文件系统。
-f:强制卸载(对于无法访问的NFS系统)
-h:显示帮助。
-n:卸除时不要将信息存入/etc/mtab文件中。
-r:若无法成功卸除,则尝试以只读的方式重新挂入文件系统。
-v:执行时显示详细的信息。
-V:显示版本信息。
-l:懒惰的卸载。从文件系统层次分离文件系统,在不繁忙的情况下清理所有对文件系统的引用
nfs挂载参数(客户端)
[root@web01 ~]$ mount -t nfs -o ro 172.16.1.16:/dmxsp/rw /mnt/
[root@web01 ~]$ touch /mnt/abc.txt
touch: cannot touch ‘/mnt/abc.txt’: Read-only filesystem
把ro修改为rw
[root@web01 ~]$ mount -o rw,remount /mnt/
[root@web01 ~]$ grep mnt /proc/mounts
注意事项
背景: 因为一些原因(磁盘故障),整个磁盘(文件系统)变为只读, 创建文件,提示 Read-only file system
排查: 查询具体哪个分区只读, 排查出是 /分区只读
解决: mount -o rw,remount /
永久挂载
方法1
写入/etc/rc.local 注意 /etc/rc.d/rc.local +x
mount -t nfs -o ro 172.16.1.16:/dmxsp/rw /mnt/
方法2
写入/etc/fstab
172.16.1.16:/dmxsp/rw /upload nfs defaults 0 0
6.NFS存储总结
NFS 存储优点
NFS 文件系统简单易用、方便部署、数据可靠、服务稳定、满足中小企业需求。
NFS 文件系统内存放的数据都在文件系统之上,所有数据都是能看得见。
NFS 存储局限
存在单点故障, 如果构建高可用维护麻烦 web‐>nfs()‐>backup
NFS 数据明文, 并不对数据做任何校验。
客户端挂载 NFS 服务没有密码验证, 安全性一般(内网使用)
NFS 应用建议
生产场景应将静态数据尽可能往前端推, 减少后端存储压力
必须将存储里的静态资源通过 CDN 缓存 jpg\png\mp4\avi\css\js
如果没有缓存或架构本身历史遗留问题太大, 在多存储也无用
7.NFS 案例实践
准备 3 台虚拟机服务器
在 NFS 服务端(A)上共享/data/w(可写)及/data/r(只读)
在 NFS 客户端(B/C)上进行挂载
环境准备
nfs服务端nfs01 10.0.0.31/172.16.1.31
nfs客户端web01 10.0.0.7/172.16.1.7
nfs客户端backup 10.0.0.41/172.16.1.41
NFS服务端配置
安装 nfs
[root@nfs01 ~]# yum install ‐y nfs‐utils
配置 nfs
[root@nfs01 ~]# cat /etc/exports
/data/r 172.16.1.0/24(ro,sync,all_squash,anonuid=666,anongid=666)
/data/w 172.16.1.0/24(rw,sync,all_squash,anonuid=666,anongid=666)
创建对应用户
[root@nfs01 ~]# groupadd ‐g 666 www
[root@nfs01 ~]# useradd -s /sbin/nologin -M -u 666 ‐g 666 www
[root@nfs01 ~]# id www
uid=666(www) gid=666(www) groups=666(www)
创建共享目录
[root@nfs01 ~]# mkdir /data/{r,w} ‐p
[root@nfs01 ~]# chown ‐R www.www /data/
重启 NFS
[root@nfs01 ~]# systemctl restart rpcbind nfs
NFS-客户端配置
安装 nfs 工具
[root@backup‐41 ~]# yum install nfs‐utils ‐y
[root@backup‐41 ~]# systemctl restart rpcbind
准备本地挂载点目录
[root@backup‐41 ~]# mkdir /data/{r,w} ‐p
准备对应用户
[root@nfs01 ~]# groupadd ‐g 666 www
[root@nfs01 ~]# useradd -s /sbin/nologin -M -u 666 ‐g 666 www
[root@nfs01 ~]# id www
uid=666(www) gid=666(www) groups=666(www)
查看远端共享的 nfs 目录
[root@web01 ~]# showmount ‐e 172.16.1.31
Export list for 172.16.1.31:
/data/w 172.16.1.0/24
/data/r 172.16.1.0/24
挂载对应目录站点
[root@web01 ~]# mount ‐t nfs 172.16.1.31:/data/w /data/w/
[root@web01~]# mount ‐t nfs 172.16.1.31:/data/r /data/r/
[root@web01 ~]# df ‐h
Filesystem Size Used Avail Use% Mounted on
172.16.1.31:/data/w 50G 1.6G 49G 4% /data/w
172.16.1.31:/data/r 50G 1.6G 49G 4% /data/r
测试/data/r 读权限
[root@web01 r]$ pwd
/data/r
[root@web01r]$ cat edu.com
This is Nfs to Oldboy
[root@web01 r]$ touch edu
touch: cannot touch ‘edu’: Read‐only file system
测试/data/w 写权限
[root@web01 r]# cd /data/w/
[root@web01 w]# pwd
/data/w
[root@web01 w]# touch bbbback
[root@web01 w]# ll
total 0
‐rw‐r‐‐r‐‐ 1 www www 0 Jul 26 09:22 backup_w
‐rw‐r‐‐r‐‐ 1 www www 0 Jul 26 09:26 bbbback
实现开机自动挂载
[root@web01 ~]# echo "172.16.1.31:/data/r /data/r nfs defaults 0 0" >>/etc/fstab
[root@web01 ~]# echo "172.16.1.31:/data/w /data/w nfs defaults 0 0" >>/etc/fstab
注意: 当将远程挂载设备写入/etc/fstab 文件后,一定要执行 mount ‐a
[root@web01 ~]# mount ‐a
[root@web01 ~]# df ‐h
Filesystem Size Used Avail Use% Mounted on
172.16.1.31:/data/r 50G 1.6G 49G 4% /data/r
172.16.1.31:/data/w 50G 1.6G 49G 4% /data/w
如果编写错误会有如下提示
[root@web01 ~]# mount ‐a
mount.nfs: access denied by server while mounting 172.16.1.31:/data/w
卸载 nfs
正常卸载
[root@web01 ~]# umount /data/w/
强制卸载
[root@web01 ~]#umount ‐lf /data/w/
8.优化设置
suid nosuid |
当挂载的文件系统上有任何SUID的程序时,只要使用nosuid就能够取消设置SUID的功能。(SUID,在linux基础学习篇权限管理里面讲过了) suid |
rw ro |
可以指定文件系统是只读(ro)或可写(rw)。 rw |
dev nodev |
是否可以保留装置文件的特殊功能?一般来说只有/dev才会有特殊的装置,因此可以选择nodev。 dev |
exec noexec |
是否具有执行文件的权限?如果想要挂载的仅是普通资源数据区(例如:图片、附件),那么可以选择noexec。exec |
user nouser |
是否允许用户进行文件的挂载与卸载功能?如果要保护文件系统,最好不要提供用户进行挂载与卸载 nouser |
auto noauto |
这个auto指的是“mount -a”时会不会被挂载的项目,如果不需要这个分区随时被挂载,可以设置为noauto/etc/fstab auto |
rsize wsize |
读出(rsize)与写入(wsize)的区块大小(block size),这个设置值可以影响客户端与服务器端传输数据的缓冲存储量,一般来说,如果在局域网内(LAN),并且客户端与服务器端都具有足够的内存,这个值可以设置大一点,比如说65535(bytes),提升缓冲区块将可提升NFS文件系统的传输能力。但设置的值也不要太大,最好以网络能够传输的最大值为限。 |
NFS内核优化
rmem_default: 为TCP socket预留用于接收缓冲的内存默认值(单位:字节)
rmem_max: 为TCP socket预留用于接收缓冲的内存最大值(单位:字节)
wmem_default: 为TCP socket预留用于发送缓冲的内存默认值( 单位:字节)
wmem_max: 为TCP socket预留用于发送缓冲的内存最大值(单位:字节)
[root@nfs ~]$ head /proc/sys/net/core/[rw]mem_{default,max}
==> /proc/sys/net/core/rmem_default <==
212992
==> /proc/sys/net/core/wmem_default <==
212992
==> /proc/sys/net/core/rmem_max <==
212992
==> /proc/sys/net/core/wmem_max <==
212992
上述文件对应的具体内核优化命令
cat >>/etc/sysctl.conf<<EOF
net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
EOF
执行sysctl -p生效