KeepAlived+Nginx实践Nginx高可用方案

高可用性 HA(High Availability)指的是通过尽量缩短因日常维护操作(计划)和突发的系统崩溃(非计划)所导致的停机时间,以提高系统和应用的可用性。HA 系统是目前企业防止核心计算机系统因故障停机的最有效手段。

实现 HA 的方式,一般采用两台或者多台机器同时完成一项功能,比如数据库服务器,平常只有一台机器对外提供服务,另一台机器作为热备,当这台机器出现故障时,自动动态切换到另一台热备的机器。

Keepalived软件起初是专为LVS(Linux Virtual Server)负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后来又加入了可以实现高可用的VRRP (Virtual Router Redundancy Protocol ,虚拟路由器冗余协议)功能。因此,Keepalived除了能够管理LVS软件外,还可以作为其他服务(例如:Nginx、Haproxy、MySQL等)的高可用解决方案软件。

Keepalived对高可用服务之间的故障切换转移,是通过 VRRP 来实现的。在 Keepalived服务正常工作时,主 Master节点会不断地向备节点发送(多播的方式)心跳消息,用以告诉备Backup节点自己还活着,当主 Master节点发生故障时,就无法发送心跳消息,备节点也就因此无法继续检测到来自主 Master节点的心跳了,于是调用自身的接管程序,接管主Master节点的 IP资源及服务。而当主 Master节点恢复时,备Backup节点又会释放主节点故障时自身接管的IP资源及服务,恢复到原来的备用角色。

Keepalived的作用是检测服务器的状态,当服务器宕机或工作出现故障,Keepalived将检测到并将服务器集群中剔除,选择其他服务器代替该服务器的工作;当服务器恢复工作正常,Keepalived检测到自动将服务器加入服务器集群。

核心原理:使用两台Nginx做反向代理服务器,当其中一台Nginx宕机之后,仍能用另一台来工作,两台Nginx之间用keeplived来监测心跳。

KeepAlived+Nginx实践Nginx高可用方案

配置要求:两台服务器,三个同网段的IP地址。

关闭系统防火墙
必须关闭,否则会导致无法访问。

systemctl stop firewalld
systemctl disable firewalld

检测系统模块加载
ip_vs模块系统默认没有自动加载,可以通过。

lsmod | grep ip_vs

命令查看一下,如果没有任何输出则表示ip_vs模块并没有被内核加载,那必须手动加载一下:

modprobe ip_vs
modprobe ip_vs_wrr

写到/etc/rc.local文件中实现开机加载此模块。

安装NGINX
两台服务器安装nginx

配置启动脚本

脚本路径:/lib/systemd/system/nginx.service

[Unit]
Description=nginx
After=network.target
  
[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true
  
[Install]
WantedBy=multi-user.target

启动并设置开启自启

systemctl start nginx
systemctl enable nginx

安装keepalived

两台都需要安装

yum install -y keepalived

#方法二:
cd /usr/local
wget https://www.keepalived.org/software/keepalived-2.2.8.tar.gz 
#解压文件
tar -zxvf keepalived-2.2.8.tar.gz
#编译
cd keepalived-2.2.8/
#--prefix 指定安装地址
#/usr/local/keepalived/ 安装的目录,不要和解压文件一个目录,不然可能报错
./configure --prefix=/usr/local/keepalived/
#编译并安装
make && make install

运行前配置

cp /usr/local/keepalived-2.2.8/keepalived/etc/init.d/keepalived /etc/init.d/
mkdir /etc/keepalived
cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
cp /usr/local/keepalived-2.2.8/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
cp /usr/local/keepalived/sbin/keepalived /usr/sbin/

配置文件修改
检测脚本路径:/usr/local/sbin/check_ng.sh
设置权限:744

#!/bin/bash
#时间变量,用于记录日志
d=`date --date today +%Y-%m-%d_%H:%M:%S`
echo "$d nginx status check" >> /var/log/check_ng.log
#计算nginx进程数量
n=`ps -C nginx --no-heading|wc -l`
#如果进程为0,则启动nginx,并且再次检测nginx进程数量,
#如果还为0,说明nginx无法启动,此时需要关闭keepalived
if [ $n -eq "0" ]; then
  echo "$d nginx stop retry again" >> /var/log/check_ng.log
  systemctl start nginx
  sleep 2
  n2=`ps -C nginx --no-heading|wc -l`
  if [ $n2 -eq "0"  ]; then
      echo "$d nginx down,keepalived will stop" >> /var/log/check_ng.log
      systemctl stop keepalived
  fi
fi

双机高可用方法目前分为两种:

1)Nginx+keepalived 双机主从模式:即前端使用两台服务器,一台主服务器和一台热备服务器,正常情况下,主服务器绑定一个公网虚拟IP,提供负载均衡服务,热备服务器处于空闲状态;当主服务器发生故障时,热备服务器接管主服务器的公网虚拟IP,提供负载均衡服务;但是热备服务器在主机器不出现故障的时候,永远处于浪费状态,对于服务器不多的网站,该方案不经济实惠,但是对于主从服务器配置差异很大的机器可以作为一种选择(从服务器就临时用一下嘛)

