基于MFS高可用的分布式存储架构

  linux干货
MFS分布式存储系统中角色分类及规划

管理服务器:负责各个数据存储服务器的管理,文件读写调度,文件空间回收以及恢复.多节点拷贝;

元数据日志服务器:负责备份master 服务器的变化日志文件,文件类型为changelog_ml.*.mfs ,以便于在master server 出问题的时候接替其进行工作;

数据存储服务器:负责连接管理服务器,听从管理服务器调度,提供存储空间,并为客户提供数据传输.存储的是数据块或则碎片;

客户机:通过fuse 内核接口挂接远程管理服务器上所管理的数据存储服务器,.看起来共享的文件系统和本地unix 文件系统使用一样的效果。

本次实验架构及相关准备信息(备注:所有系统环境均为centos7.4,请按图表配置好IP与主机名)

基于MFS高可用的分布式存储架构基于MFS高可用的分布式存储架构

MFS体系工作涉及流程分析
MFS的读数据过程

1:client当需要一个数据时,首先向master server发起查询请求;

2:管理服务器检索自己的数据,获取到数据所在的可用数据服务器位置ip|port|chunkid;

3:管理服务器将数据服务器的地址发送给客户端;

4:客户端向具体的数据服务器发起数据获取请求;

5:数据服务器将数据发送给客户端;

MFS的写数据过程

1:当客户端有数据写需求时,首先向管理服务器提供文件元数据信息请求存储地址(元数据信息如:文件名|大小|份数等);

2:管理服务器根据写文件的元数据信息,到数据服务器创建新的数据块;

3:数据服务器返回创建成功的消息;

4:管理服务器将数据服务器的地址返回给客户端(chunkIP|port|chunkid);

5:客户端向数据服务器写数据;

6:数据服务器返回给客户端写成功的消息;

7:客户端将此次写完成结束信号和一些信息发送到管理服务器来更新文件的长度和最后修改时间

MFS的删除文件过程

1:客户端有删除操作时,首先向Master发送删除信息;

2:Master定位到相应元数据信息进行删除,并将chunk server上块的删除操作加入队列异步清理;

3:响应客户端删除成功的信号

MFS修改文件内容的过程

1:客户端有修改文件内容时,首先向Master发送操作信息;

2:Master申请新的块给.swp文件,

3:客户端关闭文件后,会向Master发送关闭信息;

4:Master会检测内容是否有更新,若有,则申请新的块存放更改后的文件,删除原有块和.swp文件块;

5:若无,则直接删除.swp文件块。

MFS重命名文件的过程

1:客户端重命名文件时,会向Master发送操作信息;

2:Master直接修改元数据信息中的文件名;返回重命名完成信息;

MFS遍历文件的过程

1:遍历文件不需要访问chunk server,当有客户端遍历请求时,向Master发送操作信息;

2:Master返回相应元数据信息;

3:客户端接收到信息后显示

注意:

1:Master记录着管理信息,比如:文件路径|大小|存储的位置(ip,port,chunkid)|份数|时间等,元数据信息存在于内存中,会定期写入metadata.mfs.back文件中,定期同步到metalogger,操作实时写入changelog.*.mfs,实时同步到metalogger中。master启动将metadata.mfs载入内存,重命名为metadata.mfs.back文件。

2:文件以chunk大小存储,每chunk最大为64M,小于64M的,该chunk的大小即为该文件大小(验证实际chunk文件略大于实际文件),超过64M的文件将被切分,以每一份(chunk)的大小不超过64M为原则;块的生成遵循规则:目录循环写入(00-FF 256个目录循环,step为2)、chunk文件递增生成、大文件切分目录连续。

3:Chunkserver上的剩余存储空间要大于1GB(Reference Guide有提到),新的数据才会被允许写入,否则,你会看到No space left on device的提示,实际中,测试发现当磁盘使用率达到95%左右的时候,就已经不行写入了,当时可用空间为1.9GB。

4:文件可以有多份copy,当goal为1时,文件会被随机存到一台chunkserver上,当goal的数大于1时,copy会由master调度保存到不同的chunkserver上,goal的大小不要超过chunkserver的数量,否则多出的copy,不会有chunkserver去存。

5:Chunkserver上的剩余存储空间要大于1GB(Reference Guide有提到),新的数据才会被允许写入,否则,你会看到No space left on device的提示,实际中,测试发现当磁盘使用率达到95%左右的时候,就已经不行写入了,当时可用空间为1.9GB

