分享

keepalived+haproxy 高可用负载均衡

 集微笔记 2013-10-21

      由于在生产环境使用了mysqlcluster,需要实现高可用负载均衡,这里提供了keepalived+haproxy来实现.

      keepalived主要功能是实现真实机器的故障隔离及负载均衡器间的失败切换.可在第3,4,5层交换.它通过VRRPv2(Virtual Router Redundancy Protocol) stack实现的.

      Layer3:Keepalived会定期向服务器群中的服务器.发送一个ICMP的数据包(既我们平时用的Ping程序),如果发现某台服务的IP地址没有激活,Keepalived便报告这台服务器失效,并将它从服务器群中剔除,这种情况的典型例子是某台服务器被非法关机。Layer3的方式是以服务器的IP地址是否有效作为服务器工作正常与否的标准。

     Layer4:主要以TCP端口的状态来决定服务器工作正常与否。如web server的服务端口一般是80,如果Keepalived检测到80端口没有启动,则Keepalived将把这台服务器从服务器群中剔除。

     Layer5:在网络上占用的带宽也要大一些。Keepalived将根据用户的设定检查服务器程序的运行是否正常,如果与用户的设定不相符,则Keepalived将把服务器从服务器群中剔除。

Software Design

keepalived+haproxy 高可用负载均衡


keepalived启动后会有单个进程

1 8352 ?        Ss     0:00 /usr/sbin/keepalived
2 8353 ?        S      0:00  \_ /usr/sbin/keepalived
3 8356 ?        S      0:01  \_ /usr/sbin/keepalived

父进程:内存管理,子进程管理等等

子进程:VRRP子进程

子进程:Healthchecking 子进程


实例

2台mysqlcluster 10.1.6.203 master  10.1.6.205 backup

vip 10.1.6.173 

目的访问10.1.6.173 3366端口 分别轮询通过haproxy转发到10.1.6.203 3306 和10.1.6.205 3306

mysqlcluster搭建参照之前博客,这里在2台机上安装keepalived

