Haproxy+Keepalived高可用双机单活

来源:互联网 发布:恐怖电影软件 编辑:程序博客网 时间:2024/05/22 09:04
我们的应用MyApp不支持集群,但要求双机单活(两台机器:master和slave): 
1.正常情况下,只有master启动MyApp并提供服务 
2.当master发生故障时,slave自动启动本机的MyApp,同时虚拟IP漂移至slave,保持对外提供服务的IP和端口不变 

F5据说也能满足上面的需求,但F5的通常用法都是双机双活,单活的话还没研究过 

服务器资源 
Java代码  收藏代码
  1. 10.75.201.2:虚拟IP(VIP),与master和slave在同一子网;以此IP对外暴露服务  
  2. 10.75.201.67(master):安装MyApp+ Haproxy + Keepalived  
  3. 10.75.201.66(slave):安装MyApp+ Haproxy + Keepalived  


网络策略 
Java代码  收藏代码
  1. 10.75.201.2:8000 <-> 10.75.201.67:9000  
  2. 10.75.201.2:8000 <-> 10.75.201.66:9000  


系统安装 

Haproxy安装及配置 
同时安装在master和slave 

1. 拷贝安装文件到/app/risk/ha下 

2. 使用root用户安装haproxy 
Java代码  收藏代码
  1. tar -xvf haproxy-1.4.24.tar.gz  
  2. cd haproxy-1.4.24  
  3. make TARGET=linux26 ARCH=x86_64  
  4. make install  

3. 使用risk用户配置haproxy,创建文件/app/risk/ha/haproxy.cfg,粘贴如下内容 
Java代码  收藏代码
  1. global  
  2.  log     127.0.0.1 alert  
  3.  log     127.0.0.1 alert debug  
  4.   
  5. defaults  
  6.  log        global  
  7.  mode       http  
  8.  option     dontlognull  
  9.  option     redispatch  
  10.  retries    3  
  11.  contimeout 10800000  
  12.  clitimeout 10800000  
  13.  srvtimeout 10800000  
  14.   
  15. listen MyApp 10.75.201.2:8000  
  16.  mode    tcp  
  17.  balance roundrobin  
  18.  option  tcpka  
  19.  server  MyApp01 10.75.201.67:9000 check inter 5000 downinter 500  
  20.  server  MyApp02 10.75.201.66:9000 check inter 5000 backup  

以10.75.201.2:8000对外提供服务,后端是主备两台机器:10.75.201.67:9000和10.75.201.66:9000 

使用HAProxy遇到的问题: 

a. 
[WARNING] 003/191909 (20413) : config : 'stats' statement ignored for proxy 'MyApp' as it requires HTTP mode. 
[WARNING] 003/191909 (20413) : config : 'option forwardfor' ignored for proxy 'MyApp' as it requires HTTP mode 
原因是: 
mode tcp是基于第4层(网络层),mode http是基于第7层(应用层),mode tcp不会检查http header 
不同的mode可配置的选项不同,例如配置改成: 
mode    http 
stats   enable 
option  forwardfor 
就会提示上述错误 
而MyApp是基于netty的TCP服务器,因此配置为mode tcp 

b. 
Starting proxy MyApp: cannot bind socket 
原因是配置的8000端口被其他程序占用了,或者是重复启动haproxy 


keepalived安装及配置 
同时安装在master和slave,使用root用户操作 


1. 依次安装如下package 
Java代码  收藏代码
  1. rpm -Uvh keyutils-libs-devel-1.4-4.el6.x86_64.rpm  
  2. rpm -Uvh libcom_err-devel-1.41.12-14.el6.x86_64.rpm  
  3. rpm -Uvh libsepol-devel-2.0.41-4.el6.x86_64.rpm  
  4. rpm -Uvh libselinux-devel-2.0.94-5.3.el6.x86_64.rpm  
  5. rpm -Uvh krb5-devel-1.10.3-10.el6.x86_64.rpm  
  6. rpm -Uvh zlib-devel-1.2.3-29.el6.x86_64.rpm  
  7. rpm -Uvh openssl-devel-1.0.0-27.el6.x86_64.rpm  


2. 解压keepalived-1.2.12.tar.gz,跳转到目录下编译安装 
Java代码  收藏代码
  1. ./configure  
  2. make  
  3. make install  


