通常说的双机热备是指两台机器都在运行,但并不是两台机器都同时在提供服务。
      eg:当提供服务的一台出现故障的时候,另外一台会马上自动接管并且提供服务,而且切换的时间非常短。
栗子:下面来以keepalived结合tomcat来实现一个web服务器的双机热备。
      keepalived的工作原理是VRRP(Virtual Router Redundancy Protocol)虚拟路由冗余协议。
  在VRRP中有两组重要的概念:VRRP路由器和虚拟路由器,主控路由器和备份路由器。
      VRRP路由器是指运行VRRP的路由器,是物理实体,

      虚拟路由器是指VRRP协议创建的,是逻辑概念。

一组VRRP路由器协同工作,共同构成一台虚拟路由器。

  Vrrp中存在着一种选举机制,用以选出提供服务的路由即主控路由,其他的则成了备份路由。

当主控路由失效后,备份路由中会重新选举出一个主控路由,来继续工作,来保障不间断服务。

我们在本文中的测试环境如下
两台物理服务器和一个虚拟服务器(vip):
master:redhat 2.6.18-53.el5  192.168.8.4
backup: redhat 2.6.18-53.el5  192.168.8.6
vip: 192.168.8.100
测试环境的网络topology图如下:

  节点A 192.168.8.4 (主节点), 节点B 192.168.8.6(备用节点),虚拟IP(对外提供服务的IP 192.168.8.100)
在这种模式下,虚拟IP在某时刻只能属于某一个节点,另一个节点作为备用节点存在。
  当主节点不可用时,备用节点接管虚拟IP(即虚拟IP漂移至节点B),提供正常服务。

keepalived的原理可以这样简单理解:
  keepalived安装在两台物理服务器上,并相互监控对方是否在正常运行。
  当节点A正常的时候:节点A上的keepalived会将下面的信息广播出去:
  192.168.8.100 这个IP对应的MAC地址为节点A网卡的MAC地址

图中的其它电脑 如客户端和NodeB会更新自己的ARP表,对应192.168.8.100的MAC地址=节点A网卡的MAC地址。

  当节点A发生故障的时候,节点B上的keepalived会检测到,并且将下面的信息广播出去:
192.168.8.100 这个IP对应的MAC地址为节点B网卡的MAC地址
图中的其它电脑如客户端会更新自己的ARP表,对应192.168.8.100的MAC地址=节点B网卡的MAC地址。

===================================================================

