NFS详解
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
张贺,多年互联网行业工作经验,担任过网络工程师、系统集成工程师、LINUX系统运维工程师
个人网站:www.zhanghehe.cn
笔者微信:zhanghe15069028807,现居济南历下区
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
一、概念
1、为什么用存储?
当我们访问WEB服务的时候,比如淘宝,淘宝的后台肯定不只有一台服务器,我们无论在什么地方登录,看到的界面都是一样的,虽然我们在不同的地区登录,访问的服务器也不是一个,但是这些服务器用的存储都是一个。
一致性,当卖家删除了一件商品时,所有的买家都不应该再看到这个商品,不能山东的用户不能看到这个商品,但是山西的用户却能看到,而存储服务器必须通过共享才能实现数据的一致性。
成本,一台WEB服务器,其实不需要太大的硬件空间,为什么?WEB服务器存的是代码,而代码是文本文本,文本文件占用的空间比较小,像淘宝的WEB前端的代码也不会超过100M,阿里云默认的WEB服务器自带也就40G硬盘,这完全足够使用了,我们不需要再另行增加,我们只需要做存储的那一台服务器有大硬盘空间就可以了,其余的WEB前端服务器都是读取的存储服务器。
2、最重要的是什么?
对于一个大型网站,存储的作用是共享,而不是加速,那么网站的加速靠什么?靠CDN
CDN的全称是Content Delivery Network,即内容分发网络,CDN是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术
对于一个网站页面来说,存储的最大作用是用来共享的,对速度的增加实有限,速度问题最终要靠CDN解决,通常是这样的,前面WEB服务器将共享存储挂载到本地,存储又通过rsync的同步功能将数据推送到备份服务器,然后备份服务器再将内容推送到CDN。
CDN上存储的是静态的内容,比如电视剧、电影、图片这些,一般不会轻易更改的,当用户向网站写入内容的时候,访问的是真实提供服务的服务器, 写入的数据会先写到存储上,然后存储再推到CDN上;当用户读取网站的图片、文字的时候,其实读取的并不是提供服务的服务器上面的内容,而是CDN上面的内容,这样减少了服务器的压力。稍有规模的网站一般都使用了CDN加速。
3、专业存储服务器
什么时候使用专业的存储服务器取决于数据量的多少和数据的重要性。
假设说你公司有1T的的数据,有没有必要使用专业的存储呢?没有必要,我们只需要买一台服务器充当存储服务器即可。
专业的存储与服务器充当的存储有什么区别?
专业的存储服务器就是在服务器充当的存储之上再次改进的产物,这个改进包括和硬件和软件两个方面。比如专业的存储比服务器充当的存储能挂更多的硬盘,有一些新的技术,操作上更为简单,服务上更加周到,任意的存储厂商无论他们的宣传手册、营销手段好花里胡哨,其实这些设备的本质都是一样的,LINUX系统+开源软件+前端WEB界面+号称自研的软件。
二、NFS
1、NFS原理
NFS是什么?是网络文件系统,好吧,说白了,他就是一个基础网络的软件,用来共享的。
为什么用NFS?因为方便,具体原因请看上文。
怎么用?这一章节就是讲这玩意儿怎么用。
本地文件操作-本地系统调用:
当我们在系统之上创建一个文件夹的时候,其实硬件是无法识别这样的操作,是shell将这样的操作翻译成系统能理解的二进制,然后告诉内核,内核通过驱动程序才能驱动硬盘,在硬盘上创建一个文件夹,然后由内核再返回结果,这里面涉及到用户空间转换到内核空间的过程。
NFS访问流程:
-
当我们在NFS客户端上执行一个操作时,请求先交给NFS客户端。
-
NFS客户端会将这些操作封装成一个函数(通过上图,我们看到这个函数包括读、写、创建、移动、改名)
-
再然后交给内核,但内核这时不会直接驱动硬盘了,而是会驱动tcp/ip协议栈,将封装好函数通过网络交给NFS服务端。
-
函数到达NFS服务器的内核时,首先到达的还是TCP/IP协议线,然后内核再交给服务端的BASH执行,进行本地系统调用 。
主机与主机之间是通过tcp/ip协议、NFS协议、rpc协议三者结合进行的跨主机远程过程调用,这就要求rpc协议必须先运行起来,然后NFS协议才能和PRC结合起来,至于tcp/ip协议就不用我们操作了,它会一直运行在内核当中,它是内核的一部分。
NFS的原理:
NFS服务端并不会直接对外提供服务,默认不会侦听任何固定的套接字,那它是怎样给用户提供服务的呢?它需要RPC程序的配合,RPC服务侦听固定的套接字:111端口,客户端访问服务端的时候,目的端口刚开始是111,连接的RPC进程,RPC进程收到用户的请求之后,会“告诉”NFS服务,有人来连接了,这个时候NFS服务才会临时生成一个进程,让这个进程侦听在2049这个端口上,RPC服务会把NFS进程侦听在2049这个消息告诉客户端,客户端会重新发起连接,这时的目的端口就是2049了,如果再有客户端再连接NFS服务商,它还是会临时再生成一个进程,再侦听在2050端口上,RPC再告诉客户端连接2050.
上述只是连接的部分,还没有结束呢?连接完成之后,服务端还有两个进程需要对客户端的请求做检查,rpc-mount进程和rpc-nfsd进程,nfsd进程检查用户的IP是否允许连接NFS服务,mount进程检查用户连接了NFS服务之后可以对目录做什么权限,也就是说mount进程会根据/etc/exports文件对客户端的请求做检查。
2、 项目案例
NFS客户端 | 192.168.80.166 |
---|---|
NFS服务器 | 192.168.80.200 |
需求:
将NFS服务端的/data目录共享给192.168.80.0网段内的所有主机
在将数据写入到NFS服务器的硬盘中后才会结合操作,最大限度保证数据的不丢失
将所有用户映射为本地的匿名用户(nfsnoby)
服务端
NFS要依赖于rpc协议进行函数的封装和数据的传输,所以在安装NFS包之前要先安装RPC包,RPC相当于中介,NFS相当于房子,要先有中介,然后房源才能找到中介进行登记注册。在centos6的时候,确实是这样,要一起安装两个包,但是在centos7这里,我们就可以只安装NFS,RPC做为NFS的依赖自动安装,并自动启动,自动加入开机启动,也就是说,我们在centos7系统上面,完全不用理会RPC,它一切都是自动的,我们要需要安装NFS,启动,加入到开机启动即可。
[root@NFS-SERVER ~]# yum erase nfs-utils
root@NFS-SERVER ~]# rpm -q nfs-utils
package nfs-utils is not installed
[root@NFS-SERVER ~]# yum list | grep '^nfs'
nfs-utils.x86_64 1:1.3.0-0.65.el7 base
nfs4-acl-tools.x86_64 0.3.3-20.el7 base
nfsometer.noarch 1.7-1.el7 base
nfstest.noarch 2.1.5-1.el7 base
[root@NFS-SERVER ~]# yum -y install nfs-utils
[root@NFS-SERVER ~]# systemctl is-active nfs-server
active
[root@NFS-SERVER ~]# systemctl status nfs-server
● nfs-server.service - NFS server and services
Loaded: loaded (/usr/lib/systemd/system/nfs-server.service; enabled; vendor preset: disabled)
Active: active (exited) since Thu 2019-10-31 09:53:29 CST; 20s ago
Main PID: 20402 (code=exited, status=0/SUCCESS)
CGroup: /system.slice/nfs-server.service
[root@NFS-SERVER ~]# systemctl status rpcbind #自动就运行了,不用我们管。
● rpcbind.service - RPC bind service
Loaded: loaded (/usr/lib/systemd/system/rpcbind.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2019-10-31 08:23:27 CST; 1h 31min ago
Main PID: 8350 (rpcbind)
CGroup: /system.slice/rpcbind.service
└─8350 /sbin/rpcbind -w
[root@NFS-SERVER ~]# rpm -qc nfs-utils #NFS的配置文件在这里并不会显示,/etc/expors才是NFS的配置文件。
/etc/gssproxy/24-nfs-server.conf
/etc/modprobe.d/lockd.conf
/etc/nfs.conf
/etc/nfsmount.conf
/etc/request-key.d/id_resolver.conf
/etc/sysconfig/nfs
/var/lib/nfs/etab
/var/lib/nfs/rmtab
/var/lib/nfs/state
/var/lib/nfs/xtab
[root@NFS-SERVER ~]# cat /etc/exports
#语法相当简单,共享哪个目录?data,共享给谁?192.168.80.0这上网段,权限是啥(rw,rsync,all_squash)
/data 192.168.80.0/24(rw,rsync,all_squash)
[root@NFS-SERVER ~]# systemctl restart nfs-server
[root@NFS-SERVER ~]# rpm -ql nfs-utils | grep "etab"
/var/lib/nfs/etab
[root@NFS-SERVER ~]# cat /var/lib/nfs/etab
#如果/var/lib/nfs/etab这个文件里面有内容说明配置正确了,如果不正常说明不正确,现在没有内容,那错在哪里了呢?
#/data文件还没有创建呢?创建一下
[root@NFS-SERVER ~]# mkdir /data
[root@NFS-SERVER ~]# systemctl restart nfs-server
[root@NFS-SERVER ~]# cat /var/lib/nfs/etab #创建了之后还是没有内容
#这里面有一个坑,注意啊,我们在学rsync的时候,rsync这个单词已经写习惯了,配置文件里面是sync,而不是rsync!
[root@NFS-SERVER ~]# cat /etc/exports
/data 192.168.80.0/24(rw,sync,all_squash)
[root@NFS-SERVER ~]# systemctl restart nfs-server
[root@NFS-SERVER ~]# cat /var/lib/nfs/etab #再次查看,里面就有内容了。
/data 192.168.80.0/24
(rw,sync,wdelay,hide,nocrossmnt,secure,root_squash,all_squash,
no_subtree_check,secure_locks,acl,no_pnfs,anonuid=65534,anongid=65534,sec=sys,rw,secure,root_squash,all_squash)
请注意/var/lib/nfs/etab这个文件,这个文件里面是啥呢?就是NFS启动的时候对外输出的内容,通过上面的内容我们可以看到当前NFS服务是以65534这个用户来来运行的,那么这个用户是谁呢?
[root@NFS-SERVER ~]# cat /etc/passwd | grep 65534
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
通过上面的内容,我们知道了,NFS服务是nfsnobody这个用户运行的。
解释一下all_squash这个参数的作用,我们看一下NFS这个服务当前是谁在运行?如下所示:
[root@NFS-SERVER ~]# ps aux | grep nfs
root 21380 0.0 0.0 0 0 ? S< 10:25 0:00 [nfsd4_callbacks]
root 21386 0.0 0.0 0 0 ? S 10:25 0:00 [nfsd]
root 21387 0.0 0.0 0 0 ? S 10:25 0:00 [nfsd]
root 21388 0.0 0.0 0 0 ? S 10:25 0:00 [nfsd]
root 21389 0.0 0.0 0 0 ? S 10:25 0:00 [nfsd]
root 21390 0.0 0.0 0 0 ? S 10:25 0:00 [nfsd]
root 21391 0.0 0.0 0 0 ? S 10:25 0:00 [nfsd]
root 21392 0.0 0.0 0 0 ? S 10:25 0:00 [nfsd]
root 21393 0.0 0.0 0 0 ? S 10:25 0:00 [nfsd]
root 21560 0.0 0.0 112708 976 pts/1 S+ 10:38 0:00 grep --color=auto nfs
当前正是root在运行,我们在参数里面加了all_aquash之后,NFS的运行者实际上还是root,但是当NFS向/data目录里面写入东西的时候,用的则是nfsnobody用户,但是你看一看当前/data目录的权限是啥?如下所示:
[root@NFS-SERVER ~]# ll -d /data
drwxr-xr-x 2 root root 6 Oct 31 10:05 /data
data目录的所有人和所属组都是root,所以等会客户端挂载完成之后是无法写入的,但这里面我们先不改,等到报了错,我们看一下是什么错误,然后再回来更改。
客户端
客户端必须RPC服务,才能发起连接,干脆,我们也安装nfs服务。
[root@NFS-client ~]# yum -y install nfs-utils
[root@NFS-client ~]# mkdir /nfs
[root@NFS-client ~]# showmount -e 192.168.80.200 #查看服务提供了哪些共享目录
Export list for 192.168.80.200:
/data 192.168.80.0/24
[root@NFS-client ~]# mount -t nfs 192.168.80.200:/data /nfs
root@NFS-client nfs]# touch client.txt #写入一个文件却报错,怎么回事?
touch: cannot touch ‘client.txt’: Permission denied
[root@NFS-SERVER ~]# chown nfsnobody:nfsnobody /data
[root@NFS-client nfs]# touch client.txt #成功写入,无报错
[root@NFS-client nfs]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos_centos7-root 50G 4.1G 46G 9% /
devtmpfs 1.6G 4.0K 1.6G 1% /dev
tmpfs 1.6G 0 1.6G 0% /dev/shm
tmpfs 1.6G 12M 1.6G 1% /run
tmpfs 1.6G 0 1.6G 0% /sys/fs/cgroup
/dev/sda1 1014M 179M 836M 18% /boot
/dev/mapper/centos_centos7-home 446G 39M 446G 1% /home
tmpfs 325M 0 325M 0% /run/user/0
192.168.80.200:/data 50G 4.1G 46G 9% /nfs #在这里
[root@NFS-client nfs]# nfsiostat #查看NFS的IO占用,不使用时为空
mount -t nfs 172.16.1.31:/data /data
指定类型 挂载什么 挂在什么地方
三、问题
1、自动挂载
客户端写入/etc/fstab文件即可,格式如下:
172.16.1.31:data /opt nfs default 0 0
2、客户端挂载失败,无法重启
rd.break
ctrl+x进入救援模式
mount -o remount.rw /sysroot/
chroot /sysroot
编辑fstab,删除一行
退出去
reboot
不重启客户端如何验证客户端的永久挂载是否正确呢?
mount -a
a是aoto是自动挂载的意思测试一下,不报错就不会出问题,卡住了就是错了,不要等着重启才发现出错,那就太晚了。
mount等于cat /proc/mounts这个文件
mount -a等于执行一下/etc/fstab这个文件
无需重启NFS,平滑加载配置文件exports -rv
3、强制卸载
如果NFS服务端挂了,在客户端正常卸载不掉的情况下,可以使用强制卸载。
umount -lf /nfsddir
4、安全性
通常NFS服务共享的只是普通的静态数据:图片、附件、视频,不需要执行suid、exec等权限,挂载的这个文件系统只能作为数据存取之用,无法执行程序,对于客户端来讲增加了安全性,例如很多木马篡改站点都是用上传入口上传的程序到存储目录,然后执行的。
//通过mount -o 指定挂载参数,禁止使用suid和exec,增加安全指数
mount -t nfs -oo nosuid,noexec,nodev 172.16.1.31/data /opt
5、性能
//通过mount -o指定挂载参数,禁止更新目录及文件时间戳
mount -t nfs -o noatime,nodiratime 172.16.1.31:data /opt
通过mount -lf 可以进行强制卸载
6、建议
为了NFS存储与前端的WEB程序统一用户,通常NFS的写入权限应当于nginx的运行用户保持一致。也就是说当我们在exports文件里面要进行权限的压缩,把写入的权限压缩成运行nginx的用户。
groupadd -g 666 www
useradd -g 666 -u 666 -M -s /sbin/nologin www
vim /etc/exports
/data 192.168.80.0/24(rw,all_squash,anonuid=666,anongid=666)
四、小结
NFS存储优点
-
NFS文件系统简单易用、方便部署,数据可靠,服务稳定,满足中小企业需求
-
NFS文件系统内存放的数据都在文件系统之上,所有数据都是可见的。
NFS存储局限
-
存在单点故障,构建高可用维护麻烦web---nfs---backup
-
NFS数据明文,没有校验
-
客户端挂载没有密码,安全性一般(也就内网使用)
NFS应用建议
-
生产场景应用将静态数据尽可能向前推送,减少后端存储的压力
-
必须将存储的静态资源通过CDN缓存jpg/png/mp4/avi/css/js
-
如果没有缓存,存储再多对网站的速度也没有太大帮助
大小问题
当我们在WEB上挂载了NFS共享的/data目录之后,查看一下,我们发现/data的大小是50G,为什么是50G,我们难道共享了一个目录就一下子共享了50G吗?其实就是这样的,你想呀,我们在/data的根下创建了目录,那这个目录是多大?我们在创建目录的时候也不能指定这个目录最大能到多少G,这就是和我们在windows上创建一个文件夹一样,这个文件夹最终能变大取决于该文件夹所在的分区有多大,在NFS上/data是在根所有的分区上创建的,理论上NFS的根最大能变多大,/data目录就能变多大。
[root@Web01 html]# df -h
Filesystem Size Used Avail Use% Mounted on
192.168.80.221:/data 50G 4.0G 47G 8% /var/www/html
我们在NFS上查看一下根的大小,发现根就是50G,这下你明白了吧!
[root@Nfs ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 50G 4.0G 47G 8% /