整个MFS高可用架构内,各服务依赖流程

1:keepalived决定了,VIP在那台机器上,

2:有VIP的机器视为drbd的(主)primay角色,需要将/dev/drbd0 挂载到指定位置 /var/lib/mfs,

3:然后启动,mfsmaster服务,并且启用mfscgiser监控服务(web形式提供)

4:(注意:启动mfsmaster时,需要目录里有meta.mfs,不然无法启动,通常其会被改成meta.mfs.back,需要手动改回来,才能启动mfsmaster)

第一阶段:软件部署

在所有主机上添加mfs的官方源

salt "*" cmd.run " yum install epel* bash-c* wget tree -y && yum update -y "
salt "*" cmd.run 'curl "http://ppa.moosefs.com/RPM-GPG-KEY-MooseFS" > /etc/pki/rpm-gpg/RPM-GPG-KEY-MooseFS'
salt "*" cmd.run 'curl "http://ppa.moosefs.com/MooseFS-3-el7.repo" > /etc/yum.repos.d/MooseFS.repo'

在master和slave上安装masterserver服务

salt -L "Master62,Slave63" cmd.run 'yum install moosefs-master moosefs-cgi moosefs-cgiserv moosefs-cli -y'

在chunk上

salt  "chunk6[5-7]" cmd.run 'yum install moosefs-chunkserver -y'

在logger上

salt  "logger64" cmd.run 'yum install moosefs-metalogger -y'

在client上

salt  "client68" cmd.run 'yum install moosefs-client -y'
第二阶段:在master和slave进行drbd资源创建阶段
在master和slave上安装drbd服务
salt  -L "Master62,Slave63" cmd.run 'rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org'
salt  -L "Master62,Slave63" cmd.run 'rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm'
salt  -L "Master62,Slave63" cmd.run 'yum install kmod-drbd84 drbd84-utils -y'
salt  -L "Master62,Slave63" cmd.run "chmod +x /etc/rc.d/rc.local"
salt  -L "Master62,Slave63" cmd.run  'echo "modprobe drbd" >> /etc/rc.local'
salt  -L "Master62,Slave63" cmd.run  'modprobe drbd'
salt  -L "Master62,Slave63" cmd.run "lsmod | grep drbd"

在master和slave上查看sdb的容量,以便如何分区(先不格式化磁盘)
salt  -L "Master62,Slave63" cmd.run "fdisk -l |grep sdb"
salt  -L "Master62,Slave63" cmd.run "parted /dev/sdb mklabel gpt "

#fdisk非交互式分区,分15G的分区出来
salt  -L "Master62,Slave63" cmd.run 'echo -e "n\np\n1\n\n+15G\nw\n" |fdisk /dev/sdb '
salt  -L "Master62,Slave63" cmd.run "parted /dev/sdb p"
salt  -L "Master62,Slave63" cmd.run "fdisk -l |grep sdb"

在master和slave上配置drbd并启动它(两台配置相同)
#在主和从上分别创建drbd资源配置文件
salt  -L "Master62,Slave63" cmd.run "touch /etc/drbd.d/mfs-meta.res"

#drbd资源配置文件内容如下
vi /etc/drbd.d/mfs-meta.res

resource mfs_meta0 {
	protocol C;
	startup { wfc-timeout 0; degr-wfc-timeout 120; }
	disk { on-io-error detach; }
	net {
		timeout 60;
		connect-int 10;
		ping-int 10;
		max-buffers 2048;
		max-epoch-size 2048;
	}
	meta-disk internal;
	device    /dev/drbd0;
	syncer {
		verify-alg sha1;
	}
	on Master62 {
		disk /dev/sdb1;
		address 192.168.1.62:7789;
	}
	on Slave63 {
		disk /dev/sdb1;
		address 192.168.1.63:7789;
	}
 }

#启动drbd(建议将drbd服务加入到开机自启里)
salt  -L "Master62,Slave63" cmd.run "systemctl start drbd.service"
salt  -L "Master62,Slave63" cmd.run "systemctl enable drbd.service"  #开机后会启动所有drbd资源

在master和slave上初始化DRBD
salt  -L "Master62,Slave63" cmd.run "drbdadm create-md mfs_meta0"
salt  -L "Master62,Slave63" cmd.run "drbdadm up mfs_meta0"
salt  -L "Master62,Slave63" cmd.run "cat /proc/drbd "	#正常状态应该是Secondary/Secondary

#将其中一个节点置主(这里在主节点,Master62)
salt  "Master62" cmd.run "drbdadm primary mfs_meta0 --force"

