背景
接触 Nginx
也有几年了,但是以前的服务都是通过一台机器上的 Nginx
来代理,一直没使用过 Nginx
高可用方案。在严格要求高可用 HA
(High Availability)的场景中,一台 Nginx
服务难免出故障,作为流量入口,单实例部署的 Nginx
服务挂掉后的后果不堪设想。今天就来体验下业界主流的结合 KeepAlived
实现的 Nginx
高可用方案(抢占模式),并在华为云的生产环境下进行实战。
KeepAlived
是基于虚拟路由冗余协议(Virtual Router Redundancy Protocol,简称 VRRP
) 协议的一款高可用软件。通常用于配置多个服务的高可用性,比如 MySQL
的高可用、 Redis
高可用、应用服务高可用等。
系统环境
[root@ecs-c8ee-0012 ~]# uname -a
Linux ecs-c8ee-0012 3.10.0-1160.15.2.el7.x86_64 #1 SMP Wed Feb 3 15:06:38 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
[root@ecs-c8ee-0012 ~]# cat /proc/version
Linux version 3.10.0-1160.15.2.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) ) #1 SMP Wed Feb 3 15:06:38 UTC 2021
[root@ecs-c8ee-0012 ~]# cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
-
Nginx 1.20.1
-
KeepAlived 2.2.4
资源准备
以2台服务器、3个IP地址(2台服务器的局域网IP以及1个虚拟IP;如果要通过公网访问,则还需要一个公网IP)为例。
IP地址
说明
192.168.0.91
Master的IP
192.168.0.207
Backup的IP
192.168.0.8
虚拟IP
整体架构
虚拟IP是什么?
使用 KeepAlived
实现 Nginx
的高可用,我们面临的第一个问题便是:
什么是虚拟IP?为什么需要虚拟IP?
关于 什么是虚拟IP?
,这个要从 Nginx
的高可用这个初心说起,根据我们的经验与直觉,要让 Nginx
能够高可用,那必然不只一个实例,那么假设我们再加一台主机并运行 Nginx
,这下就有两台主机上跑了 Nginx
服务,并代理了相同的业务服务。这时候问题来了,当前有了两个请求入口,那客户端到底该访问哪个 Nginx
?显然,客户端是不知道该访问哪个服务的(因为有两台主机,两个IP)。。
此时, KeepAlived
闪亮登场,其具体的实现原理我们按下不表,可以简单地理解为: KeepAlived
的基本功能就是换IP,说得专业一点叫 IP漂移
,这样前面那个 那客户端到底该访问哪个Nginx? 的问题就迎刃而解了,即我们在每个运行 Nginx
的主机上同时再装一个 KeepAlived
,客户端使用虚拟IP来访问,借助 KeepAlived
的 换IP
功能,一旦发现当前的 Nginx
主机无法使用,则进行 换IP
操作,将 IP漂移
到一个 Nginx
可用的主机上。因此,所谓的 虚拟IP
就是对外的唯一IP,就是用来漂移的,根据具体的 KeepAlived
服务状态,可能在这台机器上,也可能在别的机器上。 IP漂移
, 漂移这个词很是形象。
虚拟IP怎么来的?
接着,便是面临第二个问题:
如何获取虚拟IP?
如果你用的是本地虚拟机,那么虚拟IP可以设置为一个未被使用的内网IP即可。这里我使用华为云提供的虚拟私有云服务(毕竟是实战嘛~~),在子网下申请虚拟IP,并绑定到我们用到的两台主机实例。
- 虚拟私有云服务-子网
- 申请虚拟IP
- 此时虚拟IP还不能直接访问
- 绑定虚拟IP至我们用到的两台主机实例
在实际生产环境中,如果想通过公网IP访问,那么将公网IP与我们申请的虚拟IP绑定即可。
KeepAlived
Nginx
的安装与配置本文忽略。其实,如果已经有反向代理的单实例 Nginx
服务,无需做任何改动,将其配置复制到其他备用机器上即可, KeepAlived
的安装与配置对已有的 Nginx
服务没有影响。
KeepAlived下载安装
下载地址:https://www.keepalived.org/download.html
由于需要在涉及高可用的两台服务器上都需要安装配置 KeepAlived
服务,建议使用命令广播的方式在多台机器上并行操作,省时高效,可以使用 XShell
或者 Electerm
,推荐 Electerm
。
cd /opt
# 解压
tar -zxvf keepalived-2.2.4.tar.gz
# 重命名
mv keepalived-2.2.4 keepalived
# 切换目录,配置安装目录
cd keepalived
./configure --prefix=/usr/local/keepalived --sysconf=/etc
# 报错,确实SSL依赖,安装即可
yum -y install openssl-devel
./configure --prefix=/usr/local/keepalived --sysconf=/etc
# 以上操作会提示:*** WARNING - this build will not support IPVS with IPv6. Please install libnl/libnl-3 dev libraries to support IPv6 with IPVS.根据需要安装依赖即可。
# 构建
make && make install
KeepAlived配置
-
MASTER
上KeepAlived
配置信息如下:! Configuration File for keepalived
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30keepalived服务唯一标识,一般使用主机IP作为区分
router_id LVS_DEVEL-249
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}vrrp_script check_nginx {
script “/etc/keepalived/nginx_check.sh” # 定时检测Nginx状态的脚本
interval 2 # 2秒检测一次
timeout 10 # 超时时间
weight -20
}vrrp_instance VI_1 {
# 主
state MASTER
interface eth0
virtual_router_id 51
priority 100 # 涉及主备的选举方式,越大优先级越高
advert_int 1
# 校验信息,节点间要求一致
authentication {
auth_type PASS
auth_pass 1111
}
# 虚拟IP,节点间要求一致
virtual_ipaddress {
192.168.0.8
}
# 配置监测脚本
track_script {
check_nginx
}
} -
BACKUP
上KeepAlived
配置信息如下:! Configuration File for keepalived
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30keepalived服务唯一标识,一般使用主机IP作为区分
router_id LVS_DEVEL-69
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}vrrp_script check_nginx {
script “/etc/keepalived/nginx_check.sh” # 定时检测Nginx状态的脚本
interval 2 # 2秒检测一次
timeout 10 # 超时时间
weight -20
}vrrp_instance VI_1 {
# 备
state BACKUP
interface eth0
virtual_router_id 51
priority 90 # 涉及主备的选举方式,越大优先级越高,备机比主机小即可
advert_int 1
# 校验信息,节点间要求一致
authentication {
auth_type PASS
auth_pass 1111
}
# 虚拟IP,节点间要求一致
virtual_ipaddress {
192.168.0.8
}
# 配置监测脚本
track_script {
check_nginx
}
} -
nginx_check脚本
先检查 Nginx
进程是否存在,如果不存在,则尝试启动 Nginx
服务,并休眠等待3秒(这是为了避免多次启动,导致资源浪费),然后再次检查 Nginx
进程是否存在,如果依然不存在 Nginx
进程,则停止 KeepAlived
服务,进行IP漂移,让其他备机接管 Nginx
的代理服务。
#!/bin/bash
x=`ps -C nginx --no-heading | wc -l`
if [ $x -eq 0 ];then
systemctl start nginx
sleep 3
x=`ps -C nginx --no-heading | wc -l`
if [ $x -eq 0 ];then
systemctl stop keepalived
fi
fi
KeepAlived启动
分别在准备好的两台机器上启动 KeepAlived
服务。
# 启动
systemctl start keepalived.service
# 开机自启
systemctl enable keepalived.service
高可用测试
一开始的状态如下:
IP地址
说明
192.168.0.91
Master的IP
192.168.0.207
Backup的IP
192.168.0.8
虚拟IP
两种方式验证
一、通过虚拟IP在任一台主机上访问: curl http://192.168.0.8
,会返回 Nginx
默认页面,我这里的华为云返回了系统信息页面,为了区分不同的主机,我事先编辑了默认页面,添加了一行内网IP, vim /usr/share/nginx/html/index.html
。
二、分别在两台主机上执行 ip addr show
,查看 eth0
下是否有虚拟IP地址信息,即虚拟IP是否有绑定到当前主机的 eth0
网卡上。
停掉MASTER上的Nginx
停止 Master
上的 Nginx
服务,通过 curl http://192.168.0.8
或者 ip addr show
发现 Master
的IP没有变,即虚拟IP没有发生漂移。这是因为我们有一个自动监测 Nginx
服务状态的脚本,一旦监测到 Nginx
服务挂掉,则尝试重启 Nginx
,显然这时候重启成功了。
停掉MASTER上的KeepAlived
停掉 Master
上的 KeepAlived
,则无论 Master
上的 Nginx
服务是否在运行,通过 curl http://192.168.0.8
或者 ip addr show
发现 Master
的IP从 192.168.0.91
变为 192.168.0.207
,虚拟IP漂移成功, Backup
成功接管上位成为 Master
。
Note:此时,相当于将 192.168.0.91
这台 Master
主机关掉了,与上述效果是一致的。
恢复一开始MASTER上停掉的KeepAlived
恢复 192.168.0.91
(一开始的 Master
)上的 KeepAlived
,通过 curl http://192.168.0.8
或者 ip addr show
发现 Master
的IP从 192.168.0.207
变为 192.168.0.91
,虚拟IP漂移成功, 昔日的王者 Master
成功接管再次恢复 Master
地位。
Note:之所以曾经的 Master
会重新夺回 Master
地位,是因为采用了抢占模式;若采用非抢占模式,主备机的 state
都应配置为 BACKUP
,则上述这种情况下,虚拟IP还是在 192.168.0.207
上绑定。一般地,在生产环境下建议使用非抢占模式,这样可以避免因虚拟IP频繁漂移而导致服务短暂的中断。
小总结
至此,结合华为云虚拟IP,基于两台主机、一个虚拟IP的 Nginx
高可用集群服务搭建成功,可用性大大提高;根据实际生产需要可自行添加多台备机,如果想通过公网IP访问,那么将公网IP与我们申请的虚拟IP绑定即可。
If you have any questions or any bugs are found, please feel free to contact me.
Your comments and suggestions are welcome!