01 root@10.1.6.203:~# apt-get install keepalived
02 root@10.1.6.203:~# cat /etc/keepalived/keepalived.conf 
03 vrrp_script chk_haproxy {
04         script "killall -0 haproxy"   # verify the pid existance
05         interval 2                    # check every 2 seconds
06         weight -2                    # add 2 points of prio if OK
07 }
08   
09 vrrp_instance VI_1 {
10         interface eth1                # interface to monitor
11         state MASTER                  
12         virtual_router_id 51          # Assign one ID for this route
13         priority 101                  # 101 on master, 100 on backup
14         nopreempt
15         debug
16   
17         virtual_ipaddress {
18                 10.1.6.173
19         }
20   
21         track_script {
22                 chk_haproxy
23         }
24   
25        notify_master /etc/keepalived/scripts/start_haproxy.sh  #表示当切换到master状态时,要执行的脚本
26        notify_fault  /etc/keepalived/scripts/stop_keepalived.sh #故障时执行的脚本
27        notify_stop   /etc/keepalived/scripts/stop_haproxy.sh # <SPAN>keepalived停止运行前运行notify_stop指定的脚本</SPAN> }

VRRPD配置包括三个类:

VRRP同步组(synchroization group)

VRRP实例(VRRP Instance)

VRRP脚本

这里使用了 VRRP实例, VRRP脚本


注意配置选项: 

stat:指定instance(Initial)的初始状态,就是说在配置好后,这台服务器的初始状态就是这里指定的,但这里指定的不算,还是得要通过竞选通过优先级来确定,里如果这里设置为master,但如若他的优先级不及另外一台,那么这台在发送通告时,会发送自己的优先级,另外一台发现优先级不如自己的高,那么他会就回抢占为master

interface:实例绑定的网卡,因为在配置虚拟IP的时候必须是在已有的网卡上添加的

priority 101:设置本节点的优先级,优先级高的为master

debug:debug级别

nopreempt:设置为不抢占

vrrp_script chk_haproxy {
        script "killall -0 haproxy"   # verify the pid existance
        interval 2                    # check every 2 seconds 脚本执行间隔
        weight -2                    # add 2 points of prio if OK 脚本结果导致的优先级变更:2表示优先级+2;-2则表示优先级-2
}

然后在实例(vrrp_instance)里面引用,有点类似脚本里面的函数引用一样:先定义,后引用函数名
        track_script {
                chk_haproxy
        }
注意:VRRP脚本(vrrp_script)和VRRP实例(vrrp_instance)属于同一个级别

01 root@10.1.6.203:scripts# cat start_haproxy.sh 
02 #!/bin/bash
03   
04 sleep 5
05 get=`ip addr  |grep 10.1.6.173 |wc -l`
06 echo $get >> /etc/keepalived/scripts/start_ha.log
07   
08 if [ $get -eq 1 ]
09 then
10         echo "`date +%c` success to get vip" >> /etc/keepalived/scripts/start_ha.log
11         /usr/local/sbin/haproxy -f /etc/haproxy/haproxy.cfg
12 else
13         echo "`date +%c` can not get vip" >> /etc/keepalived/scripts/start_ha.log
14 fi
15 root@10.1.6.203:scripts# cat stop_keepalived.sh 
16 #!/bin/bash
17   
18 pid=`pidof keepalived`
19 if [ $pid == "" ]
20 then
21     echo "`date +%c` no keepalived process id"  >> /etc/keepalived/scripts/stop_keep.log
22 else
23     echo "`date +%c` will stop keepalived "  >> /etc/keepalived/scripts/stop_keep.log
24     /etc/init.d/keepalived  stop
25 fi
26   
27 /etc/init.d/keepalived  stop
28   
29 root@10.1.6.203:scripts# cat stop_haproxy.sh 
30 #!/bin/bash
31   
32 pid=`pidof haproxy`
33 echo "`date +%c` stop haproxy" >> /etc/keepalived/scripts/stop_ha.log
34 kill -9 $pid

同理配置10.1.6.205

01 root@10.1.6.205:~# cat /etc/keepalived/keepalived.conf 
02 vrrp_script chk_haproxy {
03    script "killall -0 haproxy"   # verify the pid existance
04    interval 2                    # check every 2 seconds
05    weight 2                      # add 2 points of prio if OK
06 }
07    
08 vrrp_instance VI_1 {
09    interface eth1               # interface to monitor
10    state BACKUP
11    virtual_router_id 51          # Assign one ID for this route
12    priority 100                 # 101 on master, 100 on backup
13    virtual_ipaddress {
14        10.1.6.173
15    }
16   
17    track_script {
18        chk_haproxy
19    }
20   
21 notify_master /etc/keepalived/scripts/start_haproxy.sh
22 notify_fault  /etc/keepalived/scripts/stop_keepalived.sh
23 notify_stop /etc/keepalived/scripts/stop_haproxy.sh
24   
25 }

下面再介绍下haproxy

       HAProxy是一款基于TCP(第四层)和HTTP(第七层)应用的代理软件,它也可作为负载均衡器.可以支持数以万计的并发连接.同时可以保护服务器不暴露到网络上,通过端口映射.它还自带监控服务器状态的页面.

      安装haproxy

1 wget -O/tmp/haproxy-1.4.22.tar.gz http://haproxy./download/1.4/src/haproxy-1.4.22.tar.gz
2 tar xvfz /tmp/haproxy-1.4.22.tar.gz -C /tmp/
3 cd /tmp/haproxy-1.4.22
4 make TARGET=linux26
5 make install

      haproxy需要对每一个mysqlcluster服务器进行健康检查

1.在2台主机分别配置haproxy.cfg

01 root@10.1.6.203:scripts# cat /etc/haproxy/haproxy.cfg 
02 global
03         maxconn 51200  #默认最大连接数 
04         #uid 99
05         #gid 99
06         daemon        #以后台形式运行haproxy
07         #quiet
08         nbproc 1      #进程数量(可以设置多个进程提高性能) 
09         pidfile /etc/haproxy/haproxy.pid  #haproxy的pid存放路径,启动进程的用户必须有权限访问此文件 
10   
11 defaults
12         mode tcp            #所处理的类别 (#7层 http;4层tcp  ) 
13         option redispatch   #serverId对应的服务器挂掉后,强制定向到其他健康的服务器 
14         option abortonclose #当服务器负载很高的时候,自动结束掉当前队列处理比较久的连接 
15         timeout connect 5000s   #连接超时
16         timeout client 50000s  #客户端超时
17         timeout server 50000s   #服务器超时
18         log 127.0.0.1 local0   #错误日志记录
19         balance roundrobin    #默认的负载均衡的方式,轮询方式 
20   
21 listen proxy
22         bind 10.1.6.173:3366   #监听端口 
23         mode tcp               #http的7层模式
24         option  httpchk        #心跳检测的文件
25         server db1 10.1.6.203:3306  weight 1 check port 9222 inter 12000 rise 3 fall 3      #服务器定义,check inter 12000是检测心跳频率 rise 3是3次正确认为服务器可用, fall 3是3次失败认为服务器不可用,weight代表权重 
26         server db2 10.1.6.205:3306  weight 1 check port 9222 inter 12000 rise 3 fall 3
27   
28 listen  haproxy_stats
29         mode http
30         bind 10.1.6.173:8888
31         option httplog
32         stats refresh 5s   
33         stats uri /status #网站健康检测URL,用来检测HAProxy管理的网站是否可以用,正常返回200,不正常返回503 
34         stats realm Haproxy Manager
35         stats auth admin:p@a1SZs24 #账号密码
01 root@10.1.6.205:~$ cat /etc/haproxy/haproxy.cfg 
02 global
03         maxconn 51200
04         #uid 99
05         #gid 99
06         daemon
07         #quiet
08         nbproc 1
09         pidfile /etc/haproxy/haproxy.pid
10   
11 defaults
12         mode tcp
13         option redispatch   
14         option abortonclose
15         timeout connect 5000s
16         timeout client 50000s
17         timeout server 50000s
18         log 127.0.0.1 local0
19         balance roundrobin 
20   
21 listen proxy
22         bind 10.1.6.173:3366
23         mode tcp
24         option  httpchk
25         server db1 10.1.6.203:3306  weight 1 check port 9222 inter 12000 rise 3 fall 3
26         server db2 10.1.6.205:3306  weight 1 check port 9222 inter 12000 rise 3 fall 3
27   
28 listen  haproxy_stats
29         mode http
30         bind 10.1.6.173:8888
31         option httplog
32         stats refresh 5s   
33         stats uri /status  
34         stats realm Haproxy Manager
35         stats auth admin:p@a1SZs24

2.安装xinetd

1 root@10.1.6.203:~# apt-get install xinetd

3.在每个节点添加xinetd服务脚本和mysqlchk端口号

01 root@10.1.6.203:~# vim /etc/xinetd.d/mysqlchk 
02 # default: on
03 # description: mysqlchk
04 service mysqlchk                  #需要在servive定义
05 {
06         flags           = REUSE
07         socket_type     = stream
08         port            = 9222
09         wait            = no
10         user            = nobody
11         server          = /opt/mysqlchk  
12         log_on_failure  += USERID
13         disable         = no
14         per_source      = UNLIMITED
15         bind            = 10.1.6.173
16 }
17   
18 root@10.1.6.203:~# vim /etc/services 
19 mysqlchk        9222/tcp                        # mysqlchk
4.编写mysqlchk监控服务脚本
01 root@10.1.6.203:~# ls -l /opt/mysqlchk 
02 -rwxr--r-- 1 nobody root 1994 2013-09-17 11:27 /opt/mysqlchk
03 root@10.1.6.203:~# cat /opt/mysqlchk 
04 #!/bin/bash
05 #
06 # This script checks if a mysql server is healthy running on localhost. It will
07 # return:
08 # "HTTP/1.x 200 OK\r" (if mysql is running smoothly)
09 # - OR -
10 # "HTTP/1.x 500 Internal Server Error\r" (else)
11 #
12 # The purpose of this script is make haproxy capable of monitoring mysql properly
13 #
14   
15 MYSQL_HOST="localhost"
16 MYSQL_SOCKET="/var/run/mysqld/mysqld.sock" 
17 MYSQL_USERNAME="mysqlchkusr"
18 MYSQL_PASSWORD="secret"
19 MYSQL_OPTS="-N -q -A"
20 TMP_FILE="/dev/shm/mysqlchk.$$.out"
21 ERR_FILE="/dev/shm/mysqlchk.$$.err"
22 FORCE_FAIL="/dev/shm/proxyoff"
23 MYSQL_BIN="/opt/mysqlcluster/mysql-cluster-gpl-7.2.6-linux2.6-x86_64/bin/mysql"
24 CHECK_QUERY="select 1"
25   
26 preflight_check()
27 {
28     for I in "$TMP_FILE" "$ERR_FILE"; do
29         if [ -f "$I" ]; then
30             if [ ! -w $I ]; then
31                 echo -e "HTTP/1.1 503 Service Unavailable\r\n"
32                 echo -e "Content-Type: Content-Type: text/plain\r\n"
33                 echo -e "\r\n"
34                 echo -e "Cannot write to $I\r\n"
35                 echo -e "\r\n"
36                 exit 1
37             fi
38         fi
39     done
40 }
41   
42 return_ok()
43 {
44     echo -e "HTTP/1.1 200 OK\r\n"
45     echo -e "Content-Type: text/html\r\n"
46     echo -e "Content-Length: 43\r\n"
47     echo -e "\r\n"
48     echo -e "MySQL is running.\r\n"
49     echo -e "\r\n"
50     rm $ERR_FILE $TMP_FILE
51     exit 0
52 }
53 return_fail()
54 {
55     echo -e "HTTP/1.1 503 Service Unavailable\r\n"
56     echo -e "Content-Type: text/html\r\n"
57     echo -e "Content-Length: 42\r\n"
58     echo -e "\r\n"
59     echo -e "MySQL is *down*.\r\n"
60     sed -e 's/\n$/\r\n/' $ERR_FILE
61     echo -e "\r\n"
62     rm $ERR_FILE $TMP_FILE
63     exit 1
64 }
65 preflight_check
66 if [ -f "$FORCE_FAIL" ]; then
67         echo "$FORCE_FAIL found" > $ERR_FILE
68         return_fail;
69 fi
70 $MYSQL_BIN $MYSQL_OPTS --host=$MYSQL_HOST --socket=$MYSQL_SOCKET --user=$MYSQL_USERNAME --password=$MYSQL_PASSWORD -e "$CHECK_QUERY" > $TMP_FILE 2> $ERR_FILE
71 if [ $? -ne 0 ]; then
72         return_fail;
73 fi
74 return_ok;


测试

2个节点开启keepalived(主节点会获得vip,自动拉起haproxy),xinetd

01 root@10.1.6.203:~# ip add
02 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
03     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
04     inet 127.0.0.1/8 scope host lo
05 2: eth0: 
06  mtu 1500 qdisc pfifo_fast state DOWN qlen 1000
07     link/ether 00:26:b9:36:0f:81 brd ff:ff:ff:ff:ff:ff
08     inet 211.151.105.186/26 brd 211.151.105.191 scope global eth0
09 3: eth1: 
10  mtu 1500 qdisc pfifo_fast state UP qlen 1000
11     link/ether 00:26:b9:36:0f:83 brd ff:ff:ff:ff:ff:ff
12     inet 10.1.6.203/24 brd 10.1.6.255 scope global eth1
13     inet 10.1.6.173/32 scope global eth1
14 4: eth2: 
15  mtu 1500 qdisc noop state DOWN qlen 1000
16     link/ether 00:26:b9:36:0f:85 brd ff:ff:ff:ff:ff:ff
17 5: eth3: 
18  mtu 1500 qdisc noop state DOWN qlen 1000
19     link/ether 00:26:b9:36:0f:87 brd ff:ff:ff:ff:ff:ff
20 root@10.1.6.203:~# netstat -tunlp | grep ha
21 tcp        0      0 10.1.6.173:3366     0.0.0.0:*               LISTEN      1042/haproxy    
22 tcp        0      0 10.1.6.203:8888     0.0.0.0:*               LISTEN      1042/haproxy    
23 udp        0      0 0.0.0.0:56562           0.0.0.0:*                           1042/haproxy    
24 root@10.1.6.203:~# netstat  -tunlp | grep xine
25 tcp        0      0 10.1.6.203:9222     0.0.0.0:*               LISTEN      30897/xinetd    
26 root@10.1.6.203:~# ps -ef | grep haproxy
27 root      1042     1  0 Sep17 ?        00:00:00 /usr/local/sbin/haproxy -f /etc/haproxy/haproxy.cfg</BROADCAST,MULTICAST></BROADCAST,MULTICAST></BROADCAST,MULTICAST,UP,LOWER_UP></BROADCAST,MULTICAST></LOOPBACK,UP,LOWER_UP>


测试:

通过vip10.1.6.173 3366访问cluster数据库(注意账户dave权限需要加3个ip10.1.6.203,10.1.6.205,10.1.6.173)

01 root@10.1.6.203:mgm# mysql -udave -p -h 10.1.6.173 -P 3366
02 Enter password: 
03 Welcome to the MySQL monitor.  Commands end with ; or \g.
04 Your MySQL connection id is 1344316
05 Server version: 5.5.22-ndb-7.2.6-gpl-log MySQL Cluster Community Server (GPL)
06   
07 Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
08   
09 mysql> show databases;
10 +--------------------+
11 | Database           |
12 +--------------------+
13 | information_schema | 
14 | dave              | 
15 | test              
16 +--------------------+
17 3 rows in set (0.01 sec)
18   
19 mysql>

手动分别使keepalive,haproxy,数据库挂掉.vip10.1.6.173会自动漂到10.1.6.205从上,并不影响vip的访问


通过vip,haproxy查看各节点状态

http://10.1.6.173:8888/status

keepalived+haproxy 高可用负载均衡



参考:

http://www./

http://haproxy./


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多