#查看状态,(一主一丛是正常状态)
[root@client68 ~]# salt  -L "Master62,Slave63" cmd.run "cat /proc/drbd "
Slave63:
    version: 8.4.10-1 (api:1/proto:86-101)
    GIT-hash: a4d5de01fffd7e4cde48a080e2c686f9e8cebf4c build by mockbuild@, 2017-09-15 14:23:22
     0: cs:SyncTarget ro:Secondary/Primary ds:Inconsistent/UpToDate C r-----
        ns:0 nr:1380352 dw:1371760 dr:0 al:8 bm:0 lo:30 pe:1 ua:29 ap:0 ep:1 wo:f oos:14356364
    	[>...................] sync'ed:  8.8% (14016/15356)M
    	finish: 0:11:27 speed: 20,880 (18,048) want: 24,720 K/sec
Master62:
    version: 8.4.10-1 (api:1/proto:86-101)
    GIT-hash: a4d5de01fffd7e4cde48a080e2c686f9e8cebf4c build by mockbuild@, 2017-09-15 14:23:22
     0: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r-----
        ns:1381112 nr:0 dw:0 dr:1383240 al:0 bm:0 lo:0 pe:30 ua:0 ap:0 ep:1 wo:f oos:14356364
    	[>...................] sync'ed:  8.8% (14016/15356)M
    	finish: 0:11:27 speed: 20,880 (18,048) K/sec

#只需在(主)Primary上执行格式化
salt  "Master62" cmd.run "mkfs.xfs -b 4096 /dev/drbd0"
第三阶段:配置并启动mfsmaster和mfscgiser,web监控服务
在master和slave上配置并启动metaserver服务
#metaserver的配置文件/etc/mfs/mfsmaster.cfg 完全可以不用修改
#在drbd的主上进行挂载/dev/drbd0设备(/var/lib/mfs是管理机存储元数据的地方)
salt  "Master62" cmd.run "mount /dev/drbd0 /var/lib/mfs "

#不修改为mfsmaster程序的用户mfs可能无法创建文件,导致无法启动mfsmaster
salt  -L "Master62,Slave63" cmd.run "chown mfs:mfs /var/lib/mfs/ -R"
salt  -L "Master62,Slave63" cmd.run "systemctl start moosefs-master.service "

#配置本地hosts解析(因为web监控会调用mfsmaster解析到ip,当然每次手动输入也可以)
salt  -L "Master62,Slave63" cmd.run 'echo "192.168.1.61	 mfsmaster" >> /etc/hosts '

#在主上启用监控(会监控9425端口,用浏览器可以查看 http://192.168.1.61:9425)
salt  "Master62" cmd.run "systemctl start moosefs-cgiserv.service"
第四阶段:安装并配置keepalived
在master和slave上安装keepalived服务
salt  -L "Master62,Slave63" cmd.run "yum install keepalived -y"

在master和slave上配置keepalived(参看每行注释,back的配置只有两点"state,priority"不一样)
[root@Master62 ~]# cat /etc/keepalived/keepalived.conf

global_defs {
   notification_email {
     root@wsfnk.com		#设置邮件报警地址,可以设置多个,每行一个
   }
   notification_email_from 123@wsfnk.com #设置邮件的发送地址
   smtp_server 192.168.200.1		 #设置smtp server
   smtp_connect_timeout 30		 #设置连接smtp server的超时时间
   router_id LVS_DEVEL			 #表示运行keepalived服务器的一个标示,发送邮件时显示在邮件主题中的信息
   vrrp_skip_check_adv_addr
   #vrrp_strict				 #注意:当你发现无法ping通虚拟VIP时,建议将此行注释掉
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}
#定义一个检查mfsmaster的脚本
vrrp_script chk_mfsmaster {
	script "/etc/keepalived/keepalived_drbd_mfs.sh check"
	#这个脚本,若是发现不执行,可以检查他的权限,777是不可以的,日志提示不安全,可以直接chmod +x /etc/keepalived/keepalived_drbd_mfs.sh 就行
	#script "shutdown -r now"	#或者,直接用命令进行调试
	interval 2
	weight 2
}
#vrrp实例定义部分
vrrp_instance VI_1 {
    state MASTER	#指定角色为主MASTER,备为BACKUP
    interface ens192	#指定HA监测网络的接口,接口名字要与系统一致(建议监测口独立)
    virtual_router_id 51  #虚拟路由标示,这个标示是一个数字,同一个vrrp实例使用唯一的标示
    priority 100	#主权值必须设得比 back 高,数字越大越高
    advert_int 1	#设定keepalived-master与备节点的心跳间隔时间,单位是秒
    authentication {	#设置验证类型和密码
        auth_type PASS	#设置验证类型,由PASS与HA两种
        auth_pass 1111	#设置验证密码,同一vrrp实例下,keepalived-master与backup节点必须使用相同的密码才能正常通信
    }
    virtual_ipaddress {	#设置虚拟ip,可以设置多个虚拟的vip,每行一个
        192.168.1.61/24 dev ens192
    }
    track_script {	#调用上面定义检查mfsmaster的脚本
        chk_mfsmaster
    }
    notify_master "/etc/keepalived/keepalived_drbd_mfs.sh master"  #表示当切换到master状态时,要执行的脚本
    notify_backup "/etc/keepalived/keepalived_drbd_mfs.sh backup"  #表示当切换到backup状态时,要执行的脚本
    notify_fault "/etc/keepalived/keepalived_drbd_mfs.sh fault"	#表示切换出现故障时要执行的脚本
    notify_stop "/etc/keepalived/keepalived_drbd_mfs.sh fault"	#停止前,执行的
}

