背景需求:
使用heartbeat来做HA高可用,并且把nginx服务作为HA对应的服务。master1为主,另一个是备。
需要在主备上漂移的资源有两个:VIP和nginx服务
准备两台机器:
master1: 192.168.42.12 10.1.1.1(心跳)
master2: 192.168.42.13 10.1.1.2(心跳)
vip: 192.168.42.14
以下是IP配置:
(上图可以看到没有配置vip:两台机器都不必手动添加vip,交给heartbeat去自动添加即可)
添加路由:
在master1添加路由:
route add -host 10.1.1.2 dev eth1
在master2添加路由:
route add -host 10.1.1.1 dev eth1
1.以下5步操作在两台机器上完成:
1). /etc/init.d/iptables stop
2). setenforce 0
3). vi /etc/hosts //增加以下内容
192.168.42.12 master1
192.168.42.13 master2
保存退出
4). 安装epel扩展源:
yum -y install epel-release
5). 安装heartbeat和nginx
yum -y install heartbeat nginx
注:heartbeat不要设置开机启动,一定要手动启动。
2.在master1上配置:
cd /usr/share/doc/heartbeat-3.0.4/
cp authkeys ha.cf haresources /etc/ha.d/
cd /etc/ha.d
vi authkeys
auth 3
md5 Hello!
保存退出。
chmod 600 authkeys
vi haresources //加入如下语句
master1 IPaddr::192.168.42.14/25/eth0:0 nginx //这里填写需要漂移的资源:VIP和nginx服务。
//只填写主节点的主机名:master1,
//IPaddr:填写VIP为192.168.42.14/25,设置在eth0:0接口上,
//nginx:主备切换时启动备机的NGINX,这里的NGINX必须是能够直接在/etc/init.d/目录下启动。
保存退出。如下图所示:
vi ha.cf //改为如下内容:
debugfile /var/log/ha-debug //设定debug文件目录
logfile /var/log/ha-log //设定日志文件目录
logfacility local0
keepalive 2 //设定检查时间间隔为2s
deadtime 30 //设定死亡时间为30s
warntime 10 //设定告警时间为10s(10s以上没收到对方的回应就报警)
initdead 60 //设定初始化时间为60s
udpport 694 //启动udp监听端口号
ucast eth1 10.1.1.2 //填写对方的心跳网卡及心跳IP
auto_failback on //启动故障恢复模式(主在恢复正常后会自动接管资源)
node master1 //指定两个节点,主节点必须写在前面
node master2
ping 192.168.42.1 //指定一个第三方的仲裁节点,这里写的是网关
respawn hacluster /usr/lib64/heartbeat/ipfail //使用这个脚本去侦听对方是否还活着(使用的是ICMP报文检测)
保存退出。如下图所示:
3.把master1上的三个文件复制到master2上:
cd /etc/ha.d
scp authkeys ha.cf haresources root@master2:/etc/ha.d
4.修改master2上的ha.cf文件:
vi /etc/ha.d/ha.cf
ucast eth1 10.1.1.2 ===》 ucast eth1 10.1.1.1 //只改一处即可,填写对方的心跳网卡及心跳IP
保存退出。如下图所示:
5.启动heartbeat:
启动:先主后从。
关闭:先从后主。
/etc/init.d/heartbeat start
注:heartbeat最好不要设置开机自动启动,要手动启动-
启动后master1会出现一个eth0:0及VIP,并自动启动nginx;而master2则不会启动eth0:0和nginx。如下图所示:
6.测试:当master1关机后,是否会切换nginx:
可以发现,当master1关机后,master2立即启动了自身的nginx来接管业务。
master1系统重启后,heartbeat恢复工作,自动将nginx开启,如下图所示:
并且VIP已移到master1上:如下图所示:
而此时的master2上的nginx已经被heartbeat关掉了,VIP也没了,如下图所示:
相关日志:
实验操作成功。
另外:当master1上的heartbeat关掉后,master2会自动接管master1上的nginx和VIP,而master1的heartbeat恢复工作后,master2上的nginx和VIP立即自动退出,交还给master1。
以手动方式完全释放master1的heartbeart对资源的管理权:
在master1上执行:
/usr/share/heartbeat/hb_standby
执行后,master1上的资源被释放,master2会立即接管资源。
以手动方式让master1强行接管master2资源管理权:
在master1上执行:
/usr/share/heartbeat/hb_takeover
执行后,master2上的资源被释放,master1会立即接管资源。
如果要对mysql进行高可用资源切换,只需两台master机器安装好mysql,修改/etc/ha.d/haresources文件为:
master1 IPaddr::192.168.42.14/25/eth0:0 nginx mysqld
保存退出。两边重启heartbeat。
扩展:在主上面的心跳线接口给down掉之后,备上面因为检测不到主还活着,于是自己成为主,启动了虚拟IP接口,接替了主的工作。当把主的心跳线接口up起来之后备主动把虚拟IP交还给主,自己成为备。
然后我将主上面的对外接口给down之后,备因为检测到心跳接口还是正常的,还以为主还活着,于是高可用就失败了。当主把对外接口up之后需要重新启动heartbeat服务才能从备上面把工作接管过来。
由这里可以看出心跳线是至关重要的,心跳线挂了之后将有可能导致脑裂行为的发生(即主和备一起在抢占虚拟IP的控制权),实际环境中最好给心跳线做冗余,使用以太端口捆绑保障心跳线的健壮性。
同时,假如主的对外接口挂了,但是心跳线没有挂,备就无法检测到主挂了,也就无法实现高可用了。
heartbeat配置drbd操作:
- 主备都要准备一块独立的磁盘,如/dev/sdb
- 主备都要做:对sdb分两个分区,第一个分区进行mkfs格式化,第二个分区为meta data分区,不用格式化。
- 在主上建立目录:mkdir /store,备不用建。用于挂载drbd磁盘分区
一、DRBD的安装:
1.安装依赖包(主备都要装):
yum install gcc gcc-c++ make glibc flex kernel-devel kernel-headers
2.安装DRBD(主备都要装):
tar zxvf drbd-8.4.3.tar.gz
cd drbd-8.4.3
./configure --prefix=/usr/local/drbd --with-km
make KDIR=/usr/src/kernels/2.6.32-504.16.2.el6.x86_64/
make install
mkdir -p /usr/local/drbd/var/run/drbd
cp /usr/local/drbd/etc/rc.d/init.d/drbd /etc/rc.d/init.d
chkconfig --add drbd
chkconfig drbd off //最好手动启动,开机自动启动容易拉住不动
3、加载DRBD模块(主备都要加载):
modprobe drbd
查看DRBD模块是否加载到内核:
lsmod |grep drbd
4.参数配置(主备都要操作):
vi /usr/local/drbd/etc/drbd.conf
清空文件内容,并添加如下配置:
resource r0{
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;
}
syncer { rate 200M;}
on master1{
device /dev/drbd0;
disk /dev/sdb1;
address 192.168.42.12:7788;
meta-disk internal;
}
on master2{
device /dev/drbd0;
disk /dev/sdb1;
address 192.168.42.13:7788;
meta-disk internal;
}
}
保存退出
5.创建DRBD设备并激活r0资源(主备都要做):
mknod /dev/drbd0 b 147 0
drbdadm create-md r0
等待片刻,显示success表示drbd块创建成功
Writing meta data...
initializing activity log
NOT initializing bitmap
New drbd meta data block successfully created.
--== Creating metadata ==--
As with nodes, we count the total number of devices mirrored by DRBD
at http://usage.drbd.org.
The counter works anonymously. It creates a random number to identify
the device and sends that random number, along with the kernel and
DRBD version, to usage.drbd.org.
http://usage.drbd.org/cgi-bin/insert_usage.pl?
nu=716310175600466686&ru=15741444353112217792&rs=1085704704
* If you wish to opt out entirely, simply enter 'no'.
* To continue, just press [RETURN]
success
再次输入该命令:
drbdadm create-md r0
成功激活r0
[need to type 'yes' to confirm] yes
Writing meta data...
initializing activity log
NOT initializing bitmap
New drbd meta data block successfully created.
6、启动DRBD服务(主备都要启动方能生效):
service drbd start
7、查看状态:
service drbd status
drbd driver loaded OK; device status:
version: 8.4.3 (api:1/proto:86-101)
GIT-hash: 89a294209144b68adb3ee85a73221f964d3ee515 build by root@drbd1.corp.com, 2015-05-12 21:05:41
m:res cs ro ds p mounted fstype
0:r0 Connected Secondary/Secondary Inconsistent/Inconsistent C
这里ro:Secondary/Secondary表示两台主机的状态都是备机状态,ds是磁盘状态,显示的状态内容为“Inconsistent不一致”,这是因为DRBD无法判断哪一方为主机,应以哪一方的磁盘数据作为标准。
执行完后,主备间正在进行磁盘同步,可多次执行service drbd status查看同步的进度百分比。
8、将master1主机配置为主节点:
drbdsetup /dev/drbd0 primary --force
分别查看主从DRBD状态(master1):
执行:/etc/init.d/drbd status
在master2执行:/etc/init.d/drbd status
- ro在主从服务器上分别显示 Primary/Secondary和Secondary/Primary
- ds显示UpToDate/UpToDate
- 表示主从配置成功。
9、挂载DRBD(只在master1):
从刚才的状态上看到mounted和fstype参数为空,所以我们这步开始挂载DRBD到系统目录/store
mkfs.ext4 /dev/drbd0
mkdir /store
mount /dev/drbd0 /store
注:Secondary节点上不允许对DRBD设备进行任何操作,包括挂载;备机上的/store目录也不必建立。heartbeat切换到备机后,会自动建立。
所有的读写操作只能在Primary节点上进行,只有当Primary节点挂掉时,Secondary节点才能提升为Primary节点,并自动挂载DRBD继续工作。
并且drbd的数据是同步的。
成功挂载后的DRBD状态(master1):
10.编辑集群资源文件(主备都要做):
vi /etc/ha.d/haresources
master1 IPaddr::192.168.42.14/25/eth0:0 nginx drbddisk::r0 Filesystem::/dev/drbd0::/store::ext4
保存退出
- IPaddr::192.168.0.190/24/eth0:用IPaddr脚本配置对外服务的浮动虚拟IP
- drbddisk::r0:用drbddisk脚本实现DRBD主从节点资源组的挂载和卸载
- Filesystem::/dev/drbd0::/store::ext4:用Filesystem脚本实现磁盘挂载和卸载
- 启动顺序:从左往右启动。如果左边的nginx被删除,那么右边的mysqld可能会无法顺利启动
- 关闭顺序:从右往左启动
二、创建DRBD脚本文件drbddisk(主备都要做):
vi /etc/ha.d/resource.d/drbddisk
#!/bin/bash
#
# This script is inteded to be used as resource script by heartbeat
#
# Copright 2003-2008 LINBIT Information Technologies
# Philipp Reisner, Lars Ellenberg
#
###
DEFAULTFILE="/etc/default/drbd"
DRBDADM="/sbin/drbdadm"
if [ -f $DEFAULTFILE ]; then
. $DEFAULTFILE
fi
if [ "$#" -eq 2 ]; then
RES="$1"
CMD="$2"
else
RES="all"
CMD="$1"
fi
## EXIT CODES
# since this is a "legacy heartbeat R1 resource agent" script,
# exit codes actually do not matter that much as long as we conform to
# http://wiki.linux-ha.org/HeartbeatResourceAgent
# but it does not hurt to conform to lsb init-script exit codes,
# where we can.
# http://refspecs.linux-foundation.org/LSB_3.1.0/
#LSB-Core-generic/LSB-Core-generic/iniscrptact.html
####
drbd_set_role_from_proc_drbd()
{
local out
if ! test -e /proc/drbd; then
ROLE="Unconfigured"
return
fi
dev=$( $DRBDADM sh-dev $RES )
minor=${dev#/dev/drbd}
if [[ $minor = *[!0-9]* ]] ; then
# sh-minor is only supported since drbd 8.3.1
minor=$( $DRBDADM sh-minor $RES )
fi
if [[ -z $minor ]] || [[ $minor = *[!0-9]* ]] ; then
ROLE=Unknown
return
fi
if out=$(sed -ne "/^ *$minor: cs:/ { s/:/ /g; p; q; }" /proc/drbd); then
set -- $out
ROLE=${5%/**}
: ${ROLE:=Unconfigured} # if it does not show up
else
ROLE=Unknown
fi
}
case "$CMD" in
start)
# try several times, in case heartbeat deadtime
# was smaller than drbd ping time
try=6
while true; do
$DRBDADM primary $RES && break
let "--try" || exit 1 # LSB generic error
sleep 1
done
;;
stop)
# heartbeat (haresources mode) will retry failed stop
# for a number of times in addition to this internal retry.
try=3
while true; do
$DRBDADM secondary $RES && break
# We used to lie here, and pretend success for anything != 11,
# to avoid the reboot on failed stop recovery for "simple
# config errors" and such. But that is incorrect.
# Don't lie to your cluster manager.
# And don't do config errors...
let --try || exit 1 # LSB generic error
sleep 1
done
;;
status)
if [ "$RES" = "all" ]; then
echo "A resource name is required for status inquiries."
exit 10
fi
ST=$( $DRBDADM role $RES )
ROLE=${ST%/**}
case $ROLE in
Primary|Secondary|Unconfigured)
# expected
;;
*)
# unexpected. whatever...
# If we are unsure about the state of a resource, we need to
# report it as possibly running, so heartbeat can, after failed
# stop, do a recovery by reboot.
# drbdsetup may fail for obscure reasons, e.g. if /var/lock/ is
# suddenly readonly. So we retry by parsing /proc/drbd.
drbd_set_role_from_proc_drbd
esac
case $ROLE in
Primary)
echo "running (Primary)"
exit 0 # LSB status "service is OK"
;;
Secondary|Unconfigured)
echo "stopped ($ROLE)"
exit 3 # LSB status "service is not running"
;;
*)
# NOTE the "running" in below message.
# this is a "heartbeat" resource script,
# the exit code is _ignored_.
echo "cannot determine status, may be running ($ROLE)"
exit 4 # LSB status "service status is unknown"
;;
esac
;;
*)
echo "Usage: drbddisk [resource] {start|stop|status}"
exit 1
;;
esac
exit 0
保存退出。只需将该脚本原样复制到服务器即可使用。
赋予755执行权限:
chmod 755 /etc/ha.d/resource.d/drbddisk
三、启动HeartBeat服务:
在两个节点上启动HeartBeat服务,先启动master1,再启动master2。
如果都已经处于启动状态,可先关闭master2,再关闭master1,再启动master1,再启动master2
相关资料:
- 心跳线意外中断会引起脑裂,导致数据的不完整性,并可能会对服务造成严重影响 。
- 引起数据的不完整性主要是指,集群中节点(在脑裂期间)同时访问同一共享资源,而此时并没有锁机制来控制针对该数据访问(都脑裂了,咋控制哩),那么就存在数据的不完整性的可能。
- 对服务造成严重影响,举例来说,可能你早上上班的时候会发现NodeA和NodeB同时接管了一个虚拟IP。
- 在“双机热备”高可用(HA)系统中,当联系2个节点的“心跳线”断开时,本来构成同一个整体、动作协调的HA系统,就分裂成为2个独立的个体。由于相互失去了联系,都以为是对方出了故障,2个节点上的HA软件像“裂脑人”一样,“本能”地争抢“共享资源”、争着起动“应用服务”,那么必然会发生严重的后果:或者共享资源被瓜分、两边的“服务”都起不来了;或者两边“服务”都起来了,但同时读写“共享存储”,导致数据损坏(常见如数据库轮询着的联机日志出错)。
操作成功。
drbd被称为穷人的SAN,屌丝级的SAN,能获得与SAN类似的效果,但整体性能差,性能开销大,响应时间较大。目前只能两台机之间做同步,扩展性较差。如果资金紧张,数据量不大,可以考虑。有条件的话最好购买SAN存储,再配置多路径+智能磁盘锁,把数据以共享方式存放在SAN中。磁盘锁可能需要存储厂商提供技术支持。