操作步骤
1,在主备机器上安装keepalived,
步骤如下:下载keepalived-1.1.15.tar.gz,然后解压安装
#tar zxvf keepalived-1.1.15.tar.gz
#cd keepalived-1.1.15
#./configure
#make
#make install
2,配置keepalived
配置中的state MASTER决定了节点为主节点
priority决定了优先级,比如在有多个备用节点的时候,主节点故障后优先级值大的接管。
主节点的配置如下:

  1. global_defs {
  2. router_id NodeA
  3. }
  4. vrrp_instance VI_1 {
  5. state MASTER    #设置为主服务器
  6. interface eth0  #监测网络接口
  7. virtual_router_id 51  #主、备必须一样
  8. priority 100   #(主、备机取不同的优先级,主机值较大,备份机值较小,值越大优先级越高)
  9. advert_int 1   #VRRP Multicast广播周期秒数
  10. authentication {
  11. auth_type PASS  #VRRP认证方式,主备必须一致
  12. auth_pass 1111   #(密码)
  13. }
  14. virtual_ipaddress {
  15. 192.168.8.100/24  #VRRP HA虚拟地址
  16. }

备用节点的配置如下:

  1. global_defs {
  2. router_id NodeB
  3. }
  4. vrrp_instance VI_1 {
  5. state BACKUP    #设置为主服务器
  6. interface eth0  #监测网络接口
  7. virtual_router_id 51  #主、备必须一样
  8. priority 90   #(主、备机取不同的优先级,主机值较大,备份机值较小,值越大优先级越高)
  9. advert_int 1   #VRRP Multicast广播周期秒数
  10. authentication {
  11. auth_type PASS  #VRRP认证方式,主备必须一致
  12. auth_pass 1111   #(密码)
  13. }
  14. virtual_ipaddress {
  15. 192.168.8.100/24  #VRRP HA虚拟地址
  16. }

3,启动keepalived:
keepalived -D -f /usr/local/etc/keepalived/keepalived.conf
查看log消息:
tail -f /var/log/messages
启动主节点A后的日志为:会广播ARP消息

  1. [root@srv4 ~]# tail -f /var/log/messages
  2. Sep 20 01:45:29 srv4 Keepalived_vrrp: Configuration is using : 34546 Bytes
  3. Sep 20 01:45:29 srv4 Keepalived_vrrp: VRRP sockpool: [ifindex(2), proto(112), fd(8,9)]
  4. Sep 20 01:45:30 srv4 Keepalived_vrrp: VRRP_Instance(VI_1) Transition to MASTER STATE
  5. Sep 20 01:45:31 srv4 Keepalived_vrrp: VRRP_Instance(VI_1) Entering MASTER STATE
  6. Sep 20 01:45:31 srv4 Keepalived_vrrp: VRRP_Instance(VI_1) setting protocol VIPs.
  7. Sep 20 01:45:31 srv4 Keepalived_vrrp: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 192.168.8.100
  8. Sep 20 01:45:31 srv4 Keepalived_vrrp: Netlink reflector reports IP 192.168.8.100 added
  9. Sep 20 01:45:31 srv4 Keepalived_healthcheckers: Netlink reflector reports IP 192.168.8.100 added
  10. Sep 20 01:45:31 srv4 avahi-daemon[4029]: Registering new address record for 192.168.8.100 on eth0.
  11. Sep 20 01:45:36 srv4 Keepalived_vrrp: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 192.168.8.100

通过ip a 命令可以看到192.168.8.100/24绑定到了eth0上

  1. [root@srv4 bin]# ip a
  2. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue
  3. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  4. inet 127.0.0.1/8 scope host lo
  5. inet6 ::1/128 scope host
  6. valid_lft forever preferred_lft forever
  7. 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
  8. link/ether 00:0c:29:50:2d:9d brd ff:ff:ff:ff:ff:ff
  9. inet 192.168.8.4/24 brd 192.168.8.255 scope global eth0
  10. inet 192.168.8.100/24 scope global secondary eth0
  11. inet6 fe80::20c:29ff:fe50:2d9d/64 scope link
  12. valid_lft forever preferred_lft forever

启动备用节点B后的日志为:

  1. Sep 20 01:47:31 hadoopsrv Keepalived_vrrp: Configuration is using : 34262 Bytes
  2. Sep 20 01:47:31 hadoopsrv Keepalived_vrrp: VRRP_Instance(VI_1) Entering BACKUP STATE
  3. Sep 20 01:47:31 hadoopsrv Keepalived_vrrp: VRRP sockpool: [ifindex(2), proto(112), fd(7,8)]
  4. Sep 20 01:47:31 hadoopsrv Keepalived: Starting VRRP child process, pid=20567

4,在两台机器上安装tomcat,安装步骤省略

安装完成后在节点A的机器上创建一个html文件内容如下

  1. this is the test page
  2. <br>
  3. from server 192.168.8.4

通过下面的url验证能够正常访问
http://192.168.8.4:8080/test/test.html

安装完成后在节点B的机器上创建一个html文件内容如下

  1. this is the test page
  2. <br>
  3. from server 192.168.8.6

通过下面的url验证能够正常访问
http://192.168.8.6:8080/test/test.html
在主节点,节点A正常的时候通过下面的url访问
192.168.8.100:8080/test/test.html
返回的内容应该为主节点上的html

  1. this is the test page
  2. <br>
  3. from server 192.168.8.4

将节点A的keepalived停止: killall keepalived
通过下面的url访问
192.168.8.100:8080/test/test.html
返回的内容应该为备用节点上的内容

  1. this is the test page
  2. <br>
  3. from server 192.168.8.6

同时查看节点B的日志:发现节点B转为主节点并且会广播ARP消息

  1. Sep 20 01:55:44 hadoopsrv Keepalived_vrrp: VRRP_Instance(VI_1) Transition to MASTER STATE
  2. Sep 20 01:55:45 hadoopsrv Keepalived_vrrp: VRRP_Instance(VI_1) Entering MASTER STATE
  3. Sep 20 01:55:45 hadoopsrv Keepalived_vrrp: VRRP_Instance(VI_1) setting protocol VIPs.
  4. Sep 20 01:55:45 hadoopsrv Keepalived_vrrp: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 192.168.8.100
  5. Sep 20 01:55:45 hadoopsrv avahi-daemon[3769]: Registering new address record for 192.168.8.100 on eth0.
  6. Sep 20 01:55:50 hadoopsrv Keepalived_vrrp: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 192.168.8.100

本文的目的主要是演示keepalived实现双机热备的功能和过程。
对于应用本身(tomcat)发生错误,以及"脑裂"等问题是不能解决的。

======================================

keepalived配置及典型应用案例

keepalived配置及典型应用案例

使用源码先安装keepalived 1.2.6

cd /usr/local/src

wget  http://www.keepalived.org/software/keepalived-1.2.6.tar.gz

tar zxf keepalived-1.2.6.tar.gz

cd keepalived-1.2.6

./configure --prefix=/usr/local/keepalived

make

make install

所设keepalived安装到/usr/local/keepalived, 则所有配置文件均位于此目录之下。 我一直没搞明白一个问题,Linux默认总是将程序安装到/usr/local目录下,所有程序共享了/usr/local/sbin目录。这对一些人的操作习惯是有影响的。为何不考虑使用每个软件一个独立的目录呢?

1.  建立服务启动脚本,以便使用service命令控制之 
cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/keepalived

chmod +x /etc/init.d/keepalived

因为我们使用非默认路径(/usr/local)安装keepalived, 故需要修改几处路径,以保证keepalived能正常启动, 需要修改的文件如下:

2. 修改/etc/init.d/keepalived, 寻找大约15行左右的. /etc/sysconfig/keepalived, 修改为: 
.  /usr/local/keepalived/etc/sysconfig/keepalived, 即指向正确的文件位置

同时在上述行下添加以下内容(将keepavlied主程序所在路径导入到环境变量PATH中):

PATH="$PATH:/usr/local/keepalived/sbin"

export PATH

3. 修改/usr/local/keepalived/etc/sysconfig/keepalived文件,设置正确的服务启动参数 
KEEPALIVED_OPTIONS="-D -f /usr/local/keepalived/etc/keepalived/keepalived.conf"

4. 经过以上修改,keepalived基本安装即可完成,启动测试之: 
service keepalived restart

5. 切勿忘记将此服务设置为开机启动

chkconfig keepalived on

默认的配置文件中,指定了两个数个虚拟IP : 192.168.200.16  192.168.200.17  192.168.200.18

可使用ip addr命令验证之。

以上实验只需要一台主机,因为当前节点被指定为主节点,且没有收到其它节点的VRRP组播信息,故自动绑定了虚拟IP。

参考案例一:主-备模式 
在这种模式下,虚拟IP在某时刻只能属于某一个节点,另一个节点作为备用节点存在。当主节点不可用时,备用节点接管虚拟IP,提供正常服务。

节点A 192.168.0.11 (主节点), 节点B 192.168.0.12(备用节点)  虚拟IP(对外提供服务的IP 192.168.0.200

要求默认情况下由节点A提供服务,当节点A不可用时,由节点B提供服务(即虚拟IP漂移至节点B)。

节点A上的配置文件/usr/local/keepalived/etc/keepalived/keepalived.conf

global_defs {

notification_email {

root@localhost

}

notification_email_from root@local host

smtp_server localhost

smtp_connect_timeout 30

router_id  NodeA

}

默认的配置文件中,使用第三方smtp服务器,但这在现实中几乎没有意义(需要验证的原因),我们将其指定为localhost, 将通知信息的发送交给本地sendmail服务处理。查阅说明文档得知route_id配置是为了标识当前节点,我将其设置为NodeA。当然两个节点的此项设置可相同,也可不相同。

vrrp_instance VI_1 {

state MASTER   #指定A节点为主节点 备用节点上设置为BACKUP即可

interface eth0   #绑定虚拟IP的网络接口

virtual_router_id 51  #VRRP组名,两个节点的设置必须一样,以指明各个节点属于同一VRRP组

priority 100   #主节点的优先级(1-254之间),备用节点必须比主节点优先级低

advert_int 1   #组播信息发送间隔,两个节点设置必须一样

authentication {   #设置验证信息,两个节点必须一致

auth_type PASS

auth_pass 1111

}

virtual_ipaddress {   #指定虚拟IP, 两个节点设置必须一样

192.168.200.16/24

192.168.200.17 /24

192.168.200.18 /24

}

}

默认的配置文件中,竟然没有子网掩码,从而导致使用了默认子网掩码255.255.255.255,如果导致无法从其它机器访问虚拟IP(keepalived虚拟IP无法ping通)。

按同样的方法配置节点B并修改配置文件,可将A节点的配置文件复制到B节点,并修改以下几项: 
router_id  NodeB

state   BACKUP

priority   99

其它项不必修改。

测试及验证:拔掉节点A的网线,就发现虚拟IP已经绑定到节点B上,再恢复A节点的网线,虚拟IP又绑定回节点A之上。

但是这种方式存在脑裂的可能,即两个节点实际都处于正常工作状态,但是无法接收到彼此的组播通知,这时两个节点均强行绑定虚拟IP,导致不可预料的后果。 
这时就需要设置仲裁,即每个节点必须判断自身的状态(应用服务状态及自身网络状态),要实现这两点可使用自定义shell脚本实现,通过周期性地检查自身应用服务状态,并不断ping网关(或其它可靠的参考IP)均可。当自身服务异常、或无法ping通网关,则认为自身出现故障,就应该移除掉虚拟IP(停止keepalived服务即可)。主要借助keepalived提供的vrrp_script及track_script实现:

在keepalived的配置文件最前面加入以下代码,定义一个跟踪脚本: 
vrrp_script check_local { #定义一个名称为check_local的检查脚本

script "/usr/local/keepalived/bin/check_local.sh" #shell脚本的路径

interval 5  #运行间隔

}

再在vrrp_instance配置中加入以下代码使用上面定义的检测脚本:

track_script {

check_local

}

我们在/usr/local/keepalived/bin/check_local.sh定义的检测规则是:

1.  自身web服务故障(超时,http返回状态不是200)

2.  无法ping通网关

3.  产生以上任何一个问题,均应该移除本机的虚拟IP(停止keepalived实例即可)

但这里有个小问题,如果本机或是网关偶尔出现一次故障,那么我们不能认为是服务故障。更好的做法是如果连续N次检测本机服务不正常或连接N次无法ping通网关,才认为是故障产生,才需要进行故障转移。另一方面,如果脚本检测到故障产生,并停止掉了keepalived服务,那么当故障恢复后,keepalived是无法自动恢复的。我觉得利用独立的脚本以秒级的间隔检查自身服务及网关连接性,再根据故障情况控制keepalived的运行或是停止。

这里提供一个思路,具体脚本内容请大家根据自己的需要编写即可。

如下图的案例:

假设节点A和B组成主备关系,A为备用节点,B为主节点,那么当在图标红叉位置发生网络故障时,节点A接收不到节点B的组播通知,将抢占虚拟IP。这时出现的后果就是节点A和节点B均拥有虚拟IP,就可能导致了脑裂。所以我们以网关IP连通性作为参考,可避免此问题产生。

参考案例二:双主模式 
主备模式的缺点就是始终只有一台机器位于工作状态,另外一台机器永远是备用状态,存在资源浪费之问题。

双主模式允许两台机器均处于工作状态并互相作为备份。

搭建keepalived双方模式的要素:

1.  必须有两个虚拟IP, 分别绑定至两个节点上

2. 每个节点作为某个虚拟IP的主节点,并同时作为另外一个虚拟IP的备用节点。

3. 当某个节点产生故障时,两个虚拟IP自动绑定至正常节点上

参阅相关文章,这就相当于使用两台物理路由器(普通主机视为路由器即可),构造出两个虚拟VRRP路由器。

也就是说,两个节点的配置应该是交叉的,对同个虚拟IP,交叉互为主备。

节点A的关键配置: 
vrrp_instance vip1 {

state MASTER

interface eth0

virtual_router_id 51   #本机两个vrrp_instance组的此值不能相同,但对应备用节点的此值必须相同

priority 99 #对应备用节点值应该比此值小

advert_int 1

authentication {

auth_type PASS

auth_pass 1111

}

virtual_ipaddress {

192.168.100.1 /24

}

}

vrrp_instance vip2 {

state BACKUP

interface eth0

virtual_router_id 52  #本机两个vrrp_instance组的此值不能相同,但对应主节点的此值必须相同

priority 90   #主节点的值应该比此值大

advert_int 1

authentication {

auth_type PASS

auth_pass 1111

}

virtual_ipaddress {

192.168.100.2 /24

}

}

复制节点A的配置至B节点,并将MASTER修改为BACKUP, 同时将BACKUP修改为MASTER。优先级和虚拟路由器组id(virtual_route_id)要特别注意其它配置必须保持相同。

B节点的配置: 
vrrp_instance vip1 {

state BACKUP

interface eth0

virtual_router_id 51

priority 90

advert_int 1

authentication {

auth_type PASS

auth_pass 1111

}

virtual_ipaddress {

192.168.100.1 /24

}

}

vrrp_instance vip2 {

state MASTER

interface eth0

virtual_router_id 52

priority 99

advert_int 1

authentication {

auth_type PASS

auth_pass 1111

}

virtual_ipaddress {

192.168.100.2 /24

}

}

另外,为了保证服务可靠性,我们应该在每个节点运行shell脚本检测本机的服务是否正常,一旦检测到服务异常时,停止掉本机的keepalived, 如此虚拟IP自动转移到备用机器之上,如每隔3秒检测一次本机服务状态,如果连接3次检测失败,则停止掉keepalived实例。同时如果本机服务是正常的,但是keepalived没有启动(故障恢复之后),则启动keepalived,以达到故障恢复之目的。

check_service.sh文件的内容

#!/bin/bash

pidfile=/var/lock/subsys/`basename $0`.pid

if [ -f $pidfile ] && [ -e /proc/`cat $pidfile` ] ; then

exit 1

fi

trap "rm -fr $pidfile ; exit 0" 1 2 3 15

echo $$ > $pidfile

maxfails=3

fails=0

success=0

while [ 1 ]

do

/usr/bin/wget --timeout=3 --tries=1 http://127.0.0.1/ -q -O /dev/null

if [ $? -ne 0 ] ; then

let fails=$[$fails+1]

success=0

else

fails=0

let success=$[$success+1]

fi

if [ $fails -ge $maxfails ] ; then

fails=0

success=0

#check keepalived is running ? try to stop it

service keepalived status | grep running

if [ $? -eq 0 ] ; then

logger -is "local service fails $maxfails times ... try to stop keepalived."

service keepalived stop 2>&1 | logger

fi

fi

if [ $success -gt $maxfails ] ; then

#check keepalived is stopped ? try to start it

service keepalived status | grep stopped

if [ $? -eq 0 ] ; then

logger -is "service changes normal, try to start keepalived ."

service keepalived start

fi

success=0

fi

sleep 3

done

两个节点上均应运行此脚本,请将此脚本加入到cron任务中(此程序已经作了单实例运行机制,加入计划任务的作用就是防止脚本意外中断后检测功能失效),可实现的功能:

如果本地服务连续三次检测失败,就尝试停止keepalived服务(如果keepalived处于运行状态)

如果本地服务连接三次检测成功,但keepalived没有启动,则启动之

关键的执行点,均已经记录到系统日志中(/var/log/messages)

执行crontab -e , 加入以下内容: 
*/1  *  *  *  * /root/check_service.sh

如果需要此脚本的原始文件,请联系笔者信箱zhangxugg@163.com。

停止掉本机的keepalived, 稍过一会,就会keepalived服务被自动启动了(这是因为本地服务检测正常)

停止掉本机的nginx, 稍过一会,就会发现keepalived服务也被停止掉了

再启动nginx, 稍过一会,发现keepalived也被正常启动,并绑定了正确的虚拟IP

我们可根据具体环境,将服务的检测功能强化(如检测到网关的连接性),以达到较好的故障转移效果。

最新文章

  1. Atitti 载入类的几种方法 &#160;&#160;&#160;Class.forName&#160;ClassLoader.loadClass&#160;&#160;直接new
  2. [转]oracle 分析函数over
  3. FMDB读取Datetime类型值为1970的问题
  4. VS.net 2013中使用Git建立源代码管理 版本管理
  5. Android常用的工具类
  6. java画图程序_图片用字母画出来_源码发布_版本二
  7. Egret版本更新(H5增加版本号)
  8. Python - 升级所有已安装的第三方包
  9. pythonchallenge关卡破解
  10. 操作笔记:tomcat在正式环境
  11. win8 或 win2008 系统 TFS 打开或获取源代码非常慢
  12. Sqlserver 理解子查询
  13. css 权威指南笔记( 五)结构和层叠之三种样式来源
  14. tablbView中section的间距
  15. javascript中函数的闭包自调用
  16. c#自定义Attribute获取接口实现
  17. [math] 我对对数的最新理解
  18. Java语法基础学习DayThirteen(枚举类和注解)
  19. 2.Early Education of Children 儿童的早期教育
  20. bzoj 1178 [Apio2009]CONVENTION会议中心

热门文章

  1. Only one statement is allowed per batch. A batch separator, such as &#39;GO&#39;, might be required between statements.
  2. 【转】Delphi 关键字详解
  3. Python之路【第十四篇】前端补充回顾
  4. 程序日志输出实现-Log4j
  5. apache 的工作模式
  6. PHP 短连接生成
  7. SqlServer 18456 错误解决方案
  8. 使用code标签获得类似代码段的效果
  9. redis php扩展安装下载
  10. CF451C Predict Outcome of the Game 水题