实现nginx的高可用
一、简要介绍
nginx作为一款企业级的代理服务器,在各种企业事业单位中,均有广泛的使用,尤其是在前后端分离的项目中,nginx作为路由转发的功能是非常常用的。在一些流量比较大的项目中,为了应对高并发的场景,后端服务往往采用集群部署,这时候,就需要使用到nginx的负载均衡功能,从而避免应用节点的单节点故障问题。
那么针对nginx的单节点故障问题,我们在实际生产中又应当如何避免呢?我们可以通过nginx+keepalived的高可用集群方案来避免nginx的单节点故障问题,从而大幅度提高nginx的稳定性和可靠性。
Keepalived软件主要是实现网站、数据库、业务系统高可用性、自动切换的,主要是基于类似交换机制OSI七层模型:3(网络层)、4(传输层)、7层(应用层)来实现健康检查的,当监测到其中一台服务器宕机或者异常,能够切换到另外一台。
Keepalived软件程序主要的功能有两个:
- 健康检测
基于类似交换机制OSI七层模型:3(网络层:IP)、4(传输层:IP+PORT)、7层(应用层:FTP、HTTP APP)来实现健康检查; - VRRP漂移
基于VRRP(虚拟路由冗余协议)路由协议来实现两台主机之间高可用,其中包括:MASTER和BACKUP,当MASTER宕机,能够自动化切换至BACKUP,从而让用户持续的访问;
下面,本文将简单介绍一下nginx+keepalived高可用集群的两种常用方案,即nginx+keepalived主从和双主模式。
二、主从模式
这种方案,使用一个VIP地址,前端使用2台机器,一台做主,一台做备,但同时只有一台机器工作,另一台备机在主机器不出现故障的时候,永远处于浪费状态,对于服务器不多的网站,该方案并不经济实惠。
网络架构图如下:
2.1 架构规划
根据网络架构图,服务器规划如下:
角色 | ip地址 | vip地址 | 软件 | nginx端口 | OS |
主 | 192.168.10.101 | 192.168.10.108 | nginx+keepalived | 80 | centos 7.9 |
从 | 192.168.10.102 | 192.168.10.108 | nginx+keepalived | 80 | centos 7.9 |
2.2 软件安装
2.2.1 nginx
前往nginx官方网站(http://nginx.org/en/download.html)下载最新版nginx,进行编译安装。以1.23.2为例:
# 根据实际情况安装依赖
yum install -y libxml2 libxslt libxslt-devel libxml2-devel gd gd-devel geoip-devel pcre-devel openssl-devel
# 解压并安装nginx
tar -zxvf nginx-1.23.2.tar.gz
cd nginx-1.23.2
./configure \
--prefix=/usr/local/nginx \
--with-threads \
--with-file-aio \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_xslt_module \
--with-http_image_filter_module \
--with-http_geoip_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_auth_request_module \
--with-http_random_index_module \
--with-http_degradation_module \
--with-http_slice_module \
--with-http_stub_status_module \
--with-stream \
--with-stream_ssl_module \
--with-stream_ssl_preread_module
make
make install
本文中,我们不探讨nginx的负载均衡功能,仅仅演示nginx+keepalived的高可用性,故而以nginx静态页面来进行展示:
#设置简单页面,区分两个nginx服务器
vim /usr/local/nginx/html/index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx! 192.168.10.101</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx! 192.168.10.102</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
分别访问两个Nginx,http://192.168.10.101,http://192.168.10.102。页面如下:
2.2.2 keepalived
在centos7.9中,自带了keepalived安装包,可以采用yum方式安装,有其他版本需求的,可以自行下载源码安装包进行安装。
yum install -y keepalived
2.3 主从配置
2.3.1 keepalived
2.3.1.1 配置主服务器
cd /etc/keepalived
true > keepalived.conf
vim keepalived.conf
在keepalived.conf中添加以下内容:
! Configuration File for keepalived
############################ 全局配置 #############################
global_defs {
# 定义管理员邮件地址,表示keepalived在发生诸如切换操作时需要发送email通知,以及email发送给哪些邮件地址,可以有多个,每行一个
notification_email {
#设置报警邮件地址,可以设置多个,每行一个。 需开启本机的sendmail服务
137708020@qq.com
}
#keepalived在发生诸如切换操作时需要发送email通知地址,表示发送通知的邮件源地址是谁
notification_email_from 137708020@qq.com
#指定发送email的smtp服务器
smtp_server 127.0.0.1
#设置连接smtp server的超时时间
smtp_connect_timeout 30
#运行keepalived的机器的一个标识,通常可设为hostname。故障发生时,发邮件时显示在邮件主题中的信息。
router_id nginx-1
}
############################ VRRPD配置 #############################
# 定义chk_nginx脚本,脚本执行间隔10秒,权重-10,检测nginx服务是否在运行。有很多方式,比如进程,用脚本检测等等
vrrp_script chk_nginx {
#这里通过脚本监测
script "/data/chk_nginx.sh"
#脚本执行间隔,每2s检测一次
interval 2
#脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -5
weight -10
#检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间)
fall 2
#检测1次成功就算成功。但不修改优先级
rise 1
}
#定义vrrp实例,VI_1 为虚拟路由的标示符,自己定义名称,keepalived在同一virtual_router_id中priority(0-255)最大的会成为master,也就是接管VIP,当priority最大的主机发生故障后次priority将会接管
vrrp_instance VI_1 {
#指定keepalived的角色,MASTER表示此主机是主服务器,BACKUP表示此主机是备用服务器。注意这里的state指定instance(Initial)的初始状态,就是说在配置好后,这台服务器的初始状态就是这里指定的,
#但这里指定的不算,还是得要通过竞选通过优先级来确定。如果这里设置为MASTER,但如若他的优先级不及另外一台,那么这台在发送通告时,会发送自己的优先级,另外一台发现优先级不如自己的高,
#那么他会就回抢占为MASTER
state MASTER
#指定HA监测网络的接口。与本机 IP 地址所在的网络接口相同,可通过ip addr 查看
interface ens33
#当该keepalived切换为MASTER状态时,执行下面的脚本
notify_master /data/chk_master.sh
#当该keepalived切换为BACKUP状态时,执行下面的脚本
notify_backup /data/chk_backup.sh
# 发送多播数据包时的源IP地址,这里注意了,这里实际上就是在哪个地址上发送VRRP通告,这个非常重要,
#一定要选择稳定的网卡端口来发送,这里相当于heartbeat的心跳端口,如果没有设置那么就用默认的绑定的网卡的IP,也就是interface指定的IP地址
mcast_src_ip 192.168.10.101
#虚拟路由标识,这个标识是一个数字,同一个vrrp实例使用唯一的标识。即同一vrrp_instance下,MASTER和BACKUP必须是一致的
virtual_router_id 51
#定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER的优先级必须大于BACKUP的优先级
priority 100
#设定MASTER与BACKUP负载均衡器之间同步检查的时间间隔,单位是秒
advert_int 1
#设置验证类型和密码。主从必须一样
authentication {
#设置vrrp验证类型,主要有PASS和AH两种
auth_type PASS
#设置vrrp验证密码,在同一个vrrp_instance下,MASTER与BACKUP必须使用相同的密码才能正常通信
auth_pass 1111
}
#VRRP HA 虚拟地址 如果有多个VIP,继续换行填写
#设置VIP,它随着state变化而增加删除,当state为master的时候就添加,当state为backup的时候则删除,由优先级决定
virtual_ipaddress {
192.168.10.108
}
#执行nginx检测脚本。注意这个设置不能紧挨着写在vrrp_script配置块的后面(实验中碰过的坑),否则nginx监控失效!!
track_script {
#引用VRRP脚本,即在 vrrp_script 部分指定的名字。定期运行它们来改变优先级,并最终引发主备切换。
chk_nginx
}
}
2.3.1.2 配置从服务器
cd /etc/keepalived
true > keepalived.conf
vim keepalived.conf
在keepalived.conf中添加以下内容,与主服务器除了priority优先级不一样外,其他保持一致:
! Configuration File for keepalived
global_defs {
notification_email {
137708020@qq.com
}
notification_email_from 137708020@qq.com
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id nginx-2
}
vrrp_script chk_nginx {
script "/data/chk_nginx.sh"
interval 2
weight -10
fall 2
rise 1
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
notify_master /data/chk_master.sh
notify_backup /data/chk_backup.sh
mcast_src_ip 192.168.10.102
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.108
}
track_script {
chk_nginx
}
}
2.3.2 检测脚本设计
在主从服务器,均创建以下检测脚本。
cd /data
#创建nginx检测脚本
vim chk_nginx.sh
###############################################
#!/bin/bash
A=`ps -C nginx --no-header |wc -l`
if [ $A -eq 0 ];then
/usr/local/nginx/sbin/nginx
sleep 3
if [ `ps -C nginx --no-header |wc -l` -eq 0 ]
then
systemctl stop keepalived
fi
fi
###############################################
chmod +x chk_nginx.sh
2.4 启动
在主从服务器上,分别启动nginx和keepalived服务:
/usr/local/nginx/sbin/nginx
systemctl start keepalived
#检查ip绑定情况
ip addr show ens33
2.5 验证
2.5.1 验证
分别访问主、从和vip地址:
主:
从:
VIP:
可以看到,访问vip地址其实就是访问了主节点。
也可以通过网卡命令查询:
ip addr show ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:f0:6d:88 brd ff:ff:ff:ff:ff:ff
inet 192.168.10.101/24 brd 192.168.10.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet 192.168.10.108/32 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::ca30:6fa0:7f41:3eec/64 scope link noprefixroute
valid_lft forever preferred_lft forever
2.5.2 切换
- nginx
关闭主节点上的nginx服务,观察主节点的nginx是否会被自动重启。如果重启则说明chk_nginx脚本执行成功,如果nginx未能重启,则应当执行脚本中的命令关闭keepalived服务。 - keepalived
关闭主节点的keepalived服务,观察vip是否会绑定到从服务器上。
重启主节点的keepalived服务,观察vip是否会绑定到主服务器上。
三、互为主从
这种方案,使用两个VIP地址,前端使用2台机器,互为主备,同时有两台机器工作,当其中一台机器出现故障,两台机器的请求转移到一台机器负担,非常适合于生产架构环境。
网络架构图如下:
3.1 架构规划
根据网络架构图,服务器规划如下:
角色 | ip地址 | vip地址 | 软件 | nginx端口 | OS |
主从 | 192.168.10.101 | 192.168.10.108 | nginx+keepalived | 80 | centos 7.9 |
从主 | 192.168.10.102 | 192.168.10.109 | nginx+keepalived | 80 | centos 7.9 |
3.2 软件安装
软件安装与前面2.2章节一模一样,此处不再赘述。
3.3 互为主从配置
3.3.1 keepalived配置
在双主模式中,大致内容与主从模式一样,需要额外添加以下内容,添加一个新的VIP,需要注意的是初始的服务器角色是反的。
3.3.1.1 配置主服务器
在原有的keepalived.conf下增加以下配置
#定义vrrp实例,VI_2 为虚拟路由的标示符,自己定义名称,keepalived在同一virtual_router_id中priority(0-255)最大的会成为master,也就是接管VIP,当priority最大的主机发生故障后次priority将会接管
vrrp_instance VI_2 {
#指定keepalived的角色,MASTER表示此主机是主服务器,BACKUP表示此主机是备用服务器。注意这里的state指定instance(Initial)的初始状态,就是说在配置好后,这台服务器的初始状态就是这里指定的,
#但这里指定的不算,还是得要通过竞选通过优先级来确定。如果这里设置为MASTER,但如若他的优先级不及另外一台,那么这台在发送通告时,会发送自己的优先级,另外一台发现优先级不如自己的高,
#那么他会就回抢占为MASTER
state BACKUP
#指定HA监测网络的接口。与本机 IP 地址所在的网络接口相同,可通过ip addr 查看
interface ens33
#当该keepalived切换为MASTER状态时,执行下面的脚本
notify_master /data/chk_master.sh
#当该keepalived切换为BACKUP状态时,执行下面的脚本
notify_backup /data/chk_backup.sh
# 发送多播数据包时的源IP地址,这里注意了,这里实际上就是在哪个地址上发送VRRP通告,这个非常重要,
#一定要选择稳定的网卡端口来发送,这里相当于heartbeat的心跳端口,如果没有设置那么就用默认的绑定的网卡的IP,也就是interface指定的IP地址
mcast_src_ip 192.168.10.101
#虚拟路由标识,这个标识是一个数字,同一个vrrp实例使用唯一的标识。即同一vrrp_instance下,MASTER和BACKUP必须是一致的
virtual_router_id 52
#定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER的优先级必须大于BACKUP的优先级
priority 90
#设定MASTER与BACKUP负载均衡器之间同步检查的时间间隔,单位是秒
advert_int 1
#设置验证类型和密码。主从必须一样
authentication {
#设置vrrp验证类型,主要有PASS和AH两种
auth_type PASS
#设置vrrp验证密码,在同一个vrrp_instance下,MASTER与BACKUP必须使用相同的密码才能正常通信
auth_pass 1111
}
#VRRP HA 虚拟地址 如果有多个VIP,继续换行填写
#设置VIP,它随着state变化而增加删除,当state为master的时候就添加,当state为backup的时候则删除,由优先级决定
virtual_ipaddress {
192.168.10.109
}
#执行nginx检测脚本。注意这个设置不能紧挨着写在vrrp_script配置块的后面(实验中碰过的坑),否则nginx监控失效!!
track_script {
#引用VRRP脚本,即在 vrrp_script 部分指定的名字。定期运行它们来改变优先级,并最终引发主备切换。
chk_nginx
}
}
3.3.1.2 配置从服务器
在原有的keepalived.conf下增加以下配置
vrrp_instance VI_2 {
state MASTER
interface ens33
notify_master /data/chk_master.sh
notify_backup /data/chk_backup.sh
mcast_src_ip 192.168.10.102
virtual_router_id 52
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.109
}
track_script {
chk_nginx
}
}
3.3.2 检测脚本设计
在主从服务器,均创建以下检测脚本。
cd /data
#创建nginx检测脚本
vim chk_nginx.sh
###############################################
#!/bin/bash
counter=$(ps -ef|grep nginx | grep -v 'grep'|wc -l)
if [ "${counter}" = "0" ]; then
/usr/local/nginx/sbin/nginx || true
sleep 2
counter=$(ps -ef|grep nginx | grep -v 'grep'|wc -l)
if [ "${counter}" = "0" ]; then
systemctl stop keepalived
fi
fi
###############################################
chmod +x chk_nginx.sh
3.4 启动
在主从服务器上,分别启动nginx和keepalived服务:
/usr/local/nginx/sbin/nginx
systemctl start keepalived
#检查ip绑定情况
ip addr show ens33
3.5 验证
分别访问主、从和两个vip地址,以及分别停止两个节点的nginx和keepalived服务进行验证。不再赘述。
四、附加脚本
- nginx_rsync.sh
执行方式:后台,nohup sh nginx_rsync.sh 该脚本只有一台主机在后台执行,此外执行改脚本需要提前配置ssh互信免密登录。
#!/bin/bash
ip_address="192.168.10.101"
inotify_cmd="inotifywait -mrq -e modify,create,attrib,move,delete /usr/local/nginx/"
rsync_cmd="rsync -azH --delete /usr/local/nginx/ root@${ip_address}:/usr/local/nginx/"
$inotify_cmd | while read DIRECTORY EVENT FILE
do
if [ $(pgrep rsync | wc -l) -le 0 ];then
$rsync_cmd
ssh root@${ip_address} "/usr/local/nginx/sbin/nginx -t"
if [ $? -eq 0 ];then
ssh root@${ip_address} "/usr/local/nginx/sbin/nginx -s reload"
fi
fi
done
PS:本文件同步脚本引用自
- chk_master.sh
在keepalived配置文件中配置,当发生主从切换时被调用执行,发送的内容和发送方式根据实际需要进行调整。
#!/bin/bash
time=$(date +%Y-%m-%d-%H-%M)
echo “$time nginx-2已故障停机,VIP飘逸至nginx-1!”|mail -s nginx VIP飘逸提醒 137708020@qq.com
- chk_backup.sh
#!/bin/bash
time=$(date +%Y-%m-%d-%H-%M)
echo “$time nginx-1已故障停机,VIP飘逸至nginx-2!”|mail -s nginx VIP飘逸提醒 137708020@qq.com
- chk_nginx.sh
nginx健康检查,在keepalived配置文件中配置。
#!/bin/bash
A=`ps -C nginx --no-header |wc -l`
if [ $A -eq 0 ];then
/usr/local/nginx/sbin/nginx
sleep 3
if [ `ps -C nginx --no-header |wc -l` -eq 0 ]
then
systemctl stop keepalived
fi
fi