2)Nginx+keepalived 双机主主模式:即前端使用两台负载均衡服务器,互为主备,且都处于活动状态,同时各自绑定一个公网虚拟IP,提供负载均衡服务;当其中一台发生故障时,另一台接管发生故障服务器的公网虚拟IP(这时由非故障机器一台负担所有的请求)。这种方案,经济实惠,非常适合于当前架构环境。一般来说,两个机器的性能都要相差无几,能够提供正常的业务访问量。

双机主从模式

实验环境配置如下:

192.168.223.128: nginx + keepalived master 主

192.168.223.129: nginx + keepalived backup 从

192.168.223.128(主节点配置)

vim /etc/keepalived/keepalived.conf
-------------------------------------------------------
! Configuration File for keepalived
global_defs {
   #不与其他节点重名即可
   router_id nginx_router
}
​
# 检测nginx是否运行
vrrp_script chk_nginx {
        script "/etc/keepalived/nginx_check.sh" #心跳执行的脚本
        interval 2  #(检测脚本执行的间隔,单位是秒)
        weight -20 #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -20
        fall 2   #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间)
        rise 1  #检测1次成功就算成功。但不修改优先级
}
​
vrrp_instance nginx {
    state BACKUP #此处不设置为MASTER,通过priority来竞争master
    interface eth0 #网卡名称
    virtual_router_id 51 #同一个keepalived集群的virtual_router_id相同
    priority 100 # 权重,master要大于slave
    advert_int 1 # 主备通讯时间间隔
    authentication { #设置验证类型和密码,MASTER和BACKUP必须使用相同的密码才能正常通信
        auth_type PASS
        auth_pass 1111
    }
    #与上方nginx运行状况检测呼应
    track_script {
        chk_nginx
    }
    # 虚拟ip地址(VIP,一个尚未占用的内网ip即可,可以多个)
    virtual_ipaddress {
        192.168.223.130
        192.168.223.131
    }
}
​

192.168.223.129(从),就改个priority

vim /etc/keepalived/keepalived.conf
​
global_defs {
   #不与其他节点重名即可
   router_id nginx_router
}
​
# 检测nginx是否运行
vrrp_script chk_nginx {
        script "/etc/keepalived/nginx_check.sh" #心跳执行的脚本
        interval 2  #(检测脚本执行的间隔,单位是秒)
        weight -20 #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -20
        fall 2   #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间)
        rise 1  #检测1次成功就算成功。但不修改优先级
}
​
vrrp_instance nginx {
    state BACKUP #此处不设置为MASTER,通过priority来竞争master
    interface eth0 #网卡名称
    virtual_router_id 51 #同一个keepalived集群的virtual_router_id相同
    priority 90 # 权重,master要大于slave
    advert_int 1 # 主备通讯时间间隔
    authentication { #设置验证类型和密码,MASTER和BACKUP必须使用相同的密码才能正常通信
        auth_type PASS
        auth_pass 1111
    }
    #与上方nginx运行状况检测呼应
    track_script {
        chk_nginx
    }
    # 虚拟ip地址(VIP,一个尚未占用的内网ip即可,可以多个)
    virtual_ipaddress {
        192.168.223.130
        192.168.223.131
    }
}

由于keepalived只检测本机和他机keepalived是否正常并实现VIP的漂移,而如果本机nginx出现故障则不会漂移VIP,所以编写脚本来判断本机nginx是否正常,如果发现NginX不正常,重启之。等待3秒再次校验,仍然失败则不再尝试,关闭keepalived,其他主机此时会接管VIP;

