Nginx+Keepalived实现高可用Web负载均衡

Posted by Yancy on 2016-05-22

Nginx+Keepalived实现高可用Web负载均衡

一、需求场景:

通过之前的一篇文章:

Nginx+Tomcat实现负载均衡,我们已经能通过Nginx来实现Tomcat应用的负载均衡,但是单个的Nginx会存在单点隐患,如果Nginx挂掉,那么全部的Tomcat应用都将变得不可用,所以实现Nginx的高可用是必不可少的一步。

二、说明

  • 高可用 HA(High Availability),简单讲就是:我某个应用挂了,自动有另外应用起来接着扛着,致使整个服务对外来看是没有中断过的。这里的重点就是不中断,致使公司整个业务能不断进行中,把影响减到最小,赚得更多。
  • 因为要不中断,所以我们就需要用到了 Keepalived。Keepalived 一般不会单独使用,基本都是跟负载均衡软件(LVS、HAProxy、Nginx)一起工作来达到集群的高可用效果。

  • Keepalived 有双主、主备方案

  • 常用词:
    • 心跳:Master 会主动给 Backup 发送心跳检测包以及对外的网络功能,而 Backup 负责接收 Master 的心跳检测包,随时准备接管主机。为什么叫心跳不知道,但是挺形象的,心跳同步。
    • 选举:Keepalived 配置的时候可以指定各台主机优先级,Master 挂了,各台 Backup 要选举出一个新的 Master。
  • Keepalived

三、搭建

  • 软件版本:

    • Nginx:1.8.1
    • Keepalived:1.2.20
    • JDK:8u72
    • Tomcat:8.0.32
  • 部署环境(下文中以第几台来代表这些主机):

    • 虚拟 IP(VIP):192.168.1.50
    • 第一台主机:Nginx 1 + Keepalived 1 == 192.168.1.120(Master)
    • 第二台主机:Nginx 2 + Keepalived 2 == 192.168.1.121(Backup)
    • 第三台主机:Tomcat 1 == 192.168.1.122(Web 1)
    • 第四台主机:Tomcat 2 == 192.168.1.123(Web 2)

四、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
安装依赖:
# sudo yum install -y gcc openssl-devel popt-devel
上传或下载 keepalived & 解压包:cd /opt/setups/;
# tar zxvf keepalived-1.2.20.tar.gz
编译:
# cd /opt/setups/keepalived-1.2.20 ;
# ./configure --prefix=/usr/local/keepalived
编译安装:
# make && make install
Keepalived 设置服务和随机启动复制配置文件到启动脚本目录:
# cp /usr/program/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/keepalived
# cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
# ln -s /usr/local/sbin/keepalived /usr/sbin/
# ln -s /usr/local/keepalived/sbin/keepalived /sbin/
设置keepalived服务开机启动:
# chkconfig keepalived on
增加权限
# chmod +x /etc/init.d/keepalived

Keepalived 配置

1
2
3
4
5
6
添加环境变量:vim /etc/profile
KEEPALIVED_HOME=/usr/local/keepalived
PATH=$PATH:$KEEPALIVED_HOME/sbin
export KEEPALIVED_HOME
export PATH
  • 刷新环境变量:source /etc/profile
  • 检测环境变量:keepalived -v
1
2
3
vim /usr/local/keepalived/etc/sysconfig/keepalived
把 14 行的:KEEPALIVED_OPTIONS="-D",改为:
KEEPALIVED_OPTIONS="-D -f /usr/local/keepalived/etc/keepalived/keepalived.conf"

第一、二台主机配置(两台在 Keepalived 配置上稍微有不一样):