修改/etc/keepalived/keepalived.conf(interface值用ifconfig确认一下) 
Java代码  收藏代码
  1. master:  
  2. vrrp_script check_MyApp {  
  3.     script "/app/risk/MyApp/shell/check_MyApp.sh"   # verify the port is listening   
  4.     interval 2                    # check every 2 seconds  
  5. }  
  6. vrrp_instance VI_1 {  
  7.     interface eth1                # interface to monitor  
  8.     state MASTER  
  9.     virtual_router_id 11          # Assign one ID for this route  
  10.     priority 101                  # 101 on master, 100 on backup  
  11.     virtual_ipaddress {  
  12.         10.75.201.2            # the virtual IP  
  13.     }  
  14.     track_script {  
  15.         check_MyApp  
  16.     }  
  17.     notify_stop "/app/risk/MyApp/shell/stopAll.sh"  
  18. }  
  19.   
  20. slave:  
  21. vrrp_script check_MyApp {  
  22.     script "killall -0 haproxy"   # verify the haproxy is running  
  23.     interval 2                    # check every 2 seconds  
  24. }  
  25. vrrp_instance VI_1 {  
  26.     interface eth1                # interface to monitor  
  27.     state BACKUP  
  28.     virtual_router_id 11          # Assign one ID for this route  
  29.     priority 100                  # 101 on master, 100 on backup  
  30.     virtual_ipaddress {  
  31.         10.75.201.2            # the virtual IP  
  32.     }  
  33.     track_script {  
  34.         check_MyApp  
  35.     }  
  36.     notify "/app/risk/MyApp/shell/keepalivednotify.sh"  
  37. }  


说明: 
a. master中的vrrp_script 是check_MyApp.sh,它定时检查MyApp(提供服务的端口是否起来),若down掉,则停掉keepalived,使得slave能接管服务并成为master: 
Java代码  收藏代码
  1. #!/bin/bash  
  2. #if MyApp is down, stop keepalived  
  3.   
  4. PORT=9000  
  5. nc -z 127.0.0.1 $PORT 1>/dev/null 2>&1; result=$?;  
  6. if [ $result -eq 0 ]; then  
  7.     exit 0  
  8. else  
  9.     service keepalived stop  
  10.     . ./log.sh "keepalived stopped"  
  11.     exit 1  
  12. fi  


b.master中notify_stop的作用是service keepalived stop后,把MyApp关掉,确保“单活”;但如果是直接kill掉keepalived进程的话,是不会触发notify_stop的,应该避免这样做。同时,salve中notify的作用是,当slave转换成master后,启动本机的MyApp的同时,远程调用shell脚本把原master的MyApp停掉,确保“单活” 

c. slave中vrrp_script 则简单地检查Haproxy是否正常,由于haproxy是一直开着的,因此slave会进入BACKUP状态 


d.虚拟IP(10.75.201.2)并不需要对应一台机器,只要求跟master和slave的IP是同一子网就可以了 

e.keepalivednotify.sh的主要作用就是当slave进入MASTER状态时,启动本机的MyApp,同时把之前master的MyApp停掉: 
Java代码  收藏代码
  1. #!/bin/bash  
  2.   
  3. LOCAL=10.75.201.66  
  4. REMOTE=10.75.201.67  
  5. PORT=9000  
  6. NOW=`date "+%Y-%m-%d %H:%M:%S"`  
  7.   
  8.   
  9. startLocal(){  
  10.          nc -z $LOCAL $PORT 1>/dev/null 2>&1; result=$?;  
  11.          if [ $result -eq 0 ]; then  
  12.              echo $NOW-$LOCAL:$PORT 'is listening! No need to restart!'  
  13.          else  
  14.              . /app/risk/MyApp/shell/startAll.sh  
  15.              echo $NOW-'start at' $LOCAL:$PORT 'ok'  
  16.          fi  
  17. }  
  18.   
  19.   
  20. #startRemote(){  
  21. #         nc -z $REMOTE $PORT 1>/dev/null 2>&1; result=$?;  
  22. #         if [ $result -eq 0 ]; then  
  23. #             echo $NOW-$REMOTE:$PORT 'is listening! No need to restart!'  
  24. #         else  
  25. #             ssh root@$REMOTE "sh /app/risk/MyApp/shell/startAll.sh"  
  26. #             echo $NOW-'start at' $REMOTE:$PORT 'ok'  
  27. #         fi  
  28. #}  
  29.   
  30. stopRemote(){  
  31.         nc -z $REMOTE $PORT 1>/dev/null 2>&1; result=$?;  
  32.         if [ $result -eq 0 ]; then  
  33.             ssh root@$REMOTE "sh /app/risk/MyApp/shell/stopAll.sh"  
  34.         fi  
  35. }  
  36.   
  37. stopLocal(){  
  38.         nc -z $LOCAL $PORT 1>/dev/null 2>&1; result=$?;  
  39.         if [ $result -eq 0 ]; then  
  40.             . /app/risk/MyApp/shell/stopAll.sh  
  41.         fi  
  42. }  
  43.   
  44. TYPE=$1  
  45. NAME=$2  
  46. STATE=$3  
  47.   
  48. case $STATE in  
  49.         "MASTER")   
  50.                   startLocal   
  51.                   stopRemote  
  52.                   exit 0  
  53.                   ;;  
  54.         "BACKUP")   
  55.                   stopLocal  
  56.                   exit 0  
  57.                   ;;  
  58.         "FAULT")    
  59.                   stopLocal  
  60.                   exit 0  
  61.                   ;;  
  62.         *)        echo "unknown state"  
  63.                   exit 1  
  64.                   ;;  
  65. esac  