在master和slave上启动keepalived服务
salt  -L "Master62,Slave63" cmd.run "systemctl start keepalived "

第五阶段:配置(metalogger)元数据日志服务器(这个角色可以在任何机器上运行,可以远程备份)
配置(metalogger)元数据日志服务器(这个角色可以在任何机器上运行,可以远程备份)(可以后来才添加,也能保持元数据一致性)
#修改目录权限
salt  "metalogger64" cmd.run "chown mfs:mfs /var/lib/mfs -R "

#很简单,只需要,修改到mfsmaster的ip地址就可以了
vi mfsmetalogger.cfg

MASTER_HOST = 192.168.1.64	#指定mfsmaster的主机地址

#启动,并开机启动metalogger服务
salt  "metalogger64" cmd.run "systemctl start moosefs-metalogger"
salt  "metalogger64" cmd.run "systemctl enable moosefs-metalogger"

#查看同步过来的文件/var/lib/mfs/metadata_ml.mfs.back是否与mfsmaster上的/var/lib/mfs/metadata.mfs.back相同(结果相同)
第六阶段:配置并启动后端存储服务器chunk
配置chunk服务器
#创建数据存放目录并修改目录所有者(mfs用户,在用yum 安装mfs套件时已经自动创建)
salt  -L "chunk65,chunk66,chunk67" cmd.run "mkdir /data"
salt  -L "chunk65,chunk66,chunk67" cmd.run "chown mfs:mfs /data"

vi /etc/mfs/mfschunkserver.cfg

MASTER_HOST = 192.168.1.61		#master的ip地址
HDD_CONF_FILENAME = /etc/mfs/mfshdd.cfg
CSSERV_LISTEN_PORT = 9422		#这个端口用于与其他chunk服务器进行连接,通常是数据复制

vi /etc/mfs/mfshdd.cfg

/data		#指定数据碎片存储的真实路径(可以是目录,磁盘等)

#启动
salt  -L "chunk65,chunk66,chunk67" cmd.run "systemctl enable moosefs-chunkserver.service"
salt  -L "chunk65,chunk66,chunk67" cmd.run "systemctl start moosefs-chunkserver.service"	

#验证:会在chunk的/data目录里创建00-FF个目录用于存放碎片文件
salt  -L "chunk65,chunk66,chunk67" cmd.run "tree /data"
第七阶段:配置客户端
#确保客户端机器内核有fuse模块(若是没有:用 modprobe fuse 进行加载)
#当然:我发现若是之前没有加载fuse模块时,运行下面的挂载命令,该模块会被自动加载(此步骤可忽略)
lsmod | grep fuse

#创建一个挂载点(这个挂载点,或则目录里不能有任何文件,否在会挂载失败)
mkdir /data

#执行挂载(进入目录 cd /data 后,就可以像操作本地数据一样进行操作了)
mfsmount -H 192.168.1.61 /data
(附)第八阶段:编写keepalived控制drbd和mfs的监控脚本
#这是我写的监控脚本,(这里的脚本,只能实现,在master和slave上的drbd开机自启动后,master上启动keepalived后能自动完成各种监测,并成功启动mfsmaster,但是slave上无法实现检查,当master故障后slave自动切换会失败)有待完善
wget https://qiniu.wsfnk.com/keepalived_drbd_mfs.sh
mv keepalived_drbd_mfs.sh /etc/keepalived/
chmod +x /etc/keepalived/keepalived_drbd_mfs.sh
(附)问题一:多client挂载,会有数据不一致的情况发生么

