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

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

HAProxy+双主Keepalived_haproxy

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

下面是拓扑图

HAProxy+双主Keepalived_haproxy_02

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

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

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

HAProxy+双主Keepalived_keepalived_03

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

172.16.11.12 ha1 ha1.sysbo.net
172.16.11.13 ha2 ha2.sysbo.net
192.168.0.1 rs1 rs1.sysbo.net
192.168.0.2 rs2 rs2.sysbo.net
192.168.0.3 rs3 rs3.sysbo.net

ha1ha2中开启端口转发

[root@ha1 ~]# vim /etc/sysctl.conf
net.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 keepalived
global_defs {
notification_email {
sysadmin@sysbo.net  //定义收件人,别忘了加上你主管的名字哦
}
notification_email_from ha@sysbo.net //定义发件人邮箱
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_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,优先级大的就会被选为MASTER
advert_int 1        //通告时间
authentication {    //验证选项
auth_type PASS  //使用与共享秘钥验证
auth_pass 1111     //与共享秘钥
}
virtual_ipaddress { //定义虚拟ip
172.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中,此节点为BACKUP
interface eth0
virtual_router_id 60    //与上面不同哦,不同的虚拟ip对应不同的MAC地址
priority 99
advert_int 1
authentication {
auth_type PASS
auth_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/bash
vip=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" in
master)
notify master
/etc/rc.d/init.d/haproxy start
exit 0
;;
backup)
notify backup
/etc/rc.d/init.d/haproxy restart            //如果服务宕掉,他会重启
exit 0
;;
fault)
notify fault
exit 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_1
state BACKUP //此节点实例1为BACKUP
priority 99 //相应优先级为99
vrrp_instance VI_2
state MASTER //此节点实例2为MASTER
priority 100 //相应优先级为100

至此双主keepalived部署完成

我们接着部署HAproxy

两个节点都安装haproxy

[root@ha1 ~]# yum install haproxy –y
haproxy的配置文件一般分为全局配置(global),代理配置(defaults, frontend, backend, listen)
[root@ha1 ~]# vim /etc/haproxy/haproxy.cfg
global
log         127.0.0.1 local2    //log日志信息发往127.0.0.1 facility 为local2
chroot      /var/lib/haproxy    //是否使用chroot
pidfile     /var/run/haproxy.pid            //pid 文件存放位置
maxconn     4000       //每个haproxy 进程可以接受最大的并发连接数,等于命令选项 “-n” “ulimit –n”自动计算的结果会参照此值得设定
user        haproxy
group       haproxy
daemon  //独立守护进程
# turn on stats unix socket
stats socket /var/lib/haproxy/stats
defaults    //默认选项,如果没有做特殊说明就按着这个选项执行
mode                   http     //默认工作在7层http
log                     global   //使用全局日志
option                  httplog
option                  dontlognull
option http-server-close
option forwardfor       except 127.0.0.0/8
option                  redispatch
retries                 3
timeout http-request    10s
timeout queue           1m
timeout connect         10s
timeout client          1m
timeout server          1m
timeout http-keep-alive 10s
timeout check           10s
maxconn                 30000
listen stats    //使用状态通告
mode http
bind 0.0.0.0:1080
stats enable
stats hide-version
stats uri     /haproxyadmin?stats   //uri地址
stats realm   Haproxy\ Statistics
stats auth    admin:admin   //账号和密码
stats admin if TRUE
frontend http-in    //前端选项
bind *:80   //默认绑定80端口
mode http
log global
option httpclose    //支持长连接,服务器端关闭
option logasap
option dontlognull
capture request  header Host len 20         //抓取请求报文的前20字节
capture request  header Referer len 60
acl url_static       path_beg       -i /static /p_w_picpaths /javascript /stylesheet
//定义acl规则,如果请求uri开始 为/static /p_w_picpaths /javascript /stylesheet 就符合此此规则,此规则不区分大小写,此规则的名字叫 url_static
acl url_static       path_end       -i .jpg .jpeg .gif .png .css .js
//定义acl规则,如果请求uri的结束符为.jpg jpeg gif .png css .js将符合此规则,此规则不区分大小写,此规则名字也叫 url_static
use_backend static_servers          if url_static
//如果请求内容符合acl url_static 则将内容发往static_server
default_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端口,最大连接数为6000
backend dynamic_servers  //定义动态服务器
balance source
server rs2 172.16.11.22:80 check maxconn 1000
server rs3 192.16.11.23:80 check maxconn 1000

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

HAProxy+双主Keepalived_keepalived_04

ha1

HAProxy+双主Keepalived_keepalived_05

ha2

HAProxy+双主Keepalived_haproxy_06

HAProxy+双主Keepalived_haproxy_07

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

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