对于负载均衡器来说,常用的有硬件解决方案,如CitrixNetscaler,F5Bigip,还有软件级别的解决方案,如对于大型网站来说的LVS,对于流量不是很大的网站来说,HAproxy还有Nginx,HAproxy+Keepalived可以达到亿pv/日,而且还非常稳定,所以对于中小企业来说是个不错的选择。

Keepalived是常见的高可用解决方案之一,原创的目的是为了LVSDirectorServer的高可用,当然也可也用于其他服务的高可用,如nginx,HAProxy等服务,Keepaliaved使用VRRP协议,使得虚拟IP和虚拟MAC在可个物理节点间流动。同样通过脚本可以使得其他资源在各节点上流动。

Keepalived主要有两个进程,一个为VRRP负责资源的迁移,另外一个为Checkers.负责健康状态的检查,还有一个watchDog的进程,负责监控VRRPCheckers是否存活。

我们来实现一下HAProxy与双主keepalived结合

ROLE

IP

HostName

虚拟ip

172.16.11.15

172.16.11.16

HAProxy节点1

172.16.11.12eth0

ha1.sysbo.net

HAProxy节点2

172.16.11.13eth0

ha2.sysbo.net

后端nginx节点1(静态)

172.16.11.21

rs1.sysbo.net

后端nginx节点2(动态)

172.16.11.22

rs2.sysbo.net

后端nginx节点3(动态)

172.16.11.23

rs3.sysbo.net

下面是拓扑图

先来解释下,为什么要双主keepalived,怎样实现双主keepalived

对于这个架构来说,keepalived的虚拟IP就是暴露在最外边给客户端访问的,所以使用在DNS添加上两个A记录,可以用负载均衡的作用,两台keepalived主机互为主备,即添加了可用性又有负载均衡的作用,而实现的过程仅仅是添加两个实例就可以了。

在来看下下面所定义的代码中,keepalived的工作流程,有图有真相

在每个节点/etc/hosts文件中添加如下行

172.16.11.12 ha1 ha1.sysbo.net172.16.11.13 ha2 ha2.sysbo.net192.168.0.1 rs1 rs1.sysbo.net192.168.0.2 rs2 rs2.sysbo.net192.168.0.3 rs3 rs3.sysbo.net

ha1ha2中开启端口转发

[root@ha1 ~]# vim /etc/sysctl.confnet.ipv4.ip_forward = 1[root@ha1 ~]# sysctl –p

ha1ha2中安装keepavlived

[root@ha1 ~]# yum install keepalived –y[root@ha1 ~]# vim /etc/keepalived/keepalived.conf! Configuration File for keepalivedglobal_defs {notification_email {sysadmin@sysbo.net  //定义收件人,别忘了加上你主管的名字哦}notification_email_from ha@sysbo.net //定义发件人邮箱smtp_server 127.0.0.1smtp_connect_timeout 30router_id LVS_DEVEL}vrrp_script chk_haproxy{        //检查haproxy是否存活的脚本script "killall -0 haproxy"        //killall -0 是代价最低的interval 1            //检查频率weight -2       //检查失败,权重-2}vrrp_instance VI_1 {        //定义第一个实例state MASTER       //这个主机在这个实例中为主节点interface eth0  //通知端口virtual_router_id 59    //每个实例有不同的vitrual_route id,这个是虚拟MAC地址的最后一位priority 100       //优先级 100,优先级大的就会被选为MASTERadvert_int 1        //通告时间authentication {    //验证选项auth_type PASS  //使用与共享秘钥验证auth_pass 1111     //与共享秘钥}virtual_ipaddress { //定义虚拟ip172.16.11.15/16 dev eth0 label eth0:0  //漂移的虚拟ip地址将会在eth0:0 上}track_script {  //定义在这个实例中使用的脚本chk_haproxy}modify_master "/etc/keepalived/notify.sh master" //如果检测到此节点变为了master/etc/keepalived/notify.sh ,并且给一个master参数modify_backup "/etc/keepalived/notify.sh backup"modify_fault  "/etc/keepalived/notify.sh fault"}vrrp_instance VI_2 {state BACKUP    //注意,在实例2中,此节点为BACKUPinterface eth0virtual_router_id 60    //与上面不同哦,不同的虚拟ip对应不同的MAC地址priority 99advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {172.16.11.16/16 dev eth0 label eth0:0}track_script {chk_haproxy}modify_master "/etc/keepalived/notify2.sh master"modify_backup "/etc/keepalived/notify2.sh backup"modify_fault  "/etc/keepalived/notify2.sh fault"}

定义故障通知脚本/etc/keepalived/notify.sh

