NGINX+KEEPALIVED实现NGINX高可用集群

一 简介

nginx作为一款企业级的代理服务器,在各种场景下均有广泛的使用,尤其是在前后端分离的项目中,nginx作为路由转发的功能是非常常用的。在一些流量比较大的项目中,为了应对高并发的场景,后端服务往往采用集群部署,这时候,就需要使用到nginx的负载均衡功能,从而避免应用节点的单节点故障问题。

那么问题又来了,nginx的单点问题怎么解决?

我们可以通过nginx+keepalived的高可用集群方案来避免nginx的单节点故障问题,从而大幅度提高nginx的稳定性和可靠性。

Keepalived的作用是检测服务器的状态,如果有一台web服务器、数据库服务器宕机,或工作出现故障,Keepalived将检测到后,会将有故障的web服务器或者数据库服务器从系统中剔除,当服务器工作正常后Keepalived自动将web、数据库服务器加入到服务器群中。

Keepalived软件程序主要的功能有两个:

1)健康检测 基于类似交换机制OSI七层模型:3(网络层:IP)、4(传输层:IP+PORT)、7层(应用层:FTP、HTTP APP)来实现健康检查;

2)VRRP漂移 基于VRRP(虚拟路由冗余协议)路由协议来实现两台主机之间高可用,其中包括:MASTER和BACKUP,当MASTER宕机,能够自动化切换至BACKUP,从而让用户持续的访问;

二 规划

IP地址主机名软件vipOS
11.0.1.131jie01nginx+keepalived11.0.1.140Euler 21.10
11.0.1.137jie02nginx+keepalived11.0.1.140Euler 21.10

三 部署

3.1 nginx 部署

说明:我这里部署的版本为1.26版本,使用脚本部署

[root@jie01 weihu]# cat install_nginx.sh 
#!/bin/bash
#
#******************************************************************************************
#Author:                a_jie
#QQ:                    1484011523
#Date:                  2024-05-26
#FileName:              install_nginx.sh
#URL:                   xxxxxxHAHAxxxxxxx
#Description:           The test script
#Copyright (C):         wujunjie 2024 All rights reserved
#******************************************************************************************

NGINX_VERSION=1.26.0
NGINX_FILE=nginx-${NGINX_VERSION}.tar.gz
NGINX_URL=http://nginx.org/download/
NGINX_INSTALL_DIR=/usr/local/nginx
NGINX_DIR=`echo $NGINX_FILE | sed -rn 's/^(.*[0-9]).*/\1/p'`
SRC_DIR=/home/weihu/src
USER=nginx
SYSTEM_TYPE=`sed -rn 's/^ID="(.*)"/\1/p' /etc/os-release`
SYSTEM_VERSION=`sed -rn 's/^VERSION_ID="(.*)"/\1/p' /etc/os-release`
CPU=`lscpu |sed -rn 's/^CPU: +([0-9])/\1/p'`

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$1" && $MOVE_TO_COL
    echo -n "["
    if [ $2 = "success" -o $2 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "    
    elif [ $2 = "failure" -o $2 = "1"  ] ;then 
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo 
}






check () {
      if [ -d "$NGINX_INSTALL_DIR" ]; then
                  color "nginx 已安装,请卸载后再安装" 1; exit; 
      fi

      cd ${SRC_DIR}
      if [  -e ${NGINX_FILE} ];then
              color "NGINX源码包已准备好" 0
      else
              color 'NGINX源码包不存在,现在开始下载' 0
              wget ${NGINX_URL}${NGINX_FILE}
              [ $? -ne 0 ] && { color "下载 ${NGINX_FILE}${TAR}文件失败" 1; exit; }
      fi
}


