一、环境规划

wKiom1X6SEax6HlpAAEImIcTpPA588.jpg

  • 操作系统:CentOS6.5 x86_64

  • 内核版本:2.6.32-504.el6.x86_64

  • Nginx版本:nginx-1.8.0-1.el6.ngx.x86_64

  • Keepalived版本:keepalived-1.2.19

    前端双Nginx+Keepalived,Nginx反向代理到后端tomcat集群实现负载均衡,Keepalived实现集群高可用,主nginx故障后虚拟IP自动漂移到备nginx。

    主nginx:192.168.60.48

    备nginx:192.168.60.49

    虚拟IP:192.168.60.50

    后端tomcat集群:192.168.60.51、192.168.60.52、192.168.60.53

    后端每个主机都开启两个端口提供业务:16915、16916

二、安装

    前端两台主机分别安装nginx和keepalived。

    1)编译安装keepalived

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 安装依赖
yum  install  kernel-* gcc  make  openssl-*
# 下载keepalived-1.2.19.tar.gz
wget http: //www .keepalived.org /software/keepalived-1 .2.19. tar .gz
# 解压
tar  xvzf keepalived-1.2.19. tar .gz 
cd  keepalived-1.2.19
# 配置
. /configure  --sysconfdir= /etc  --with-kernel- dir = /usr/src/kernels/2 .6.32-504.el6.x86_64
# 编译并安装
make  &&  make  install
# 查看keepalived版本,验证安装成功
keepalived - v
# 设置开机自启动
chkconfig keepalived on

    注:用yum也可安装keepalived,不过版本要低一些。

    2)RPM包安装Nginx

    官方nginx yum源:

1
2
3
4
5
[nginx]
name=nginx repo
baseurl=http: //nginx .org /packages/centos/ $releasever/$basearch/
enabled=1
gpgcheck=0

    yum源设置好后直接安装即可:

1
2
yum  install  nginx
chkconfig nginx on

三、配置

    1)前端两台主机nginx的配置完全一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# vim /etc/nginx/conf.d/upstream.conf 
 
upstream tomcatclu_16915 {
         server 192.168.60.51:16915;
         server 192.168.60.52:16915;
         server 192.168.60.53:16915;
         ip_hash;
}
 
upstream tomcatclu_16916 {
         server 192.168.60.51:16916;
         server 192.168.60.52:16916;
         server 192.168.60.53:16916;
         ip_hash;
}
 
# vim /etc/nginx/conf.d/server.conf
 
server {
     listen 16915;
     server_name _;
 
     location / {
         proxy_pass http: //tomcatclu_16915 ;
     }
     location  /nginx_status {
         stub_status on;
         access_log off;
         allow 127.0.0.1;
         # 要允许公司ip访问nginx status
         allow 192.168.252.0 /24 ;
         deny all;
     }
}
 
server {
     listen 16916;
     server_name _;
 
     location / {
         proxy_pass http: //tomcatclu_16916 ;
     }
     location  /nginx_status {
         stub_status on;
         access_log off;
         allow 127.0.0.1;
         # 要允许公司ip访问nginx status
         allow 192.168.252.0 /24 ;
         deny all;
     }
}

    2)nginx_master的keepalived配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[root@nginx_master ~] # vim /etc/keepalived/keepalived.conf 
 
! Configuration File  for  keepalived
 
global_defs {
    router_id nginx-ha1
}
 
vrrp_script check_nginx {
     # 检查nginx状态的脚本,文章后面给出
     script  "/data/script/check_nginx.sh"
     # 执行间隔2秒
     interval 2
}
 
vrrp_instance VI_1 {
     # 两台主机都是BACKUP
     state BACKUP
     interface eth0
     # 同一keepalived集群的virtual_router_id 必须相同,默认51
     virtual_router_id 55
     # 主的优先级高
     priority 100
     advert_int 1
     # 不抢占:如果集群里已存在MASTER状态的主机,即使优先级高于MASTER也不抢占为MASTER。只在优先级高的主机上设置即可。
     nopreempt
     authentication {
         auth_type PASS
         auth_pass 1111
     }
     virtual_ipaddress {
         # 虚拟IP
         192.168.60.50
     }
     track_script {
         check_nginx
     }
}

    3)nginx_slave的keepalived配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[root@nginx_slave ~] # vim /etc/keepalived/keepalived.conf 
 
! Configuration File  for  keepalived
 
global_defs {
    router_id nginx-ha2
}
 
vrrp_script check_nginx {
     script  "/data/script/check_nginx.sh"
     interval 2
}
 
