Keepalived + Nginx 实现高可用 Web 负载均
之前的文章中提到了 Nginx 作为反向代理服务器是把多个来自不同客户端的请求转发到私有网络下的各个对应的服务下,这么看来, Nginx 就是一个中转器,所有的请求都要从 Nginx 中通过。那么 Nginx 的稳定性和可用性就必然有很高的要求。
此文将介绍使用 Keepalived 对 Nginx 进行主备的高可用配置。
一、Keepalived 简要介绍
Keepalived 是一种高性能的服务器高可用或热备解决方案, Keepalived 可以用来防止服务器单点故障的发生,通过配合 Nginx 可以实现 web 前端服务的高可用。
Keepalived 以 VRRP 协议为实现基础,用 VRRP 协议来实现高可用性(HA)。 VRRP(Virtual Router Redundancy Protocol) 协议是用于实现路由器冗余的协议, VRRP 协议将两台或多台路由器设备虚拟成一个设备,对外提供虚拟路由器 IP(一个或多个),而在路由器组内部,如果实际拥有这个对外 IP 的路由器如果工作正常的话就是 MASTER,或者是通过算法选举产生, MASTER 实现针对虚拟路由器 IP 的各种网络功能,如 ARP 请求, ICMP,以及数据的转发等;其他设备不拥有该虚拟 IP,状态是 BACKUP,除了接收 MASTER 的 VRRP 状态通告信息外,不执行对外的网络功能。
当主机失效时, BACKUP 将接管原先 MASTER 的网络功能。VRRP 协议使用多播数据来传输 VRRP 数据, VRRP 数据使用特殊的虚拟源 MAC 地址发送数据而不是自身网卡的 MAC 地址, VRRP 运行时只有 MASTER 路由器定时发送 VRRP 通告信息,表示 MASTER 工作正常以及虚拟路由器 IP (组), BACKUP 只接收 VRRP 数据,不发送数据,如果一定时间内没有接收到 MASTER 的通告信息,各 BACKUP 将宣告自己成为 MASTER,发送通告信息,重新进行 MASTER 选举状态。
二、方案规划
VIP | IP | HOSTANME | Nginx 端口 | 默认主从 |
---|---|---|---|---|
192.168.174.110 | 192.168.174.200 | hadoop1 | 80 | MASTER |
192.168.174.110 | 192.168.174.201 | hadoop2 | 80 | BACKUP |
CentOS 6.9 x64
keepalived-1.2.24
nginx-1.13.0
三、Nginx 安装
四、Keepalived 安装
需在 hadoop1/hadoop2 两个节点均进行如下安装
1 下载 Keepalived
官方下载地址
http://www.keepalived.org/download.html
下载 1.2.24 版本程序到服务器
[root@hadoop1 keepalived]# pwd
/data/software/keepalived
[root@hadoop1 keepalived]# wget http://www.keepalived.org/software/keepalived-1.2.24.tar.gz
2 解压程序
[root@hadoop1 keepalived]# pwd
/data/software/keepalived
[root@hadoop1 keepalived]# ll
total 812
-rw-r--r--. 1 root root 829602 May 27 03:21 keepalived-1.2.24.tar.gz
[root@hadoop1 keepalived]# tar zxvf keepalived-2.0.0.tar.gz
3 编译安装
[root@hadoop1 keepalived]# cd keepalived-1.2.24
[root@hadoop1 keepalived-1.2.24]# pwd
/data/software/keepalived/keepalived-1.2.24
[root@hadoop1 keepalived-1.2.24]# ./configure --prefix=/usr/local/keepalived
[root@hadoop1 keepalived-1.2.24]# make && make install
4 将 keepalived 安装成 Linux 系统服务
因为没有使用 keepalived 的默认路径安装(默认是/usr/local) ,安装完成之后,需要做一些工作复制默认配置文件到默认路径
[root@hadoop1 keepalived-1.2.24]# mkdir /etc/keepalived
[root@hadoop1 keepalived-1.2.24]# cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
复制 keepalived 服务脚本到默认的地址
[root@hadoop1 keepalived-1.2.24]# cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/
[root@hadoop1 keepalived-1.2.24]# cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
[root@hadoop1 keepalived-1.2.24]# ln -s /usr/local/sbin/keepalived /usr/sbin/
[root@hadoop1 keepalived-1.2.24]# ln -s /usr/local/keepalived/sbin/keepalived /sbin/
赋予权限
[root@hadoop1 init.d]# chmod 755 /etc/init.d/keepalived
设置 keepalived 服务开机启动
chkconfig keepalived on
五、Keepalived 配置
1 MASTER 节点配置 - (hadoop1/192.168.174.200):
备份默认配置文件:
[root@hadoop1 keepalived]# pwd
/etc/keepalived
[root@hadoop1 keepalived]# cp keepalived.conf keepalived.conf.bak
清除默认配置并编辑 keepalived 配置文件:
[root@hadoop1 keepalived]#>keepalived.conf
[root@hadoop1 keepalived]# vi keepalived.conf
配置如下内容并保存退出:
! Configuration File for keepalived
global_defs {
router_id hadoop1 # hostname
}
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh" # 检测 nginx 的脚本
interval 2 # 每 2 秒检测一次
weight -20 # 如果某一个 nginx 宕机 则权重减 20
}
vrrp_instance VI_1 {
state MASTER # 状态 MASTER BACKUP
interface eth0 # 绑定的网卡
virtual_router_id 51 # 虚拟路由的 ID 号,两个节点设置必须一样
mcast_src_ip 192.168.174.200 # 本机的 IP
priority 100 # 节点优先级,值范围 0-254,MASTER 要比 BACKUP 高,按优先级值大小优先访问优先级高的
nopreempt # 优先级高的设置 nopreempt 解决异常恢复后再次抢占的问题
advert_int 1 # 组播信息发送间隔,两个节点设置必须一样,默认 1s
# 设置验证信息,两个节点必须一致
authentication {
auth_type PASS
auth_pass 1111
}
# 虚拟 IP,两个节点设置必须一样。
virtual_ipaddress {
192.168.174.110
}
# nginx 存活状态检测脚本
track_script {
chk_nginx
}
}
2 BACKUP 节点配置 - (hadoop2/192.168.174.201):
备份默认配置文件:
[root@hadoop2 keepalived]# pwd
/etc/keepalived
[root@hadoop2 keepalived]# cp keepalived.conf keepalived.conf.bak
清除默认配置并编辑 keepalived 配置文件:
[root@hadoop2 keepalived]#>keepalived.conf
[root@hadoop2 keepalived]# vi keepalived.conf
配置如下内容并保存退出:
! Configuration File for keepalived
global_defs {
router_id hadoop2 # hostname
}
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh" # 检测 nginx 的脚本
interval 2 # 每 2 秒检测一次
weight -20 # 如果某一个 nginx 宕机 则权重减 20
}
vrrp_instance VI_1 {
state BACKUP # 状态 MASTER BACKUP
interface eth0 # 绑定的网卡
virtual_router_id 51 # 虚拟路由的 ID 号,两个节点设置必须一样
mcast_src_ip 192.168.174.201 # 本机的 IP
priority 90 # 节点优先级,值范围 0-254,MASTER 要比 BACKUP 高,按优先级值大小优先访问优先级高的
advert_int 1 # 组播信息发送间隔,两个节点设置必须一样,默认 1s
# 设置验证信息,两个节点必须一致
authentication {
auth_type PASS
auth_pass 1111
}
# 虚拟 IP,两个节点设置必须一样。
virtual_ipaddress {
192.168.174.110
}
# nginx 存活状态检测脚本
track_script {
chk_nginx
}
}
注:上方的配置文件中有几处必须要改动的内容
(1) router_id hadoop1 将 hadoop1 改为配置的 MASTER 节点的主机名。
(2) mcast_src_ip 192.168.174.200 将 192.168.174.200 改为 配置的 MASTER 节点的 IP。
(3) virtual_ipaddress {192.168.174.110} 将 192.168.174.110 改为配置 keepalived 集群的两台服务器同网段且可用的 IP 作为虚拟 IP,此 IP 作为负载均衡的访问 IP,且可以配置多个。
六、编写 Nginx 状态检测脚本
编写 Nginx 状态检测脚本 /etc/keepalived/nginx_check.sh (已在 keepalived.conf 中配置)脚本要求:如果 nginx 停止运行,尝试启动,如果无法启动则杀死本机的 keepalived 进程, keepalied将虚拟 ip 绑定到 BACKUP 机器上。
新建并编译 nginx_check.sh 文件
[root@hadoop1 keepalived]# vim /etc/keepalived/nginx_check.sh
添加如下内容:
#!/bin/bash
# 设置当前服务器的 nginx 的监听端口,用于下方脚本通过端口号来准确校验 nginx 的运行状态
NGINX_PORT=80
# 校验指定端口的 nginx 服务的运行情况
function check_nginx() {
PROCESS_COUNT=`netstat -anp | grep "\<${NGINX_PORT}\>" | grep nginx | wc -l`
return ${PROCESS_COUNT}
}
check_nginx
if [ $? -eq 0 ];then
/usr/local/nginx/sbin/nginx
sleep 2
check_nginx
if [ $? -eq 0 ];then
killall keepalived
fi
fi
注:如果你的 nginx 服务的监听端口设置的不是 80 (/usr/local/nginx/conf/nginx.conf 中默认配置为 80),将 NGINX_PORT 改为对应的监听端口。
赋予执行权限
[root@hadoop1 keepalived]# chmod 755 /etc/keepalived/nginx_check.sh
七、服务启停
分别在两台服务器执行如下命令启动 keepalived
[root@hadoop1 keepalived]# service keepalived start
Starting keepalived: [ OK ]
[root@hadoop2 keepalived]# service keepalived start
Starting keepalived: [ OK ]
注:
由于在 nginx_check.sh 脚本中已经加入了 nginx 检测及启动。因此,此处可以不用启动 nginx,由 keepalived 来校验及启动。
常用命令
service keepalived start #启动服务
service keepalived stop #停止服务
service keepalived restart #重启服务
八、验证
8.1 校验 nginx/keepalived 进程
hadoop1:
[root@hadoop1 keepalived]# netstat -anp | grep nginx | grep "\<80\>"
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 48008/nginx
[root@hadoop1 keepalived]# ps -ef | grep keepalived | grep -v grep
root 53267 1 0 02:35 ? 00:00:00 keepalived -D
root 53268 53267 0 02:35 ? 00:00:00 keepalived -D
root 53269 53267 0 02:35 ? 00:00:00 keepalived -D
hadoop2:
[root@hadoop2 keepalived]# netstat -anp|grep nginx | grep "\<80\>"
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 25778/nginx
[root@hadoop2 keepalived]# ps -ef | grep keepalived | grep -v grep
root 29559 1 0 02:18 ? 00:00:00 keepalived -D
root 29560 29559 0 02:18 ? 00:00:00 keepalived -D
root 29561 29559 0 02:18 ? 00:00:00 keepalived -D
8.2 校验虚拟 IP 绑定情况
hadoop1:
[root@hadoop1 keepalived]# ip addr
hadoop1 的虚拟 IP
hadoop2:
[root@hadoop2 keepalived]# ip addr
hadoop2 的虚拟 IP
8.3 校验访问
修改两台服务器的 nginx 的 index.html 文件
hadoop1:
[root@hadoop1 keepalived]# cd /usr/local/nginx/html
[root@hadoop1 html]# vim index.html
<h1>Welcome to nginx</h1>
改为
<h1>Welcome to nginx -> hadoop1!</h1>
image.png
保存退出
hadoop2:
[root@hadoop2 keepalived]# cd /usr/local/nginx/html
[root@hadoop2 html]# vim index.html
<h1>Welcome to nginx</h1>
改为
<h1>Welcome to nginx -> hadoop2!</h1>
保存退出
修改 hadoop1 的 nginx index.htmlHTTP 访问
在浏览器中输入 http://192.168.174.110:80 访问,如下显示,则表示访问 keepalived 负载均衡正常,因为默认优先访问 master 节点,因此在 master 节点(hadoop1/192.168.174.130)nginx 服务正常情况下,将一直访问到的是 master 节点的服务
修改 hadoop2 的 nginx index.html测试
停止 master 节点的 keepalived 服务
[root@hadoop1 html]# service keepalived stop
Stopping keepalived: [ OK ]
[root@hadoop1 html]# ps -ef | grep keepalived
root 58172 115469 0 02:51 pts/1 00:00:00 grep keepalived
再访问 http://192.168.174.110/
停止 master 节点的 keppalived 服务启动 master 节点的 keepalived 服务
[root@hadoop1 html]# service keepalived start
Starting keepalived: [ OK ]
[root@hadoop1 html]# ps -ef|grep keepalived | grep -v grep
root 58421 1 0 02:53 ? 00:00:00 keepalived -D
root 58423 58421 0 02:53 ? 00:00:00 keepalived -D
root 58424 58421 0 02:53 ? 00:00:00 keepalived -D
再次访问 http://192.168.174.110/
启动 master 节点的 keepalived 服务可以看到,访问到的又是 master 节点的 nginx 服务了。
至此,Keepalived + Nginx 实现高可用 Web 负载均衡便安装与配置完成了。
附录:keepalived 配置文件说明
引用自:http://blog.csdn.net/xyang81/article/details/52554398
keepalived 服务安装完成之后,后面的主要工作就是在 keepalived.conf 文件中配置 HA 和负载均衡。
一个功能比较完整的常用的 keepalived 配置文件,主要包含三块:
- 全局定义块、VRRP实例定义块和虚拟服务器定义块。
- 全局定义块是必须的,如果keepalived只用来做ha,
- 虚拟服务器是可选的。下面是一个功能比较完整的配置文件模板:
#全局定义块
global_defs {
# 邮件通知配置
notification_email {
email1
email2
}
notification_email_from email
smtp_server host
smtp_connect_timeout num
lvs_id string
router_id string ## 标识本节点的字条串,通常为hostname
}
#VRRP 实例定义块
vrrp_sync_group string {
group {
string
string
}
}
vrrp_instance string {
state MASTER|BACKUP
virtual_router_id num
interface string
mcast_src_ip @IP
priority num
advert_int num
nopreempt
smtp_alert
lvs_sync_daemon_interface string
authentication {
auth_type PASS|AH
auth_pass string
}
virtual_ipaddress { # Block limited to 20 IP addresses @IP
@IP
@IP
}
}
#虚拟服务器定义块
virtual_server (@IP PORT)|(fwmark num) {
delay_loop num
lb_algo rr|wrr|lc|wlc|sh|dh|lblc
lb_kind NAT|DR|TUN
persistence_timeout num
protocol TCP|UDP
real_server @IP PORT {
weight num
notify_down /path/script.sh
TCP_CHECK {
connect_port num
connect_timeout num
}
}
real_server @IP PORT {
weight num
MISC_CHECK {
misc_path /path_to_script/script.sh(or misc_path “/path_to_script/script.sh <arg_list>”)
}
}
real_server @IP PORT {
weight num
HTTP_GET|SSL_GET {
url {
# You can add multiple url block path alphanum
digest alphanum
}
connect_port num
connect_timeout num
nb_get_retry num
delay_before_retry num
}
}
}
配置说明
一、全局定义块
1、email通知(notification_email、smtp_server、smtp_connect_timeout):
用于服务有故障时发送邮件报警,可选项,不建议用。需要系统开启sendmail服务,
建议用第三独立监控服务,如用nagios全面监控代替。
2、lvs_id:lvs负载均衡器标识,在一个网络内,它的值应该是唯一的。
3、router_id:用户标识本节点的名称,通常为hostname
4、花括号{}:用来分隔定义块,必须成对出现。如果写漏了,
keepalived运行时不会得到预期的结果。由于定义块存在嵌套关系,
因此很容易遗漏结尾处的花括号,这点需要特别注意。
二、VRRP实例定义块
vrrp_sync_group:同步vrrp级,用于确定失败切换(FailOver)包含的路由实例个数。
即在有2个负载均衡器的场景,一旦某个负载均衡器失效,需要自动切换到另外一个负载均衡器的实例是哪
group:至少要包含一个vrrp实例,vrrp实例名称必须和vrrp_instance定义的一致
vrrp_instance:vrrp实例名
1> state:实例状态,只有MASTER 和 BACKUP两种状态,并且需要全部大写。
抢占模式下,其中MASTER为工作状态,BACKUP为备用状态。当MASTER所在的服务器失效时,
BACKUP所在的服务会自动把它的状态由BACKUP切换到MASTER状态。
当失效的MASTER所在的服务恢复时,BACKUP从MASTER恢复到BACKUP状态。
2> interface:对外提供服务的网卡接口,即VIP绑定的网卡接口。
如:eth0,eth1。当前主流的服务器都有2个或2个以上的接口(分别对应外网和内网),在选择网卡接口时,一定要核实清楚。
3> mcast_src_ip:本机IP地址
4> virtual_router_id:虚拟路由的ID号,每个节点设置必须一样,
可选择IP最后一段使用,相同的 VRID 为一个组,他将决定多播的 MAC 地址。
5> priority:节点优先级,取值范围0~254,MASTER要比BACKUP高
6> advert_int:MASTER与BACKUP节点间同步检查的时间间隔,单位为秒
7> lvs_sync_daemon_inteface:负载均衡器之间的监控接口,
类似于 HA HeartBeat 的心跳线。但它的机制优于 Heartbeat,因为它没有“裂脑”这个问题,
它是以优先级这个机制来规避这个麻烦的。在 DR 模式中,
lvs_sync_daemon_inteface与服务接口interface使用同一个网络接口
8> authentication:验证类型和验证密码。类型主要有 PASS、AH 两种,通常使用PASS类型,
据说AH使用时有问题。验证密码为明文,同一vrrp 实例MASTER与BACKUP使用相同的密码才能正常通信。
9> smtp_alert:有故障时是否激活邮件通知
10> nopreempt:禁止抢占服务。默认情况,当MASTER服务挂掉之后,
BACKUP自动升级为MASTER并接替它的任务,当MASTER服务恢复后,
升级为MASTER的BACKUP服务又自动降为BACKUP,
把工作权交给原MASTER。当配置了nopreempt,
MASTER从挂掉到恢复,不再将服务抢占过来。
11> virtual_ipaddress:虚拟IP地址池,可以有多个IP,每个IP占一行,不需要指定子网掩码。注意:这个IP必须与我们的设定的vip保持一致。
三、虚拟服务器virtual_server定义块
virtual_server:定义一个虚拟服务器,这个ip是virtual_ipaddress中定义的其中一个,后面一个空格,然后加上虚拟服务的端口号。
1> delay_loop:健康检查时间间隔,单位:秒
2> lb_algo:负载均衡调度算法,互联网应用常用方式为wlc或rr
3> lb_kind:负载均衡转发规则。包括DR、NAT、TUN 3种,一般使用路由(DR)转发规则。
4> persistence_timeout:http服务会话保持时间,单位:秒
5> protocol:转发协议,分为TCP和UDP两种
real_server:真实服务器IP和端口,可以定义多个
1> weight:负载权重,值越大,转发的优先级越高
2> notify_down:服务停止后执行的脚本
3> TCP_CHECK:服务有效性检测
* connect_port:服务连接端口
* connect_timeout:服务连接超时时长,单位:秒
* nb_get_retry:服务连接失败重试次数
* delay_before_retry:重试连接间隔,单位:秒