#################################################################
开篇引题
Distributed Replicated Block Device
部署MFS
部署Corosync+Pacemaker
故障模拟测试
补充和总结
#################################################################
开篇引题
直接上图,有图有真相啊!此图是MFS网络组成和运行原理,先不说图中每种角色的作用(下文会有详细说明),直观信息告诉我们客户端无论是读写请求都需要与MasterServer通信,而图中MasterServer角色只有一个,因此单点故障的因素就显而易见了。解决MFS的单点故障正是本文的初衷,接下来就介绍如何利用多种技术解决MFS的单点故障,实现MasterServer的高可用。
Distributed Replicated Block Device
分布式复制块设备是Linux内核的存储层中的一个分布式存储系统,可利用DRBD在两台Linux服务器之间共享块设备、文件系统和数据,类似于一个网络RAID1的功能,内核中的DRBD模块监听特定套接字上,复制系统调用产生的写数据为副本并通过TCP协议发送至DRBD从节点,因为节点间磁盘设备每一个数据位都是相同的,所以DRBD可以实现廉价块级别的数据共享。
DRBD工作模型
主从模型(primary/secondary),同一时刻只能有一个节点提供服务(否则会产生脑裂),从节点无法使用磁盘分区(挂载也不可以)。
主主模型(primary/primary),需要借助于集群文件系统并启用分布式文件锁功能,而且写性能不会有提升.
DRBD管理
内核模块:drbd用户空间
管理工具:drbdadm,drbdsetup,drbdmeta
工作流程(默认模型是Sync)
Async:副本交于本地TCP/IP协议栈就返回(性能最高)
SemiSync:副本交对方TCP/IP协议栈就返回(折中方案)
Sync:副本被secondary存储到磁盘中就返回(性能差)
安装配置DRBD(drbd内核模块必须和内核版本完全匹配)
rpm -ivh drbd-8.4.3-33.el6.x86_64.rpm drbd-kmdl-2.6.32-358.el6-8.4.3-33.el6.x86_64.rpm
主配置文件
[root@one packages]# cat /etc/drbd.conf # You can find an example in /usr/share/doc/drbd.../drbd.conf.example include "drbd.d/global_common.conf"; include "drbd.d/*.res";
全局配置文件
cat /etc/drbd.d/global_common.conf global { usage-count yes; # minor-count dialog-refresh disable-ip-verification } common { handlers { pri-on-incon-degr "/usr/lib/drbd/notify-pri-on-incon-degr.sh; /usr/lib/drbd/notify-emergency-reboot.sh; echo b > /proc/sysrq-trigger ; reboot -f"; pri-lost-after-sb "/usr/lib/drbd/notify-pri-lost-after-sb.sh; /usr/lib/drbd/notify-emergency-reboot.sh; echo b > /proc/sysrq-trigger ; reboot -f"; local-io-error "/usr/lib/drbd/notify-io-error.sh; /usr/lib/drbd/notify-emergency-shutdown.sh; echo o > /proc/sysrq-trigger ; halt -f"; # fence-peer "/usr/lib/drbd/crm-fence-peer.sh"; # split-brain "/usr/lib/drbd/notify-split-brain.sh root"; # out-of-sync "/usr/lib/drbd/notify-out-of-sync.sh root"; # before-resync-target "/usr/lib/drbd/snapshot-resync-target-lvm.sh -p 15 -- -c 16k"; # after-resync-target /usr/lib/drbd/unsnapshot-resync-target-lvm.sh; } startup { # wfc-timeout degr-wfc-timeout outdated-wfc-timeout wait-after-sb } options { # cpu-mask on-no-data-accessible } disk { on-io-error detach; # size max-bio-bvecs on-io-error fencing disk-barrier disk-flushes # disk-drain md-flushes resync-rate resync-after al-extents # c-plan-ahead c-delay-target c-fill-target c-max-rate # c-min-rate disk-timeout } net { cram-hmac-alg "sha1"; shared-secret "soulboy"; # protocol timeout max-epoch-size max-buffers unplug-watermark # connect-int ping-int sndbuf-size rcvbuf-size ko-count # allow-two-primaries cram-hmac-alg shared-secret after-sb-0pri # after-sb-1pri after-sb-2pri always-asbp rr-conflict # ping-timeout data-integrity-alg tcp-cork on-congestion # congestion-fill congestion-extents csums-alg verify-alg # use-rle } syncer { rate 1000M; } }
定义资源mfs
[root@one packages]# cat /etc/drbd.d/mydata.res resource mydata { on one.soulboy.com { device /dev/drbd0; disk /dev/sdb2; #大小要一致 address 192.168.1.61:7789; meta-disk internal; } on two.soulboy.com { device /dev/drbd0; disk /dev/sdb1; #大小要一致 address 192.168.1.62:7789; meta-disk internal; } } resource mfs { on one.soulboy.com { device /dev/drbd1; disk /dev/sdb3; address 192.168.1.61:7788; meta-disk internal; } on two.soulboy.com { device /dev/drbd1; disk /dev/sdb2; address 192.168.1.62:7788; meta-disk internal; } }
同步配置文件到从节点
scp /etc/drbd.d/* two.soulboy.com:/etc/drbd.d/
初始化资源(分别在两个节点上执行)
drbdadm create-md mfs
启动资源(分别在两个节点上执行)
service drbd start
将某节点变为主节点(192.168.1.61为主节点)
drbdadm primary --force mydata
查看状态确定同步完毕
[root@one packages]# service drbd status 1:mfs Connected Primary/Secondary UpToDate/UpToDate C /mfs ext4
格式化文件系统(在主节点)
mke2fs -t ext4 /dev/drbd1
允许对方抢占(分别在两节点上执行)
drbdadm primary mfs
开机不要自动启动
chkconfig drbd off
部署MFS
MFS工作原理
MFS文件系统能够实现RAID功能,节约成本,不逊色于专业的存储系统,可以实现在线扩容。
MFS的四种角色
MasterServer(元数据服务器):负责管理各个ChunkServer及调度文件读写,回收文件空间及恢复多节点拷贝。
Metalogger(元数据日志服务器):负责备份管理服务器的变化日志文件。
ChunkServer(数据存储服务器):真正存储用户数据的服务器,将文件切块相互同步,听从MasterServer的调度为Client提供数据传输,Chunk节点数量越多,可靠性和MFS可用的磁盘空间就会越大。
Client(客户端):客户端通过fuse内核接口远程管理服务器上所管理的数据存储服务器,和使用本地文件系统一样。
安装配置元数据服务
mount /dev/drbd1 /mfs #挂载drbd设备 groupadd -g 1000 mfs #两边节点的uid要统一 useradd -u 1000 -g mfs -s /sbin/nologin mfs #两边节点都需要创建 mkdir -pv /mfs #主节点创建数据目录即可 chown -R mfs.mfs /mfs #两个节点修改目录属主和属组为mfs tar xf mfs-1.6.26.tar.gz cd mfs-1.6.26 ./configure --prefix=/mfs --with-default-user=mfs --with-default-group=mfs make && make install cp /mfs/etc/mfsmaster.cfg.dist /mfs/etc/mfsmaster.cfg cp /mfs/etc/mfsexports.cfg.dist /mfs/etc/mfsexports.cfg cp /mfs/var/mfs/metadata.mfs.empty /mfs/var/mfs/metadata.mfs
主配置文件
vim /mfs/etc/mfsmaster.cfg # WORKING_USER = mfs #运行用户 # WORKING_GROUP = mfs #运行组 # SYSLOG_IDENT = mfsmaster #在syslog中标识自己 # LOCK_MEMORY = 0 #是否执行mlockall()以避免mfsmaster进程溢出(默认为0) # NICE_LEVEL = -19 #运行的优先级 # EXPORTS_FILENAME = /usr/local/mfs/etc/mfsexports.cfg #目录控制文件路径 # TOPOLOGY_FILENAME = /usr/local/mfs/etc/mfstopology.cfg #拓扑类型文件路径 # DATA_PATH = /usr/local/mfs/var/mfs #数据存放路径(changelog,sessions,stats) # BACK_LOGS = 50 #元数据的改变日志文件数量 # BACK_META_KEEP_PREVIOUS = 1 # # REPLICATIONS_DELAY_INIT = 300 #延迟复制时间(300秒) # REPLICATIONS_DELAY_DISCONNECT = 3600 #ChunkServer断开复制的延迟 # MATOML_LISTEN_HOST = * #元数据日志服务器监听的IP地址(*代表任何IP) # MATOML_LISTEN_PORT = 9419 #元数据日志服务器监听的端口地址(9419) # MATOCS_LISTEN_HOST = * #用于ChunkServer连接的IP地址(*代表任何IP) # MATOCS_LISTEN_PORT = 9420 #用于ChunkServer连接的端口(9420) # MATOCL_LISTEN_HOST = * #用于客户端连接的地址 # MATOCL_LISTEN_PORT = 9421 #用于客户端连接的端口 # CHUNKS_LOOP_CPS = 100000 # CHUNKS_LOOP_TIME = 300 #Chunks回环频率 # CHUNKS_SOFT_DEL_LIMIT = 10 # CHUNKS_HARD_DEL_LIMIT = 25 # CHUNKS_WRITE_REP_LIMIT = 2 #在一个循环里复制到一个ChunkServer的最大Chunks数目 # CHUNKS_READ_REP_LIMIT = 10 # REJECT_OLD_CLIENTS = 0 #弹出低于1.6.0客户端的连接
目录挂载控制文件
vim /mfs/etc/mfsexports.cfg #分为三个部分,无需修改 * . rw * / rw,alldirs,maproot=0 客户端IP 被挂载目录 客户端拥有的权限
为MasterServer提供lsb格式启动脚本
cat /etc/init.d/mfsmaster # chkconfig: 345 91 10 # description: mfs start. . /etc/rc.d/init.d/functions . /etc/sysconfig/network path="/mfs/sbin" [ "${NETWORKING}" = "no" ] && exit 0 start() { $path/mfsmaster start $path/mfscgiserv start } stop() { $path/mfsmaster stop $path/mfscgiserv start } restart() { $path/mfsmaster restart $path/mfscgiserv restart } status() { $path/mfsmaster test $path/mfscgiserv test } case "$1" in start) start ;; stop) stop ;; restart) restart ;; status) status ;; *) echo $"Usage: $0 start|stop|restart|status" exit 1 esac exit 0
修改权限
chmod 755 /etc/init.d/mfsmaster
导出命令
echo 'export PATH=$PATH:/mfs/sbin' > /etc/profile.d/mfs.sh . /etc/profile.d/mfs.sh
同步启动脚本至从节点
scp -p /etc/init.d/mfsmaster two:/etc/init.d/
关闭服务卸载drbd设备
service mfsmaster stop umount /dev/drbd1
部署Corosync+Pacemaker
Corosync是集群管理套件的一部分,它在传递信息的时候可以通过一个简单的配置文件来定义信息传递的方式和协议等,RHCS集群套件就是基于corosync实现。但corosync只提供了message layer的能力。集群的资源管理则需要Pacemaker,其管理接口有两个分别是crmsh和pcs。
环境准备
service NetworkManager stop
时间同
主机名称解析的结果等于uname -n
安装(pacemaker作为corosync的插件运行)
yum install -y corosync pacemaker
资源管理器配置接口基于crmsh
yum install -y crmsh-1.2.6-4.el6.x86_64.rpm pssh-2.3.1-2.el6.x86_64.rpm
生成密钥
corosync-keygen cp /etc/corosync/corosync.conf.example /etc/corosync/corosync.conf
配置文件
vim /etc/corosync/corosync.conf #添加pacemaker插件 compatibility: whitetank #是否兼容0.8版本的corosync totem { #用来定义集群节点心跳信息传递 version: 2 #版本号 secauth: on #启用安全认证机制 threads: 0 #启用多少线程完成心跳信息传递 interface { #定义心跳信息传递的接口 ringnumber: 0 #避免循环转发心跳信息 bindnetaddr: 192.168.2.0 #指定网卡的网络地址 mcastaddr: 226.194.61.21 #心跳信息使用的组播地址 mcastport: 5405 #组播监听端口 ttl: 1 } } logging { #心跳信息层日志 fileline: off # to_stderr: no #是否把错误信息发往屏幕 to_logfile: yes #使用自定义日志文件logfile to_syslog: no #是否记录到系统日志 logfile: /var/log/cluster/corosync.log debug: off #调试功能 timestamp: on #每次记录心跳信息是否记录时间戳 logger_subsys { subsys: AMF debug: off } } amf { mode: disabled } service { #添加pacemaker插件 ver: 0 name: pacemaker } aisexec { #可省略 user: root group: root }
复制配置文件到其他节点
scp -p /etc/corosync/corosync.conf /etc/corosync/authkey two.soulboy.com:/etc/corosync/
分别在两节点启动corosync服务
service corosync start
使用crmsh接口定义drbd资源(忽略法定票数、禁用stonith设备)
crm(live)configure# property no-quorum-policy=ignore crm(live)configure# property stonith-enabled=false
定义原始资源
crm(live)configure# primitive mfs_drbd ocf:linbit:drbd params drbd_resource=mfs op monitor role=Master interval=10 timeout=20 op monitor role=Slave interval=20 timeout=20 op start timeout=240 op stop timeout=100 #定义drbd资源 crm(live)configure# ms ms_mfs_drbd mfs_drbd meta master-max="1" master-node-max="1" clone-max="2" clone-node-max="1" notify="true" #定义drbd的克隆资源、克隆属性 crm(live)configure# primitive mfsstore ocf:heartbeat:Filesystem params device="/dev/drbd1" directory="/mfs" fstype="ext4" op monitor interval=40 timeout=40 op start timeout=60 op stop timeout=60 #定义本地挂载资源 crm(live)configure# primitive mfsip ocf:heartbeat:IPaddr params ip="192.168.1.40" op monitor interval=20 timeout=20 on-fail=restart #定义vip crm(live)configure# primitive mfsserver lsb:mfsmaster #定义mfs服务
定义colocation约束(资源运行在同一个节点上的偏好)
crm(live)configure# colocation mfsstore_with_ms_mfs_drbd_master inf: mfsstore ms_mfs_drbd:Master #挂载资源追随drbd主资源在一起 crm(live)configure# colocation mfsserver_with_mfsstore inf: mfsserver mfsstore #mfs服务追随挂载资源 crm(live)configure# colocation mfsip_with_mfsserver inf: mfsip mfsserver #vip追随mfs服务
定义资源组(如果定义了资源组就没有必要定义colocation约束了)
crm(live)configure# group ha_mfsservice mfsstore mfsserver mfsip #本文没有这样做,但特此说明这样做也是可以的
定义order约束(资源启动和关闭的次序)
crm(live)configure# order ms_mfs_drbd_before_mfsstore mandatory: ms_mfs_drbd:promote mfsstore:start #节点上存在drbdMaster才能启动mystore服务 crm(live)configure# order mfsstore_before_mfsserver mandatory: mfsstore:start mfsserver:start #mystore服务启动才能启动mfs服务 crm(live)configure# order mfsip_before_mfsserver mandatory: mfsip mfsserver #vip启动才能启动mfs服务
定义location约束(资源对节点的倾向性)
location mfsservice_prefer_one ha_mfsservice 500: one.soulboy.com #主节点从故障中回复是否可以将资源抢夺回来,本文没有这样做,特此说明这样做是可以完成资源抢占的。
检查语法并保存
crm(live)configure# verify crm(live)configure# commit
查看集群状态(发现资源都运行在主节点上)
[root@one packages]# crm crm(live)# status Online: [ one.soulboy.com two.soulboy.com ] Master/Slave Set: ms_mfs_drbd [mfs_drbd] Masters: [ one.soulboy.com ] Slaves: [ two.soulboy.com ] mfsstore (ocf::heartbeat:Filesystem): Started one.soulboy.com mfsserver (lsb:mfsmaster): Started one.soulboy.com mfsip (ocf::heartbeat:IPaddr): Started one.soulboy.com
查看验证
[root@one ~]# drbd-overview #drbd资源正常 1:mfs/0 Connected Primary/Secondary UpToDate/UpToDate C r----- /mfs ext4 5.0G 142M 4.6G 3% [root@one ~]# service mfsmaster status #mfs资源正常 mfsmaster pid: 13966 mfscgiserv pid:14158 [root@one ~]# ip addr show | grep 192.168.1.40 #vip资源正常 inet 192.168.1.40/24 brd 192.168.1.255 scope global secondary eth0 [root@one ~]# ls /mfs #挂载资源正常 etc lost+found sbin share var
故障模拟测试
安装ChunkServer
useradd mfs -s /sbin/nologin tar xf mfs-1.6.26.tar.gz cd mfs-1.6.26 ./configure --prefix=/usr/local/mfs --with-default-user=mfs --with-default-group=mfs make && make install cp /usr/local/mfs/etc/mfschunkserver.cfg.dist /usr/local/mfs/etc/mfschunkserver.cfg cp /usr/local/mfs/etc/mfshdd.cfg.dist /usr/local/mfs/etc/mfshdd.cfg
主配置文件
vim /usr/local/mfs/etc/mfschunkserver.cfg # WORKING_USER = mfs # WORKING_GROUP = mfs # SYSLOG_IDENT = mfschunkserver # LOCK_MEMORY = 0 # NICE_LEVEL = -19 # DATA_PATH = /usr/local/mfs/var/mfs # MASTER_RECONNECTION_DELAY = 5 # BIND_HOST = * MASTER_HOST = 192.168.1.40 #元数据服务器的地址 MASTER_PORT = 9420 #元数据服务器监听端口 # MASTER_TIMEOUT = 60 # CSSERV_LISTEN_HOST = * # CSSERV_LISTEN_PORT = 9422 #此端口用户和其他ChunkServer间复制数据 # HDD_CONF_FILENAME = /usr/local/mfs/etc/mfshdd.cfg #分配给MFS磁盘使用空间配置文件路径 # HDD_TEST_FREQ = 10 # LOCK_FILE = /var/run/mfs/mfschunkserver.lock # BACK_LOGS = 50 # CSSERV_TIMEOUT = 5
磁盘空间配置文件
vim /usr/local/mfs/etc/mfshdd.cfg /data #/data是一个MFS的分区,实例化为本机一个独立的磁盘挂载分区。
修改权限并启动服务
chown -R mfs:mfs /data mfschunkserver start
Client编译安装
MFS客户端依赖于fuse
tar xf fuse-2.9.2.tar.gz cd fuse-2.9.2 ./configure make && make install vim /etc/profile #在最后添加 export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH source /etc/profile #即时生效 export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH
安装MFS客户端
useradd mfs -s /sbin/nologin tar xf mfs-1.6.26.tar.gz cd mfs-1.6.26 ./configure --prefix=/usr/local/mfs --with-default-user=mfs --with-default-group=mfs --enable-mfsmount make && make install modprobe fuse #加载fuse到内核
挂载MFS文件系统
mkdir /webdata #创建本地目录作为挂载点 /usr/local/mfs/bin/mfsmount /webdata -H 192.168.1.40 #挂载MFS到本地/webdata目录
挂载MFSMeta文件系统
mkdir /webdatameta #创建本地MFSMeta目录 /usr/local/mfs/bin/mfsmount -m /webdatameta -H 192.168.1.40 #挂载MFSMeta文件系统
client创建文件并查看信息(正常)
[root@five /]# echo "123" > /webdata/one #创建文件 [root@five /]# mfsfileinfo /webdata/one #查看副本和存储节点 /webdata/one: chunk 0: 0000000000000006_00000001 / (id:6 ver:1) copy 1: 192.168.1.50:9422 copy 2: 192.168.1.64:9422
登录web管理控制台(正常)
模拟主节点故障
crm(live)node# standby #离线,等待几秒钟 crm(live)node# online #上线 crm(live)node# cd #回退 crm(live)# status #查看集群资源状态 Online: [ one.soulboy.com two.soulboy.com ] Master/Slave Set: ms_mfs_drbd [mfs_drbd] Masters: [ two.soulboy.com ] Slaves: [ one.soulboy.com ] mfsstore (ocf::heartbeat:Filesystem): Started two.soulboy.com mfsserver (lsb:mfsmaster): Started two.soulboy.com mfsip (ocf::heartbeat:IPaddr): Started two.soulboy.com
client再次创建文件并查看副本数(正常)
[root@five /]# echo "123" > /webdata/two [root@five /]# mfsfileinfo /webdata/two /webdata/two: chunk 0: 0000000000000007_00000001 / (id:7 ver:1) copy 1: 192.168.1.50:9422 copy 2: 192.168.1.64:9422
再次登录web管理控制台(正常)
补充和总结
解决MFS单点故障的主要思路是将MasterServer安装在drbd设备目录中,通过corosync+pacemaker将drbd、vip、mount、mfsmaster资源粘合在一起,并通过colocation和order的约束保证了资源间依赖关系和启动次序,此外mfsmaster的启动在pacemaker中定义为lsb风格RA,也就是形如/etc/init.d/目录下的sysv风格的脚本。值得一提的是pacemaker的管理接口,本文中使用的是crmsh,而pcs接口有着比crmsh更强大的功能,可以实现管理集群整个生命周期,支持节点的添加、移除、启动、关闭等操作。
实现mysql的高可用也可以通过本文这种思路实现,具体步骤可参考本文,这里补充下pcs接口的用法,方便读者做对比。
pcs resource create myvip ocf:heartbeat:IPaddr params ip=192.168.1.70 op monitor interval=20 timeout=20 on-fail=restart #定义vip pcs resource create mystore ocf:heartbeat:Filesystem params device="192.168.1.50:/mysqldata" directory="/mydata" fstype="nfs" op monitor interval=40 timeout=40 on-fail=restart op start timeout=60 op stop timeout=60 #定义nfs pcs resource create mysqlserver lsb:mysqld op monitor interval=20 timeout=20 on-fail=restart #定义httpd pcs resource group add mysqlservice myvip mystore mysqlserver #定义webservice资源组 pcs constraint location mysqlservice prefers two.soulboy.com=500 #定义资源倾向性,资源组webservice对节点二的倾向性为500 pcs constraint order start myvip then start mystore #定义资源的order执行次序,这个貌似不能一下子定义三个资源月约束 pcs constraint order start mystore then start mysqlserver #定义资源的order执行次序 pcs constraint colocation add myvip mystore #定义colocation,如果有资源组可以省略。这个貌似不能一次定义三个资源月约束 pcs constraint colocation add mystore mysqlserver #定义colocation
实现mfs的高可用也可以通过heartbeat+drbd来实现,思路和本文类似,已经大牛撰写,文章内容优质,请参考: qzhijun的BLOG