vrrp_instance VI_1 {
     state BACKUP
     interface eth0
     virtual_router_id 55
     # 备的优先级低
     priority 80
     advert_int 1
     authentication {
         auth_type PASS
         auth_pass 1111
     }
     virtual_ipaddress {
         192.168.60.50
     }
     track_script {
         check_nginx
     }
}

    4)防火墙设置

1
2
3
# iptables放行组播地址流量:
iptables -I INPUT -d 224.0.0.18 -j ACCEPT
service iptables save

    VRRP报文是通过IP多播形式发送的,组播地址224.0.0.18是VRRP报文的目的地址。
    本实验里,两个主机都是BACKUP,如果同时启动keepalived,VRRP协议通过竞选使优先级高的主机做为MASTER。如果防火墙没有允许VRRP报文通过的话,两个BACKUP都会成为MASTER,你会发现两个主机都启动了虚拟IP。
    5)部署nginx状态检查脚本check_nginx.sh

    /data/script/check_nginx.sh检查脚本内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/bash
# check nginx server status
# http://qicheng0211.blog.51cto.com
  
# nginx端口
PORTS= "16915 16916"
 
function  check_ports {
     for  port  in  $PORTS; do
         nc -z 127.0.0.1 $port |  grep  -q succeeded
         "${PIPESTATUS[1]}"  - eq  0 ] && mark=${mark}1
     done
     # 如果mark值为空说明两个端口都不通。
     # 如果mark等于1,说明有一个端口是通的。
     # 如果mark等于11,说明两个端口都是通的。
     echo  $mark
}
 
ret1=$(check_ports)
# 如果nginx端口不通,会尝试重启一次nginx
if  "$ret1"  != 11 ]; then
     /sbin/service  nginx stop
     /sbin/service  nginx start
     sleep  1
     ret2=$(check_ports)
     # 如果还是有端口不通,表示nginx服务不正常,则停掉keepalived,使VIP发生切换
     "$ret2"  != 11 ] &&  /etc/init .d /keepalived  stop
fi

    大家根据自个的环境编写nginx状态检查脚本,不一定要照搬。

    给脚本设置可执行权限:

1
chmod  +x  /data/script/check_nginx .sh

    补充一点:如果nginx恢复正常后,keepalived不能自动启动,需要编写一个脚本完成这项工作:判断nginx正常后,拉起keepalived。脚本放到cron里每分钟执行。

    6)开启keepalived的日志

    编辑/etc/sysconfig/keepalived:

1
KEEPALIVED_OPTIONS= "-D -d -S 0"

    编辑/etc/rsyslog.conf:

1
2
# 配置文件最后面加上下面一行
local0.*                                         /var/log/keepalived .log

    重启rsyslog:

1
service rsyslog restart

    按上面配置后,keepalived会把日志记录到/var/log/keepalived.log。

    7)启动服务

1
2
3
4
5
6
7
8
# 先检查nginx配置文件正确性
nginx -t
# 启动nginx服务
service nginx start
# 同时启动keepalived服务
service keepalived start
# 过一会查看虚拟IP是否在nginx_master主机上
ip a

    四、验证

    nginx_master和nginx_slave同时启动keepalived,观察日志/var/log/keepalived.log,你会发现nginx_master抢占为MASTER,绑定了虚拟IP192.168.60.50。

    nginx_master:

wKioL1X6XViz_LVZAALUyIqxLDQ217.jpg

wKioL1X6XEmwb8rbAAI2ptSMhEM234.jpg

    nginx_slave:

wKiom1X6WkGjEhJWAAIL_4Ucuas845.jpg

    我们在同网段的其他机器上去arping一下虚拟IP的MAC,发现是nginx_master eth0的mac:

wKiom1X6dZajUw0vAACljgbtW2M588.jpg

   下面我们把nginx_master的keepalived服务停掉或者重启系统,同时不断的ping虚拟IP。经过一个请求超时的间隔,虚拟IP会漂移到nginx_slave上面:

wKioL1X6XkiDyYSuAAO93j-joEs063.jpg

    nginx_slave:

wKiom1X6XDahLBXdAAH5kcUUJ0g730.jpg

    我们再去arping一下虚拟IP的MAC,发现变成了nginx_slave eth0的mac:

wKioL1X6eDeDqwTlAACuBTSgYGk191.jpg

    查看nginx_slave的日志keepalived.log,nginx_slave在成为MASTER的同时发送了免费ARP(gratuitous ARP),更新了以太网邻居的ARP快速缓存:

1
2
3
VRRP_Instance(VI_1) Entering MASTER STATE
VRRP_Instance(VI_1) setting protocol VIPs.
VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 192.168.60.50

    最后把nginx_master的keepalived服务开启,虚拟IP并没有漂移回到nginx_master,这是因为nginx_master开启了不抢占模式,即使优先级高,也不会抢占MASTER。