1
2
3
4
5
6
7
8
9
健康监测脚本(我个人放在:/opt/bash 目录下):[nginx_check.sh](Keepalived-Settings/nginx_check.sh)
健康监测脚本添加执行权限:
chmod 755 /opt/bash/nginx_check.sh
运行监测脚本,看下是否有问题:
sh /opt/bash/nginx_check.sh,如果没有报错,则表示改脚本没有问题.
这个脚本很重要,如果脚本没法用,在启用 Keepalived 的时候可能会报:Keepalived_vrrp[5684]: pid 5959 exited with status 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
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# (重点)
upstream tomcatCluster {
server 192.168.1.122:8080 weight=1;
server 192.168.1.123:8080 weight=1;
}
# (重点)
server {
listen 80;
server_name 192.168.1.50;
location / {
proxy_pass http://tomcatCluster;
index index.html index.htm;
}
}
}

4.1 修改keepalived配置文件

cat /etc/init.d/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
! Configuration File for keepalivedglobal_defs {
keepalived 自带的邮件提醒需要开启 sendmail 服务。建议用独立的监控或第三方 SMTP
router_id edu-proxy-01 ## 标识本节点的字条串,通常为 hostname }
keepalived 会定时执行脚本并对脚本执行的结果进行分析,动态调整 vrrp_instance 的优先级。如果 脚本执行结果为 0,并且 weight 配置的值大于 0,则优先级相应的增加。如果脚本执行结果非 0,并且 weight 配置的值小于 0,则优先级相应的减少。其他情况,维持原本配置的优先级,即配置文件中 priority 对应 的值。
vrrp_script chk_nginx {script "/etc/keepalived/nginx_check.sh"
interval 2 ## 检测时间间隔weight -20 ## 如果条件成立,权重-20}
检测 nginx 状态的脚本路径
定义虚拟路由,VI_1 为虚拟路由的标示符,自己定义名称
vrrp_instance VI_1 {state MASTER
## 主节点为 MASTER,对应的备份节点为 BACKUPinterface eth1
## 绑定虚拟 IP 的网络接口,与本机 IP 地址所在的网络接口相同,我的是 eth1 virtual_router_id 51
## 虚拟路由的 ID 号,两个节点设置必须一样,可选 IP 最后一段使用, 相同的 VRID 为一个组,他将决定多播的 MAC 地址,eth1值的获取可以在机器上执行ifconfig命令得到mcast_src_ip 192.168.1.51
## 本机 IP 地址priority 100
## 节点优先级,值范围 0-254,MASTER 要比 BACKUP 高 nopreempt
## 优先级高的设置 nopreempt 解决异常恢复后再次抢占的问题 advert_int 1
## 组播信息发送间隔,两个节点设置必须一样,默认 1s
## 设置验证信息,两个节点必须一致authentication { auth_type PASSauth_pass 1111
## 真实生产,按需求对应该过来 }
将 track_script 块加入 instance 配置块.
track_script {chk_nginx
## 执行 Nginx 监控的服务}
虚拟 IP 池, 两个节点设置必须一样
virtual_ipaddress {192.168.1.50
## 虚拟 ip,可以定义多个} }

Keepalived 配置文件编辑(第一、二台配置稍微不同,不同点具体看下面重点说明)

编辑:vim /usr/local/keepalived/etc/keepalived/keepalived.conf

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
52
53
54
55
56
! Configuration File for keepalived
# 全局配置
global_defs {
# 邮箱通知配置,keepalived 在发生切换时需要发送 email 到的对象,一行一个
notification_email {
#acassen@firewall.loc
#failover@firewall.loc
#sysadmin@firewall.loc
}
# 指定发件人
#notification_email_from Alexandre.Cassen@firewall.loc
# 指定smtp服务器地址
#smtp_server 192.168.200.1
# 指定smtp连接超时时间,单位秒
#smtp_connect_timeout 30
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
vrrp_strict
}
# (重点)脚本监控实现
vrrp_script check_nginx {
# 运行脚本
script "/opt/bash/nginx_check.sh"
# 时间间隔,2秒
interval 2
# 权重
weight 2
}
vrrp_instance VI_1 {
# (重点)Backup 机子这里是设置为:BACKUP
state MASTER
interface eth0
virtual_router_id 51
# (重点)Backup 机子要小于当前 Master 设置的 100,建议设置为 99
priority 100
# Master 与 Backup 负载均衡器之间同步检查的时间间隔,单位是秒
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
# (重点)配置虚拟 IP 地址,如果有多个则一行一个
virtual_ipaddress {
192.168.1.50
}
# (重点)脚本监控调用
track_script {
check_nginx
}
}

附录:

192.168.31.146(MASTER节点)的keepalived.conf

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
! Configuration File for keepalived
global_defs {
router_id dreyer-zk-03
}
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh"
interval 2
weight -20
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 146
mcast_src_ip 192.168.1.120
priority 100
nopreempt
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_nginx
}
virtual_ipaddress {
192.168.31.111
}
}

192.168.31.154(BACKUP节点)的keepalived.conf

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
! Configuration File for keepalived
global_defs {
router_id dreyer-zk-01
}
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh"
interval 2
weight -20
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 146
mcast_src_ip 192.168.1.121
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_nginx
}
virtual_ipaddress {
192.168.31.111
}
}

nginx_check.sh(Nginx状态检测脚本)

1
2
3
4
5
6
7
8
#!/bin/bash
A=ps -C nginx –no-header |wc -lif [ $A -eq 0 ];then
/usr/local/nginx/sbin/nginx
sleep 2
if [ps -C nginx --no-header |wc -l-eq 0 ];then
killall keepalived
fi
fi

脚本大意为:检查是否有nginx进程,如果没有,那么就启动nginx,启动后睡眠2秒,再检查是否有nginx的进程,如果没有的话,那么就杀掉keepalived的全部进程(杀掉进程后keepalived才能进行重新选举)

启动各自服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
四台机子都停掉防火墙:service iptables stop
先启动两台 Tomcat:
sh /usr/program/tomcat8/bin/startup.sh
tail -200f /usr/program/tomcat8/logs/catalina.out
检查两台 Tomcat 是否可以单独访问,最好给首页加上不同标识,好方便等下确认是否有负载.
http://192.168.1.122:8080
http://192.168.1.123:8080
启动两台 Nginx 服务:/usr/local/nginx/sbin/nginx
启动两台 Keepalived 服务:service keepalived start
查看 Master 和 Backup 两台主机的对应日志:
tail -f /var/log/messages

高可用测试

模拟 Keepalived 挂掉

关闭Master主机的Keepalived,查看 MasterBackup两台主机的对应日志:

1
tail -f /var/log/messages

关闭服务:

1
service keepalived stop

如果第二台机接管了,则表示成功
重新开启 Master 主机的 Keepalived,查看 Master 和 Backup 两台主机的对应日志:

1
tail -f /var/log/messages

重启服务:service keepalived restart

  • 如果第一台机重新接管了,则表示成功
  • 模拟 Nginx 挂掉
  • 关闭 Master 主机的 Nginx,查看 Master 和 Backup 两台主机的对应日志:
1
tail -f /var/log/messages

关闭服务:/usr/local/nginx/sbin/nginx -s stop
如果第二台机接管了,则表示成功
重新开启 Master 主机的 Nginx,查看 Master 和 Backup 两台主机的对应日志:

1
tail -f /var/log/messages
  • 重启 Nginx 服务:/usr/local/nginx/sbin/nginx -s reload
  • 重启 Keepalived 服务:service keepalived restart
  • 如果第一台机重新接管了,则表示成功
  • 可以优化的地方,改为双主热备,监控脚本上带有自启动相关细节,后续再进行。
  • 日志中常用的几句话解释:

    1
    2
    3
    4
    5
    - `Entering to MASTER STATE`,变成 Master 状态
    - `Netlink reflector reports IP 192.168.1.50 added`,一般变为 Master 状态,都要重新加入虚拟 IP,一般叫法叫做:虚拟 IP 重新漂移到 Master 机子上
    - `Entering BACKUP STATE`,变成 Backup 状态
    - `Netlink reflector reports IP 192.168.1.50 removed`,一般变为 Backup 状态,都要移出虚拟 IP,一般叫法叫做:虚拟 IP 重新漂移到 Master 机子上
    - `VRRP_Script(check_nginx) succeeded`,监控脚本执行成功

资料