背景
接触 Nginx 也有几年了,但是以前的服务都是通过一台机器上的 Nginx 来代理,一直没使用过 Nginx 高可用方案。在严格要求高可用 HA (High Availability)的场景中,一台 Nginx 服务难免出故障,作为流量入口,单实例部署的 Nginx 服务挂掉后的后果不堪设想。今天就来体验下业界主流的结合 KeepAlived 实现的 Nginx 高可用方案(抢占模式),并在华为云的生产环境下进行实战。
KeepAlived 是基于虚拟路由冗余协议(Virtual Router Redundancy Protocol,简称 VRRP ) 协议的一款高可用软件。通常用于配置多个服务的高可用性,比如 MySQL 的高可用、 Redis 高可用、应用服务高可用等。
系统环境
[root@ecs-c8ee-0012 ~]
Linux ecs-c8ee-0012 3.10.0-1160.15.2.el7.x86_64
[root@ecs-c8ee-0012 ~]
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) )
[root@ecs-c8ee-0012 ~]
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绑定即可。
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
yum -y install openssl-devel
./configure --prefix=/usr/local/keepalived --sysconf=/etc
make && make install
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 30
# keepalived服务唯一标识,一般使用主机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
}
}
! 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 30
# keepalived服务唯一标识,一般使用主机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 进程是否存在,如果不存在,则尝试启动 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!
|