install_nginx () {
    color "开始安装 nginx" 0
#    if id ${USER}  &> /dev/null 2>&1;then
#       color "${USER} 用户已存在" 1 
#    else
#       useradd -s /sbin/nologin -r ${USER}
#       color "创建 ${USER} 用户" 0 
#    fi
       color "开始安装 nginx 依赖包" 0

    if [ $SYSTEM_TYPE == "centos" ] ;then
            if [[ $SYSTEM_VERSION =~ ^7 ]];then
                yum -y  install  gcc  make pcre-devel openssl-devel zlib-devel perl-ExtUtils-Embed
            elif [[ $SYSTEM_VERSION =~ ^8 ]];then
                yum -y  install make gcc-c++ libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed 
            else 
               color '不支持此centos系统! 请确认版本信息'  1
        fi

    elif [ $SYSTEM_TYPE == "bclinux"  ];then
        if [[ $SYSTEM_VERSION =~ 21.10 ]];then
               #yum -y  install gcc make gcc-c++ libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
               yum -y install gcc gcc-c++ pcre pcre-devel openssl openssl-devel zlib zlib-devel gd gd-devel perl-ExtUtils-Embed
        elif [[ $SYSTEM_VERSION =~ 22.10 ]];then
           #yum -y  install make gcc-c++ libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
               yum -y install gcc gcc-c++ pcre pcre-devel openssl openssl-devel zlib zlib-devel gd gd-devel perl-ExtUtils-Embed
        else
                color '不支持此bclinux系统! 请确认版本信息'  1
        fi
    else
        echo "不支持的系统类型! 请检查 SYSTEM_TYPE 的值。"  1
    fi
        [ $? -ne 0 ] && { color "安装依赖包失败" 1; exit; }


cd ${SRC_DIR}
tar xf ${NGINX_FILE}
cd ${NGINX_DIR}
./configure --prefix=${NGINX_INSTALL_DIR} \
--with-pcre \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_addition_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_random_index_module \
--with-http_secure_link_module \
--with-http_stub_status_module \
--with-http_auth_request_module \
--with-http_image_filter_module \
--with-http_slice_module \
--with-mail \
--with-threads \
--with-file-aio \
--with-stream \
--with-mail_ssl_module \
--with-stream_ssl_module


make && make install 
# make -j $CPU && make install

[ $? -eq 0 ] && color "nginx 编译安装成功" 0 ||  { color "nginx 编译安装失败,退出!" 1 ;exit; }


#chown -R nginx.nginx ${NGINX_INSTALL_DIR}
#ln -s ${NGINX_INSTALL_DIR}/sbin/nginx /usr/local/sbin/nginx
#echo "PATH=${NGINX_INSTALL_DIR}/sbin:${PATH}" > /etc/profile.d/nginx.sh

cat > /lib/systemd/system/nginx.service <<EOF
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=${NGINX_INSTALL_DIR}/logs/nginx.pid
ExecStartPre=/bin/rm -f ${NGINX_INSTALL_DIR}/logs/nginx.pid
ExecStartPre=${NGINX_INSTALL_DIR}/sbin/nginx -t
ExecStart=${NGINX_INSTALL_DIR}/sbin/nginx
ExecReload=/bin/kill -s HUP \$MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
LimitNOFILE=100000

[Install]
WantedBy=multi-user.target
EOF

     systemctl daemon-reload
     systemctl enable --now nginx &> /dev/null 
     systemctl is-active nginx &> /dev/null ||  { color "nginx 启动失败,退出!" 1 ; exit; }
     color "nginx 安装完成" 0


}


check 
install_nginx
[root@jie01 weihu]# chmod +x install_nginx.sh 
[root@jie01 weihu]# ./install_nginx.sh 

创建测试页面

[root@jie01 ~]# echo  "11.0.1.131_jie01" > /usr/local/nginx/html/index.html 
[root@jie02 weihu]# echo  "11.0.1.137_jie02" > /usr/local/nginx/html/index.html

#重启nginx
[root@jie01 ~]# systemctl restart nginx
[root@jie02 weihu]# systemctl restart nginx
访问测试

3.2 keepalived 部署

说明:我这里采用编译安装,如果有yum源可以直接yum安装 。

1)yum安装

yum -y install keepalived
​
#如果是yum装的配置文件在/etc/keepalived/keepalived.conf

2)编译安装(两台都要编译)

# 安装依赖包
[root@jie01 ~]# yum install -y gcc openssl-devel libnl* popt-devel
# 下载源码包
https://www.keepalived.org/software/keepalived-2.2.8.tar.gz
# 上传至服务器并解压
[root@jie01 src]# tar -xf keepalived-2.2.8.tar.gz 
#编译
[root@jie01 src]# cd keepalived-2.2.8
[root@jie01 keepalived-2.2.8]# ./configure --prefix=/usr/local/keepalived
#安装
[root@jie01 keepalived-2.2.8]# make && make install
#查看
[root@jie01 ~]# ll -d /usr/local/keepalived/
drwxr-xr-x 6 root root 4.0K  6月  6 22:03 /usr/local/keepalived/

3)设置配置文件

# jie_01主机配置文件
[root@jie01 keepalived]# cat keepalived.conf
! Configuration File for keepalived
  
global_defs {
     router_id nginx-ha01
}

vrrp_script check_nginx {  
    script "/usr/local/keepalived/sbin/chk_nginx.sh"   
    interval 2
    weight -20
    fall 2
    rise 1                
}