#!/bin/bashvip=172.16.11.15 //notify.sh对应vrrp_INSTANCE V1_1,对应v1_2再复制一份与此相同的脚本,VIP=172.16.11.16 即可contact='root@localhost'notify() {mailsubject="`hostname` to be $1: $vip floating"mailbody="`date '+%F %H:%M:%S'`: vrrp transition, `hostname` changed to be $1"echo $mailbody | mail -s "$mailsubject" $contact}case "$1" inmaster)notify master/etc/rc.d/init.d/haproxy startexit 0;;backup)notify backup/etc/rc.d/init.d/haproxy restart            //如果服务宕掉,他会重启exit 0;;fault)notify faultexit 0;;*)echo 'Usage: `basename $0` {master|backup|fault}'exit 1;;esac

复制上面内容至ha2

[root@ha1 keepalived]# scp keepalived.conf ha2:/etc/keepalived/[root@ha1 keepalived]# scp notify.sh ha2:/etc/keepalived/[root@ha1 keepalived]# scp notify2.sh ha2:/etc/keepalived/

修改ha2中的内容

vrrp_instance VI_1state BACKUP //此节点实例1为BACKUPpriority 99 //相应优先级为99vrrp_instance VI_2state MASTER //此节点实例2为MASTERpriority 100 //相应优先级为100

至此双主keepalived部署完成

我们接着部署HAproxy

两个节点都安装haproxy

[root@ha1 ~]# yum install haproxy –yhaproxy的配置文件一般分为全局配置(global),代理配置(defaults, frontend, backend, listen)[root@ha1 ~]# vim /etc/haproxy/haproxy.cfggloballog         127.0.0.1 local2    //log日志信息发往127.0.0.1 facility 为local2chroot      /var/lib/haproxy    //是否使用chrootpidfile     /var/run/haproxy.pid            //pid 文件存放位置maxconn     4000       //每个haproxy 进程可以接受最大的并发连接数,等于命令选项 “-n” “ulimit –n”自动计算的结果会参照此值得设定user        haproxygroup       haproxydaemon  //独立守护进程# turn on stats unix socketstats socket /var/lib/haproxy/statsdefaults    //默认选项,如果没有做特殊说明就按着这个选项执行mode                   http     //默认工作在7层httplog                     global   //使用全局日志option                  httplogoption                  dontlognulloption http-server-closeoption forwardfor       except 127.0.0.0/8option                  redispatchretries                 3timeout http-request    10stimeout queue           1mtimeout connect         10stimeout client          1mtimeout server          1mtimeout http-keep-alive 10stimeout check           10smaxconn                 30000listen stats    //使用状态通告mode httpbind 0.0.0.0:1080stats enablestats hide-versionstats uri     /haproxyadmin?stats   //uri地址stats realm   Haproxy\ Statisticsstats auth    admin:admin   //账号和密码stats admin if TRUEfrontend http-in    //前端选项bind *:80   //默认绑定80端口mode httplog globaloption httpclose    //支持长连接,服务器端关闭option logasapoption dontlognullcapture request  header Host len 20         //抓取请求报文的前20字节capture request  header Referer len 60acl url_static       path_beg       -i /static /p_w_picpaths /javascript /stylesheet//定义acl规则,如果请求uri开始 为/static /p_w_picpaths /javascript /stylesheet 就符合此此规则,此规则不区分大小写,此规则的名字叫 url_staticacl url_static       path_end       -i .jpg .jpeg .gif .png .css .js//定义acl规则,如果请求uri的结束符为.jpg jpeg gif .png css .js将符合此规则,此规则不区分大小写,此规则名字也叫 url_staticuse_backend static_servers          if url_static//如果请求内容符合acl url_static 则将内容发往static_serverdefault_backend dynamic_servers//其他发往dynmic_servers,这样就实现了动静分离backend static_servers //定义静态服务器组balance roundrobin  //是用roundrobin 轮训算法server rs1 172.16.11.21:80 check maxconn 6000//imgsrv1 是这个后端静态服务器的名字,对应的IP为192.168.0.1,使用80端口,最大连接数为6000backend dynamic_servers  //定义动态服务器balance sourceserver rs2 172.16.11.22:80 check maxconn 1000server rs3 192.16.11.23:80 check maxconn 1000

在生产环境中动态服务器应该部署一样的东西,静态服务器应该是图片,css样式表等

ha1

ha2

最后要写明白的一点怎样保持用户seesion,对于DNS,本来就有TTL值可以保证用户解析到同一IP,而对于haproxybackend中使用的souce算法,也保证使其始终发往同一服务器。

至此HAproxy+双主Keepalived就告一段落,我还会继续努力,做最好的自己