1)经过前面的配置,如果master主服务器的keepalived停止服务,slave从服务器会自动接管VIP对外服务; 一旦主服务器的keepalived恢复,会重新接管VIP。 但这并不是我们需要的,我们需要的是当NginX停止服务的时候能够自动切换。
2)keepalived支持配置监控脚本,我们可以通过脚本监控NginX的状态,如果状态不正常则进行一系列的操作,最终仍不能恢复NginX则杀掉keepalived,使得从服务器能够接管服务。

防止出现脑裂现象

脑裂(split-brain):指在一个高可用(HA)系统中,当联系着的两个节点断开联系时,本来为一个整体的系统,分裂为两个独立节点,这时两个节点开始争抢共享资源,结果会导致资源瓜分甚至“各自为政”,系统混乱,数据损坏。

对于无状态服务的HA,无所谓脑裂不脑裂;但对有状态服务(比如MySQL)的HA,必须要严格防止脑裂:

1)或者共享资源被瓜分、两边"服务"都起不来了;

2)或者两边"服务"都起来了,但同时读写"共享存储",导致数据损坏(常见如数据库轮询着的联机日志出错)。

双机双主模式

主机

注意修改:脚本地址、网卡名称、虚拟IP地址

! Configuration File for keepalived
global_defs {
   router_id nginx_router
}
​
# 检测nginx是否运行
vrrp_script chk_nginx {
        script "/etc/keepalived/nginx_check.sh" #心跳执行的脚本
        interval 2  #(检测脚本执行的间隔,单位是秒)
        weight -20 #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -20
        fall 2   #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间)
        rise 1  #检测1次成功就算成功。但不修改优先级
}
​
vrrp_instance nginx {
    state BACKUP #此处不设置为MASTER,通过priority来竞争master
    interface eth0 #网卡名称
    virtual_router_id 51 #virtual_router_id相同漂移相同的VIP
    priority 100 # 权重,master要大于slave
    advert_int 1 # 主备通讯时间间隔
    authentication { #设置验证类型和密码,同一个VIP实例,MASTER和BACKUP必须使用相同的密码才能正常通信
        auth_type PASS
        auth_pass 1111
    }
    #与上方nginx运行状况检测呼应
    track_script {
        chk_nginx
    }
    # 虚拟ip地址(VIP,一个尚未占用的内网ip即可,可以多个)
    virtual_ipaddress {
        192.168.223.130
    }
}
#增加的备虚拟节点
vrrp_instance nginx2 { 
    state BACKUP
    interface eth0
    virtual_router_id 52 #注意不要与上方virtual_router_id相同
    priority 90 #一定要比上方的优先级低
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    #与上方nginx运行状况检测呼应
    track_script {
        chk_nginx
    }
    virtual_ipaddress {
        192.168.223.131
    }
}
​

备机

注意修改:脚本地址、网卡名称、虚拟IP地址

! Configuration File for keepalived
global_defs {
   router_id nginx_router
}
​
# 检测nginx是否运行
vrrp_script chk_nginx {
        script "/etc/keepalived/nginx_check.sh" #心跳执行的脚本
        interval 2  #(检测脚本执行的间隔,单位是秒)
        weight -20 #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -20
        fall 2   #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间)
        rise 1  #检测1次成功就算成功。但不修改优先级
}
​
vrrp_instance nginx {
    state BACKUP #此处不设置为MASTER,通过priority来竞争master
    interface eth0 #网卡名称
    virtual_router_id 51 #同一个keepalived集群的virtual_router_id相同
    priority 90 # 权重,master要大于slave
    advert_int 1 # 主备通讯时间间隔
    authentication { #设置验证类型和密码,MASTER和BACKUP必须使用相同的密码才能正常通信
        auth_type PASS
        auth_pass 1111
    }
    #与上方nginx运行状况检测呼应
    track_script {
        chk_nginx
    }
    # 虚拟ip地址(VIP,一个尚未占用的内网ip即可,可以多个)
    virtual_ipaddress {
        192.168.223.130
    }
}
#增加的主虚拟节点
vrrp_instance nginx2 {
    state BACKUP
    interface eth0
    virtual_router_id 52 #注意不要与上方virtual_router_id相同
    priority 100 #一定要比上方的优先级高
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    #与上方nginx运行状况检测呼应
    track_script {
        chk_nginx
    }
    virtual_ipaddress {
        192.168.223.131
    }
}
​

启动并设置开启自启

systemctl start keepalived
systemctl enable keepalived

Tags: nginx

添加新评论