答:不会,原因:参看MFS的工作原理流程分析

(附)问题二:假比chunk有三台,挂了一台,新加入一台,原本的数据副本数为2,那么必然部分数据的副本数会降为1,请问如何恢复降低副本数的副本份数,以保障数据的可靠性
(附)问题三:整个架构,启动与停止顺序
正常启动顺序:matser >> chunk >> metalogger >> client
正常关闭顺序:client >> chunk >> metalogger >> master
master主机上:drbd资源启动 >> drbd资源置主 >> 挂载drbd到指定目录 >> 启动mfsmaster和mfscgiser >> 启动keepalived掌管VIP
slave备机上:drbd资源启动 >> drbd资源置从 >> 启动keepalived监测master主机是否故障
(附)问题四:drbd脑裂情况及其处理方法(注意:只有当状态为Primary的一方,才可以挂载磁盘)
正常状态:
1:role=Primary/Secondary	cstate=Connected  UpToDate/UpToDate	#这是正常工作状态,一主一丛,连接状态,数据最新
2:role=Secondary/Secondary   cstate=Connected  UpToDate/UpToDate	#这是drbd资源刚刚启动阶段,默认都是为从,只需将一端手动置主即可
故障状态分类
#故障原因:可能是由于主drbd服务器,网络出现故障(如网卡down了等),备服务器处于正常状态
3:(主上)role=Primary/Unknown	cstate=StandAlone  UpToDate/DUnkown	#表示网络配置不可用,资源还没有被连接或者是被管理断开
3:(备上)role=Secondary/Unknown  cstate=WFConnection  UpToDate/DUnkown	#等待对端节点恢复.
#解决办法:将主drbd的网络故障排除后,在主上执行连接命令 drbdadm connect mfs_meta0 (或则,将备drbd置主,下线主)

#故障原因:可能是由于备drbd服务器,网络出现故障,主处于正常
4:(主上)role=Primary/Unknown	cstate=WFConnection  UpToDate/DUnkown	#等待对端节点恢复.
4:(备上)role=Secondary/Unknown  cstate=StandAlone  UpToDate/DUnkown	#表示网络配置不可用,资源还没有被连接或者是被管理断开

#解决办法:
(1)可以不做处理,因为主是正常的,
(2)当然也可以在排除备机网络故障后,在备上重新连接 drbdadm connect mfs_meta0;(放弃本地数据进行连接)drbdadm connect --discard-my-data mfs_meta0

#故障原因:原因不明,主备都出现故障
5:(主上)role=Primary/Unknown	cstate=StandAlone  UpToDate/DUnkown	#表示网络配置不可用,资源还没有被连接或者是被管理断开
5:(备上)role=Secondary/Unknown  cstate=StandAlone  UpToDate/DUnkown	#表示网络配置不可用,资源还没有被连接或者是被管理断开

解决办法:
A:先要排除主备机器的网络故障
B:在备上
drbdadm disconnect mfs_meta0
drbdadm secondary mfs_meta0
drbdadm connect --discard-my-data mfs_meta0	#放弃本地数据进行连接

C:在主上
drbdadm connect mfs_meta0

D:验证是否正常
(附)问题五:如何修复因断电导致的master可能无法启动的情况
#需要最后一个元数据日志changelog 并入主要的metadata 中。这个操作时通过 mfsmetarestore 工具做的
#先修复(几次测试发现:如果mfsmetarestore -a无法修复,则使用metalogger也无法修复)
mfsmetarestore -a

#如果master 数据被存储在MooseFS 编译指定地点外的路径,则要利用-d 参数指定使用,如:
mfsmetarestore -a -d /opt/mfsmaster

#再启动(才能成功)

#强制使用metadata.mfs.back创建metadata.mfs,可以启动master,但应该会丢失1小时的数据。
#明确表示会丢失故障点到上一个整点之间的数据。和之前我猜测的一致。因为对mfs的操作日志都记录到changelog.0.mfs里面。changelog.0.mfs每小时合并一次到metadata.mfs中,如果突然断电,则changelog.0.mfs里面的信息就没有合并到metadata中,强制使用metadata.mfs.back创建metadata.mfs,就会导致丢失changelog.0.mfs里的数据。