vrrp_instance nginx-ha { 
    state BACKUP
    interface ens160
    virtual_router_id 52
    priority 100
    advert_int 1
    nopreempt
    authentication {
        auth_type PASS
        auth_pass R65yudzK   
    }

    track_script {
       check_nginx
    }

    virtual_ipaddress {          
        11.0.1.140/24 brd 11.0.1.255
    }
}

#jie_02主机配置文件
[root@jie02 ~]# cat /usr/local/keepalived/etc/keepalived/keepalived.conf
! Configuration File for keepalived
  
global_defs {
    router_id nginx-ha02
}

vrrp_script check_nginx {  
    script "/usr/local/keepalived/sbin/chk_nginx.sh"   
    interval 2
    weight -20
    fall 2
    rise 1                
}

vrrp_instance nginx-ha { 
    state BACKUP
    interface ens160
    virtual_router_id 52
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass R65yudzK   
    }

    track_script {
           check_nginx
    }

    virtual_ipaddress {          
        11.0.1.140/24 brd 11.0.1.255
    }
}
[root@jie02 ~]# 
4)编写检测nginx脚本(两台都要创建)
#创建nginx检测脚本
vim /usr/local/keepalived/sbin/chk_nginx.sh
###############################################
#!/bin/bash
count=`ps -C nginx --no-header |wc -l` 

if [ "${count}" -eq 0 ];then 
    /usr/local/nginx/sbin/nginx
    sleep 5
   
   count=`ps -C nginx --no-header |wc -l` 
    if [ "${count}" -eq 0 ] 
    then
        systemctl stop keepalived 
    fi 
fi
###############################################


#添加执行权限
 [root@jie01 keepalived]# chmod +x /usr/local/keepalived/sbin/chk_nginx.sh

5)启动keepalived

#设置为开机自启并且立即启动
[root@jie01 keepalived]# systemctl enable --now keepalived 
[root@jie02 keepalived]# systemctl enable --now keepalived

#扩展
systemctl start keepalived   启动keepalived服务
systemctl stop keepalived   停止keepalived服务
systemctl reload keepalived   重新加载
systemctl eable keepalived   开机自启服务

6)查看VIP地址

[root@jie01 keepalived]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:50:56:3e:2c:55 brd ff:ff:ff:ff:ff:ff
    inet 11.0.1.131/24 brd 11.0.1.255 scope global noprefixroute ens160
       valid_lft forever preferred_lft forever
    inet 11.0.1.140/24 brd 11.0.1.255 scope global secondary ens160
       valid_lft forever preferred_lft forever
    inet6 fe80::9f1d:93bc:d40b:a5d4/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
[root@jie01 keepalived]#

# 发现目前vip地址漂移在 jie01 这台主机上面
7)页面通过vip地址访问

3.3 测试验证

1)先将11.0.1.131(jie01)服务器上的nginx停掉,看脚本是否会自拉起

[root@jie01 keepalived]# /usr/local/nginx/sbin/nginx -s stop
[root@jie01 keepalived]# 
[root@jie01 keepalived]# 
[root@jie01 keepalived]# ps -ef |grep nginx
root       13719   11745  0 22:36 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody     13720   13719  0 22:36 ?        00:00:00 nginx: worker process
root       13727    2101  0 22:36 pts/0    00:00:00 grep --color=auto nginx

2)将11.0.1.131(jie01)服务器上的keepalived停掉或者直接将这台关机,看VIP是否漂移到11.0.1.137(jie02)服务器上

# 11.0.1.131(jie01) 已关机
[root@jie02 keepalived]# ping 11.0.1.131
PING 11.0.1.131 (11.0.1.131) 56(84) bytes of data.
From 11.0.1.137 icmp_seq=1 Destination Host Unreachable
From 11.0.1.137 icmp_seq=2 Destination Host Unreachable
From 11.0.1.137 icmp_seq=3 Destination Host Unreachable

# 查看VIP发现在已经漂移在11.0.1.137(jie_02)服务器上
[root@jie02 keepalived]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:50:56:3c:d3:cc brd ff:ff:ff:ff:ff:ff
    inet 11.0.1.137/24 brd 11.0.1.255 scope global noprefixroute ens160
       valid_lft forever preferred_lft forever
    inet 11.0.1.140/24 brd 11.0.1.255 scope global secondary ens160
       valid_lft forever preferred_lft forever
    inet6 fe80::3a5d:3c35:2a0a:119e/64 scope link dadfailed tentative noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 fe80::3149:f1bd:ec73:336c/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
[root@jie02 keepalived]# 

页面访问VIP地址

