> 数据库 > mysql > 了解 OpenStack 高可用(HA)(4):RabbitMQ 和 Mysql HA_mysql 理解 OpenStack 高可用(HA)(4):RabbitMQ 和 mysql HA
本系列会分析OpenStack 的高可用性(HA)概念和解决方案:
(1)OpenStack 高可用方案概述
(2)Neutron L3 Agent HA – VRRP (虚拟路由冗余协议)
(3)Neutron L3 Agent HA – DVR (分布式虚机路由器)
(4)RabbitMQ 和 Mysql HA
(5)OpenStack 和 VMware 的高可用性比较
1. 基础知识
1.1 Pacemaker
Pacemaker 承担集群资源管理者(CRM – Cluster Resource Manager)的角色,它是一款开源的高可用资源管理软件,适合各种大小集群。Pacemaker 由 Novell 支持,SLES HAE 就是用 Pacemaker 来管理集群,并且 Pacemaker 得到了来自Redhat,Linbit等公司的支持。它用资源级别的监测和恢复来保证集群服务(aka. 资源)的最大可用性。它可以用基础组件(Corosync 或者是Heartbeat)来实现集群中各成员之间的通信和关系管理。它包含以下的关键特性:
监测并恢复节点和服务级别的故障
存储无关,并不需要共享存储
资源无关,任何能用脚本控制的资源都可以作为服务
支持使用 STONITH 来保证数据一致性
支持大型或者小型的集群
支持 quorum (仲裁) 或 resource(资源) 驱动的集群
支持任何的冗余配置
自动同步各个节点的配置文件
可以设定集群范围内的 ordering, colocation and anti-colocation
支持高级的服务模式
Pacemaker 软件架构:
Pacemaker – 资源管理器(CRM),负责启动和停止服务,而且保证它们是一直运行着的以及某个时刻某服务只在一个节点上运行(避免多服务同时操作数据造成的混乱)。
Corosync – 消息层组件(Messaging Layer),管理成员关系、消息和仲裁。见 1.2 部分介绍。
Resource Agents – 资源代理,实现在节点上接收 CRM 的调度对某一个资源进行管理的工具,这个管理的工具通常是脚本,所以我们通常称为资源代理。任何资源代理都要使用同一种风格,接收四个参数:{start|stop|restart|status},包括配置IP地址的也是。每个种资源的代理都要完成这四个参数据的输出。Pacemaker 的 RA 可以分为三种:(1)Pacemaker 自己实现的 (2)第三方实现的,比如 RabbitMQ 的 RA (3)自己实现的,比如 OpenStack 实现的它的各种服务的RA,这是 mysql 的 RA。
Pacemaker 支持多种类型的集群,包括 Active/Active, Active/Passive, N+1, N+M, N-to-1 and N-to-N 等。
这里 有详细的 Pacemaker 安装方法。这是 中文版。这篇文章 提到了 Pacemaker 的一些问题和替代方案。
1.2 Corosync
Corosync 用于高可用环境中提供通讯服务,位于高可用集群架构中的底层,扮演着为各节点(node)之间提供心跳信息传递这样的一个角色。Pacemaker 位于 HA 集群架构中资源管理、资源代理这么个层次,它本身不提供底层心跳信息传递的功能,它要想与对方节点通信就需要借助底层的心跳传递服务,将信息通告给对方。
关于心跳的基本概念:
心跳: 就是将多台服务器用网络连接起来,而后每一台服务器都不停的将自己依然在线的信息使用很简短很小的通告给同一个网络中的其它主机,告诉它们自己依然在线,其它服务器收到这个心跳信息就认为它是在线的,尤其是主服务器。
心跳信息怎么发送, 由谁来收,其实就是进程间通信。两台主机是没法通信的,只能利用网络功能,通过进程监听在某一套接字上,实现数据发送,数据请求,所以多台服务器就得运行同等的进程,这两个进程不停的进行通信,主节点(主服务器)不停的向对方同等的节点发送自己的心跳信息,那这个软件就叫高可用的集群的基准层次,也叫心跳信息传递层以及事物信息的传递层,这是运行在集群中的各节点上的进程,这个进程是个服务软件,关机后需要将其启动起来,主机间才可以传递信息的,一般是主节点传给备节点。
这篇文章 详细介绍了其原理。
1.3 DRBD
DRBD (Distributed Replication Block Device) 即分布式复制块设备。它的工作原理是:在A主机上有对指定磁盘设备写请求时,数据发送给 A主机的 kernel,然后通过 kernel 中的一个模块,把相同的数据通过网络传送给 B主机的 kernel 一份,然后 B主机再写入自己指定的磁盘设备,从而实现两主机数据的同步,也就实现了写操作高可用。DRBD一般是一主一从,并且所有的读写和挂载操作,只能在主节点服务器上进行,但是主从DRBD服务器之间是可以进行调换的。因此,DRBD 可以看着基于网络的 RAID 1 的实现。
DRBD共有两部分组成:内核模块和用户空间的管理工具。其中 DRBD 内核模块代码已经整合进Linux内核 2.6.33 以后的版本中,因此,如果你的内核版本高于此版本的话,你只需要安装管理工具即可;否则,你需要同时安装内核模块和管理工具两个软件包,并且此两者的版本号一定要保持对应。最新的 DRBD 版本为 8.4.
这是一个很有意思的技术,可以用来预防脑裂。Stonith 是“shoot the other node in the head” 的首字母简写,它是 Heartbeat 软件包的一个组件,它允许使用一个远程或“智能的”连接到健康服务器的电源设备自动重启失效服务器的电源,stonith设备可以关闭电源并响应软件命令,运行Heartbeat的服务器可以通过串口线或网线向stonith设备发送命令,它控制高可用服务器对中其他服务器的电力供应,换句话说,主服务器可以复位备用服务器的电源,备用服务器也可以复位主服务器的电源。详细的说明可以参考 这篇文章。
RabbitMQ A/P HA 官方方案 是采用 Pacemaker + (DRBD 或者其它可靠的共享 NAS/SNA 存储) + (CoroSync 或者 Heartbeat 或者 OpenAIS)组合来实现的。需要注意的是 CoroSync 需要使用多播,而多播在某些云环境中是被禁用的,这时候可以改为使用 Heartbeat,它采用单播。其架构为:
RabbitMQ 官方的 这篇文章介绍了基于 Pacemaker 的 RabbitMQ HA 方案。它同时指出,这是传统的 RabbitMQ HA 方案,并且建议使用 RabbitMQ 集群 + 镜像 Message Queue 的方式来实现 A/A HA。使用 Pacemaker 实现 HA 的方案主要步骤包括:
为 RabbitMQ 配置一个 DRBD 设备
配置 RabbitMQ 使用建立在 DRBD 设备之上的数据目录
选择并绑定一个可以在各集群节点之间迁移的虚拟 IP 地址 (即 VIP )
配置 RabbitMQ 监听该 IP 地址
使用 Pacemaker 管理上述所有资源,包括 RabbitMQ 守护进程本身
2.2.1 安装 Corosync 和 Pacemaker
本配置使用两个节点。
首先,在两个节点上安装软件包:apt-get install pacemaker crmsh corosync cluster-glue resource-agents,并配置 Corosync,设它为 boot 自启动:vi /etc/default/corosync,START=yes。
两个节点上,
(1)修改配置文件:vim /etc/corosync/corosync.conf
totem { #... interface { ringnumber: 0 bindnetaddr: #节点1上,192.168.1.15;节点2上, 192.168.1.32 broadcast: yes mcastport: 5405 } transport: udpu } nodelist { node { ring0_addr: 192.168 .1.15 nodeid: 1 } node { ring0_addr: 192.168 .1.32 nodeid: 2 } }
(2)启动服务 service corosync start
(3)查看状态
root@compute2:/home/s1# corosync-cfgtool -s
Printing ring status. Local node ID 2 RING ID 0 id = 192.168.1.32 status = ring 0 active with no faults
root@compute2:/home/s1# corosync-cmapctl runtime.totem.pg.mrp.srp.members #需要确保两个节点都加入了组 runtime.totem.pg.mrp.srp.members.1.config_version (u64) = 0 runtime.totem.pg.mrp.srp.members.1.ip (str) = r(0) ip(192.168.1.15) runtime.totem.pg.mrp.srp.members.1.join_count (u32) = 1 runtime.totem.pg.mrp.srp.members.1.status (str) = joined runtime.totem.pg.mrp.srp.members.2.config_version (u64) = 0 runtime.totem.pg.mrp.srp.members.2.ip (str) = r(0) ip(192.168.1.32) runtime.totem.pg.mrp.srp.members.2.join_count (u32) = 1 runtime.totem.pg.mrp.srp.members.2.status (str) = joined
(4)启动 pacemaker:service pacemaker start
(5)查看 pacemaker 状态:crm_mon
Last updated: Sun Aug 16 15 :59 :10 2015 Last change: Sun Aug 16 15 :58 :59 2015 via crmd on compute1 Stack: corosync Current DC: compute1 ( 1 ) - partition with quorum Version: 1.1 .10 -42f2063 3 Nodes configured 0 Resources configured Node compute1 ( 1084752143 ): UNCLEAN (offline) Online: [ compute1 compute2 ]
(6)配置 pacemaker
root@compute2:/home/s1# crm crm(live)# configure crm(live)configure# property no -quorum-policy=" ignore " / #因为这里只有两个节点,因此需要设置为 ‘ignore’。两个节点以上,不可以设置为 ‘ignore’ > pe-warn-series-max=" 1000 " / > pe-input-series-max=" 1000 " / > pe-error-series-max=" 1000 " / > cluster-recheck-interval=" 2min " crm(live)configure# quit There are changes pending. Do you want to commit them ? yes bye
2.2.1 为 RabbitMQ 配置一个 DRBD 设备
在 node1 和 node2 上,依次进行:
(0)安装 DRBD,并设置机器启动时 DRBD 服务不自动启动。该服务的启停升降机等都需要由 Pacemaker 控制。
(1)添加一个 1G 的 hard disk,fdiskl -l 可见 /dev/sdb
(2)创建 LVM:pvcreate /dev/sdb,vgcreate vg_rabbit /dev/sdb,lvcreate -L1000 -n rabbit vg_rabbit。创建好的 LVM 为 /dev/mapper/vg_rabbit-rabbit。
(3)定义 rabbitmq 资源:vi /etc/drbd.d/rabbitmq.res
根据 /etc/drbd.conf,资源的配置文件需要放置在 /etc/drbd.d/ 目录中,并以 res 为文件类型。DRBD 会自动读取这些配置文件并创建相应的资源。
rource rabbitmq { device minor 1 ; # DRBD device 是 /dev/drbd1,相当于 device /dev/drbd1 disk " /dev/mapper/vg_rabbit-rabbit " ; # Raw device, 本例中是 LVM path。也可以使用不同名字的 Raw device,这样的话需要放到 host 定义部分。 meta -disk internal ; # 这是默认值,更多信息可以参考这个 on compute1 { # 节点1,名称需要与 uname -n 的输出相同。 address ipv4 192.168 .1.15 :7701 ; #7701 是 DRBD 通信的 TCP 端口,需要确保该端口可以被访问 } on compute2 { # 节点2 address ipv4 192.168 .1.32 :7701 ; } }
(4)drbdadm create-md rabbitmq
root@compute2:/home/s1# drbdadm create-md rabbitmq Writing meta data... initializing activity log NOT initializing bitmap New drbd meta data block successfully created.
(5)drbdadm up rabbitmq 在 compute 2 上, (1)drbdadm -- --force primary rabbitmq (2)mkfs -t xfs /dev/drbd1 (如果提示 mkfs.xsf 找不到,则 sudo apt-get install xfsprogs)
meta-data=/dev/drbd1 isize=256 agcount=4 , agsize=63996 blks = sectsz=512 attr=2 , projid32bit=0 data = bsize=4096 blocks=255983 , imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0 log =internal log bsize=4096 blocks=1200 , version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0 , rtextents=0
(3)mount /dev/drbd1 /var/lib/rabbitmq
(4)umount /var/lib/rabbitmq
(3)drbdadm secondary rabbitmq
在 compute 1 上:
drbdadm — –force primary rabbitmq
mkfs -t xfs /dev/drbd1
mount /dev/drbd1 /var/lib/rabbitmq
至此,DRBD 设置完成,目前 compute 1 上的 DRBD 是主,compute 2 上的是备。查看其状态:
root@compute1:/home/s1# /etc/init.d/drbd status drbd driver loaded OK; device status: version: 8.4 .3 (api:1 /proto:86 -101 ) srcversion: 6551AD2C98F533733BE558C m:res cs ro ds p mounted fstype 1 :rabbitmq Connected Primary/Secondary UpToDate/UpToDate C /var /lib/rabbitmq xfs root@compute2: /home/s1# /etc/init.d/drbd status drbd driver loaded OK; device status: version: 8.4 .3 (api:1 /proto:86 -101 ) srcversion: 6551AD2C98F533733BE558C m:res cs ro ds p mounted fstype 1 :rabbitmq Connected Secondary/Primary UpToDate/UpToDate C
调试时遇到一个脑裂问题,就是两个node上 drbd 的状态都是 StandAlone,然后 DRBD 服务在 compute 2 上能起来,在 compute 1 上起不来。
root@compute1:/home/s1# /etc/init.d/drbd status drbd driver loaded OK; device status: version: 8.4 .3 (api:1 /proto:86 -101 ) srcversion: 6551AD2C98F533733BE558C m:res cs ro ds p mounted fstype 1 :rabbitmq StandAlone Secondary/Unknown UpToDate/DUnknown r----- DRBD ' s startup script waits for the peer node(s) to appear. - In case this node was already a degraded cluster before the reboot the timeout is 0 seconds. [degr-wfc-timeout] - If the peer was available before the reboot the timeout will expire after 0 seconds. [wfc-timeout] (These values are for resource ' rabbitmq ' ; 0 sec -> wait forever) To abort waiting enter ' yes ' [ 148 ]:
这篇文章 和 这篇文章 给出了这个问题的解决办法:
在起不来 DRBD 服务的节点(compute1)上,运行 drbdadm disconnect rabbitmq, drbdadm secondary rabbitmq,和 drbdadm –discard-my-data connect rabbitmq
在能起来 DRBD 服务的节点(compute2)上,运行 drbdadm connect rabbitmq
然后 DRBD 状态恢复成 Connected 了。
SUSE 有关于 DRBD 安装、配置和测试的 不错的文档 。
2.22 安装和配置 RabbitMQ
(1)在两个节点上安装 RabbitMQ。rabbitmq-server 进程会在 rabbitmq 组内的 rabbitmq 用户下运行。
(2)确保 rabbitmq 组和用户在两个节点上具有相同的 ID。运行 cat /etc/passwd | grep rabbitmq 和 cat /etc/group | grep rabbitmq 查看 ID,必要时进行修改。
(3)确保 rabbitmq 用户对 /var/lib/rabbitmq/ 有读写权限。 运行 chmod a+w /var/lib/rabbitmq/。
(4)确保各节点都使用相同的 Erlang cookie。需要将 compute 1 上的 RabbitMQ cookie 拷贝到 compute 2 上:
(1)compute 1:scp /var/lib/rabbitmq/.erlang.cookie s1@compute2:/home/s1 (2)compute 2:mv .erlang.cookie /var/lib/rabbitmq/ (3) compute 2:chown rabbitmq: /var/lib/rabbitmq/.erlang.cookie (4)compute 2:chmod 400 /var/lib/rabbitmq/.erlang.cookie (5)再执行相同的步骤,将该文件拷贝到 DRBD 共享存储文件系统中
(5)确保计算机启动时不自动启动 rabbitmq。修改 /etc/init.d/rabbitmq-server 文件,在文件头注释后面添加 exit 0.
2.2.3 在 Pacemaker 中添加 RabbitMQ 资源
在添加前,在 compute 1 节点上,运行 crm configure,输入:
primitive p_ip_rabbitmq ocf:heartbeat:IPaddr2 / #定义访问 RabbitMQ 的 VIP。使用 RA ocf:heartbeat:IPaddr2。对该 VIP 的监控间隔为 10s。 params ip=" 192.168.1.222 " cidr_netmask=" 24 " / op monitor interval =" 10s " primitive p_drbd_rabbitmq ocf:linbit:drbd / #定义RabbitMQ 的 DRBD 资源,pacemaker 会对它 start,stop,promote,demote 和 monitor。 params drbd_resource=" rabbitmq " / op start timeout =" 90s " / #启动的超时时间 op stop timeout =" 180s " / op promote timeout =" 180s " / op demote timeout =" 180s " / op monitor interval =" 30s " role=" Slave " / #对 Slave drbd 的监控间隔定义为 30s op monitor interval =" 29s " role=" Master " #对 master drbd 的监控间隔定义为 29s primitive p_fs_rabbitmq ocf:heartbeat:Filesystem / # 在 /dev/drbd1 上创建 xfs 文件系统,并 mount 到 /var/lib/rabbitmq params device=" /dev/drbd1 " directory =" /var/lib/rabbitmq " fstype =" xfs " options=" relatime " / op start timeout =" 60s " op stop timeout =" 180s " op monitor interval =" 60s " timeout=" 60s " primitive p_rabbitmq ocf:rabbitmq:rabbitmq -server / #定义 RabbitMQ 资源 params nodename=" rabbit@localhost " / mnesia_base =" /var/lib/rabbitmq " / op monitor interval =" 20s " timeout=" 10s " group g_rabbitmq p_ip_rabbitmq p_fs_rabbitmq p_rabbitmq #group 指定一组资源需要在同一个node上 ip -> fs -> rabbitmq,顺序启动,逆序停止 ms ms_drbd_rabbitmq p_drbd_rabbitmq meta notify =" true " master-max=" 1 " clone-max=" 2 " # 定义一个资源集合,往往用于 master-slave 资源集群。其中,clone-max 定义集合内的 drbd 节点数目,master-max 指定 master 最多只能有一个;notify = “true” 表示启用notification。 colocation c_rabbitmq_on_drbd inf: g_rabbitmq ms_drbd_rabbitmq:Master #colocation 定义在同一个节点上启动的资源。这里定义了一个约束,rabbitmq 只能在 DRBD Master 节点上启动 order o_drbd_before_rabbitmq inf: ms_drbd_rabbitmq:promote g_rabbitmq:start #oder 指定服务启动顺序。这个定义要求先 DRBD 升级为 Master 然后依次执行 ip,fs 和 rabbitmq 启动。
更多的 Pacemaker 配置细节,请参考 这个文档。
Pacemaker 一些有用的命令:
crm status:显示集群状态
crm configure show:显示集群配置
crm configure edit:修改集群配置
crm node standby:将当前节点设为备节点
crm node online:将当前节点设为主节点
crm ra meta ocf:heartbeat:IPaddr2:查看 RA 的 metadata
配置完成后,RabbitMQ 起不来。一堆问题,挨个来说:
(1)Corosync 调试:设置日志文件
logging { fileline: off to_stderr: yes to_logfile: yes to_syslog: yes logfile: /var /log/cluster/corosync.log syslog_facility: daemon debug: off timestamp: on }
(2)pacemaker 调试:pacemaker 的日志在 corosync 的 log file 中。
(3)运行 crm status,如果出现 Could not establish cib_ro connection: Connection refused (111) ,原因是 pacemaker 服务没有启动。运行 service pacemaker start 即可。
(4)rabbitmq 启动的错误日志可以在 /var/log/rabbitmq 目录下找到。可能的错误之一是,rabbit 用户没有目录 /var/lib/rabbitmq 的写权限。
成功后,是这样的效果:
root@compute2:/var /lib/rabbitmq/rabbit@localhost# crm status Last updated: Mon Aug 17 00 :16 :11 2015 Last change: Sun Aug 16 22 :54 :27 2015 via cibadmin on compute1 Stack: corosync Current DC: compute1 ( 1 ) - partition with quorum Version: 1.1 .10 -42f2063 3 Nodes configured 5 Resources configured Online: [ compute1 compute2 ] # pacemaker 集群中有两个节点 OFFLINE: [ compute1 ] # compute 1 是备节点 Resource Group: g_rabbitmq p_ip_rabbitmq (ocf::heartbeat:IPaddr2): Started compute2 #在 compute 2 上启动 VIP,成功 p_rabbitmq (ocf::rabbitmq:rabbitmq -server): Started compute2 #在 compute 2 上启动 rabbitmq,成功 Master /Slave Set: ms_drbd_rabbitmq [p_drbd_rabbitmq] Masters: [ compute2 ] Slaves: [ compute1 ] p_fs_rabbitmq (ocf::heartbeat:Filesystem): Started compute2 # 在 compute 2 上设置 drbd 文件系统,成功
可见,根据配置,pacemaker 会(1)根据 corosync 确定集群中的节点和状态 (2)启动 VIP (3)启动指定的服务 (4)设置 DRBD 文件系统。每一步都可能失败,失败则需要调试。
(5)将主节点停机,rabbitmq 服务顺利地被切换到备节点上。
RabbitMQ 自身实现了集群功能。官方文档在这里。基于该功能,就可以实现RabbitMQ Active/Active 模式的HA:当 master 挂掉了,按照策略选择某个slave (其实就是最先加入集群的那个slave)来担当master的角色。多个单独的 RabbitMQ 服务,可以加入到一个集群中,也可以从集群中退出。集群中的 RabbitMQ 服务,使用同样的 Erlang cookie(unix 系统上默认为 /var/lib/rabbitmq/.erlang.cookie)。所有在一个 RabbitMQ 服务中被操作的数据和状态(date/state)都会被同步到集群中的其它节点。只有 message queue 是例外,它默认只会保存到创建它的节点上,但是 这篇文章 介绍了从 3.3 版本开始,RabbitMQ 加入了 message queue 镜像的支持。这样,使用 RabbitMQ 集群+ 镜像 Message Queue 就可以实现一个完整的 A/A HA 了。
使用这种模式的 RabbitMQ,客户端象正常情况下一样,连接集群中的某个 RabbitMQ 服务。当该服务 down 掉后,客户端需要能感知到它和该服务之间的连接被中断了,然后自动连接集群中其它运行着的节点。这就需要 OpenStack 使用 RabbitMQ 的各组件也支持这种模式。目前,支持高可用 RabbitMQ 服务的 OpenStack 组件有:
除了在 OpenStack 各服务中配置多个 RabbitMQ 节点外,还可以使用 HAProxy 来提供一个 VIP 供各 OpenStack 服务使用。但是这又会涉及到 HAProxy 的 HA 问题。
和使用 Pacemaker 实现的 A/P HA 相比,这种方式是更优的方案,因为(1)它是 RabbitMQ 和 OpenStack 原生支持的,不需要使用别的软件 (2)A/A 的切换时间比 A/P 更短。但是,A/A 这种 HA 模式,仁者见仁智者见智,很多人说这是坑。
与 RabbitMQ HA 方案类似,OpenStack 官方推荐的 Mysql Active/Passive HA 方案也是 Pacemaker + DRBD + CoroSync。具体方案为:
OpenStack 官方的推荐是使用 Galera 来做 A/A HA。这种模式下,Galera 提供多个 Mysql 节点之间的同步复制,使得多个 Mysql 节点同时对外提供服务,这时候往往需要使用负载均衡软件来提供一个 VIP 给各应用使用。官网 在这里。