keepalived的其他相关配置: 
1. 让keepalived作为linux服务自启动 
Java代码  收藏代码
  1. cd /etc/sysconfig  
  2. ln -s /usr/local/etc/sysconfig/keepalived .  
  3. cd /etc/rc3.d/  
  4. ln -s /usr/local/etc/rc.d/init.d/keepalived S100keepalived  
  5. cd /etc/init.d/  
  6. ln -s /usr/local/etc/rc.d/init.d/keepalived .  


2. 让keepalived启动时输出详细信息,修改/usr/local/etc/sysconfig/keepalived 
修改为KEEPALIVED_OPTIONS="-D -d" 

3. 让主机可绑定非本地IP 
Java代码  收藏代码
  1. echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf  
  2. sysctl -p  



使用keepalived遇到的问题: 
a.虚拟IP绑定不成功 
可以尝试service network restart,同时注意启动keepalived使用绝对路径的配置文件,例如: 
keepalived -f /app/risk/ha/keepalived.conf 
而不要这样: 
cd /app/risk/ha 
keepalived -f ./keepalived.conf 
具体原因不明 

如果不指定keepalived的配置文件的话,默认是读取/etc/keepalived/keepalived.conf文件 
强烈建议使用/etc/keepalived/keepalived.conf(没有这个文件则创建一个) 
这个默认的路径可以在/usr/local/etc/rc.d/init.d/keepalived中看到: 
Java代码  收藏代码
  1. #!/bin/sh  
  2. #  
  3. # Startup script for the Keepalived daemon  
  4. #  
  5. # processname: keepalived  
  6. # pidfile: /var/run/keepalived.pid  
  7. # config: /etc/keepalived/keepalived.conf  
  8. # chkconfig: - 21 79  
  9. # description: Start and stop Keepalived  
  10.   
  11. # Source function library  
  12. . /etc/rc.d/init.d/functions  
  13.   
  14. # Source configuration file (we set KEEPALIVED_OPTIONS there)  
  15. . /etc/sysconfig/keepalived  
  16.   
  17.   
  18. ......  


b.执行service keepalived start报错: 
Starting keepalived: /bin/bash: keepalived: command not found 

keepalived这个命令在: 
/usr/local/sbin/keepalived 

而echo $PATH确认/usr/local/sbin/是在PATH里面的 

这个问题非常奇怪,不知是什么原因 

上网搜索一下,解决方案有两个: 
一是把keepalived拷贝到/usr/sbin/: 

cp /usr/local/sbin/keepalived /usr/sbin/ 

二是修改启动脚本/etc/init.d/keepalived,把start方法当中启动命令修改为全路径: 

daemon /usr/local/sbin/keepalived ${KEEPALIVED_OPTIONS} 

c.其他错误 
需要检查各个shell脚本是否有执行权限,以及shell脚本中是否有windows字符(dos2unix) 


启动 
1. 使用risk用户启动master的MyApp(slave不启动MyApp) 
/app/risk/MyApp/shell/startAll.sh 

2. 使用risk用户启动master和slave的haproxy 
nohup haproxy -f /app/risk/ha/haproxy.cfg & 
nohup haproxy -f /app/risk/ha/haproxy.cfg & 

3. 使用root用户启动master和slave的keepalived. 
service keepalived start 

测试验证 
1. 查看MyApp状态 
netstat -anp | grep 9000 
2. 查看Haproxy状态 
ps -ef | grep haproxy 
3. 查看keepalived状态 
ps –ef | grep keepalived 
cat /var/log/messages | grep VRRP_Instance 
或tail –f /var/log/messages 
4. 虚拟IP绑定状态 
ip a | grep eth 



正常情况下: 
1. 虚拟IP绑定在master上 
在master上执行命令ip add | grep eth1: 
eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UNKNOWN qlen 1000 
inet 10.75.201.67/24 brd 10.75.201.255 scope global eth1 
inet 10.75.201.2/32 scope global eth1 
可见绑定了虚拟IP(10.75.201.2) 

2. master的keepalived状态为MASTER(在master上执行命令tail –f /var/log/messages): 
localhost Keepalived_healthcheckers[23359]: Using LinkWatch kernel netlink reflector... 
localhost Keepalived_vrrp[23360]: VRRP_Script(check_MyApp) succeeded 
localhost Keepalived_vrrp[23360]: VRRP_Instance(VI_1) Transition to MASTER STATE 
localhost Keepalived_vrrp[23360]: VRRP_Instance(VI_1) Received lower prio advert, forcing new election 
localhost Keepalived_vrrp[23360]: VRRP_Instance(VI_1) Entering MASTER STATE 

3. slave的keepalived为BACKUP状态(命令同上) 
localhost Keepalived_vrrp[5161]: VRRP_Instance(VI_1) Entering BACKUP STATE 

测试master有故障的情况: 
1. 把master的MyApp进程kill掉 
2. 把master的keepalived服务停掉:service keepalived stop 
3. 把master的keepalived进程kill掉(此时master上的MyApp不会停掉,需要手动关掉,应该避免这种情况) 
以上任意一种情况发生,都会使得slave转换到MASTER状态并且虚拟IP漂移至slave,同时slave的MyApp会自动启动 
0 0
原创粉丝点击