3)将11.0.1.131(jie01)服务器重启开机,回复nginx、keepalived服务,会发现VIP不会切换回来,因为上面配置的是非抢占模式。

[root@jie02 keepalived]# ping 11.0.1.131 -c 3
PING 11.0.1.131 (11.0.1.131) 56(84) bytes of data.
64 bytes from 11.0.1.131: icmp_seq=1 ttl=64 time=0.730 ms
64 bytes from 11.0.1.131: icmp_seq=2 ttl=64 time=0.654 ms
64 bytes from 11.0.1.131: icmp_seq=3 ttl=64 time=0.702 ms

--- 11.0.1.131 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2085ms
rtt min/avg/max/mdev = 0.654/0.695/0.730/0.031 ms
[root@jie02 keepalived]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:50:56:3c:d3:cc brd ff:ff:ff:ff:ff:ff
    inet 11.0.1.137/24 brd 11.0.1.255 scope global noprefixroute ens160
       valid_lft forever preferred_lft forever
    inet 11.0.1.140/24 brd 11.0.1.255 scope global secondary ens160
       valid_lft forever preferred_lft forever
    inet6 fe80::3a5d:3c35:2a0a:119e/64 scope link dadfailed tentative noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 fe80::3149:f1bd:ec73:336c/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
[root@jie02 keepalived]# 

四 扩展

4.1 keepalived服务脚本,编译安装后自动生成

[root@jie01 ~]# ll /usr/lib/systemd/system/keepalived.service 
-rw-r--r-- 1 root root 540  6月  6 22:03 /usr/lib/systemd/system/keepalived.service
[root@jie01 ~]# cat /usr/lib/systemd/system/keepalived.service
[Unit]
Description=LVS and VRRP High Availability Monitor
After=network-online.target syslog.target 
Wants=network-online.target 
Documentation=man:keepalived(8)
Documentation=man:keepalived.conf(5)
Documentation=man:genhash(1)
Documentation=https://keepalived.org

[Service]
Type=forking
PIDFile=/run/keepalived.pid
KillMode=process
EnvironmentFile=-/usr/local/keepalived/etc/sysconfig/keepalived
ExecStart=/usr/local/keepalived/sbin/keepalived  $KEEPALIVED_OPTIONS
ExecReload=/bin/kill -HUP $MAINPID

[Install]
WantedBy=multi-user.target
[root@jie01 ~]# 

4.2 keepalived配置文件详解

第一部分:全局定义块

  1、email通知。作用:有故障,发邮件报警。

  2、Lvs负载均衡器标识(lvs_id)。在一个网络内,它应该是唯一的。

  3、花括号“{}”。用来分隔定义块,因此必须成对出现。

global_defs {            
   notification_email {  #指定keepalived在发生切换时需要发送email到的对象,一行一个
    sysadmin@fire.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc #指定发件人
   smtp_server localhost #指定smtp服务器地址
   smtp_connect_timeout 30 #指定smtp连接超时时间
   router_id LVS_DEVEL #运行keepalived机器的一个标识
}

第二部分: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 {
    state BACKUP #指定那个为master,那个为backup,如果设置了nopreempt这个值不起作用,主备考priority决

定
    interface eth0 #设置实例绑定的网卡
    dont_track_primary #忽略vrrp的interface错误(默认不设置)
    track_interface{ #设置额外的监控,里面那个网卡出现问题都会切换
    eth0
    eth1
    }
    mcast_src_ip #发送多播包的地址,如果不设置默认使用绑定网卡的primary ip
    garp_master_delay #在切换到master状态后,延迟进行gratuitous ARP请求
    virtual_router_id 50 #VPID标记
    priority 99 #优先级,高优先级竞选为master
    advert_int 1 #检查间隔,默认1秒
    nopreempt #设置为不抢占 注:这个配置只能设置在backup主机上,而且这个主机优先级要比另外一台高
    preempt_delay #抢占延时,默认5分钟
    debug #debug级别
    authentication { #设置认证
        auth_type PASS #认证方式
        auth_pass 111111 #认证密码
    }
    #VRRP HA 虚拟地址 如果有多个VIP,继续换行填写
	#设置VIP,它随着state变化而增加删除,当state为master的时候就添加,当state为backup的时候则删除,由优先级决定
    virtual_ipaddress {
        192.168.202.200
    }
}

第四部分:执行nginx检测脚本。注意这个设置不能紧挨着写在vrrp_script配置块的后面。一定要注意

	track_script {   
 
       #引用VRRP脚本,即在 vrrp_script 部分指定的名字。定期运行它们来改变优先级,并最终引发主备切换。	
	   chk_nginx                    
	}
}

  • 26
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值