Docker+Nginx+KeepaLived 简单实现Nginx高可用+负载均衡

我们知道 Nginx反向代理可以简单的实现负载均衡(不知道的话可以先去百度了解下,这里就当你知道了,haha...)

如果服务器节点(Service节点)挂了,可以使用其他组件去做心跳检测(Consul、k8s等等),今天先不说这些。

今天主要说说:如果Nginx代理所在服务器挂了该怎么办?如何实现Nginx的高可用?

先看下图:

解释:

1,两台Nginx服务器,一主一备,也可以一主N备,每台Nginx服务器上负载有两台Service节点

2,客户端发起一个请求 ,请求没有到Nginx的实际IP上,而是请求的虚拟IP(会和实际IP通过配置文件进行绑定)

3,这时候如果有一台Nginx服务器挂了,Keepalived会自动在备Nginx服务器上选一台当主服务器

接下来落地实操

1,准备2台服务器(Linux),这里示例IP分别为:192.168.1.104、192.168.1.105

2,设置发送邮件的功能,后边使用:参考另一篇博文:  Linux系统下用mail(mailx)发送邮件 

3,两台服务器上分别安装 Docker (参考另一篇博文:https://www.cnblogs.com/peterzhang123/p/13858345.html)

4,在两台机器的Docker上分别安装Nginx,对外访问端口为:4001   (参考另一篇博文:https://www.cnblogs.com/peterzhang123/p/13864381.html)

5,在两台机器上分别安装 keepalived (注意:keepalived安装在实体机上,不是安装到Docker上

6,准备一个虚拟IP,说人话就是弄个假IP,当前网段内没人用该IP  例如:192.168.1.110

7,准备两个Service服务(ApI应用),为了演示,这里提供两个不同端口IP地址作为负载(192.168.1.102:5001,192.168.1.102:5002)

1,配置Nginx内容

upstream group1 {
    server 192.168.1.102:5001;
    server 192.168.1.102:5002;
}

server {
    listen       80;
    server_name  localhost;
    
    location / {
        proxy_pass http://group1/;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

2,在Linux主机上安装 Keepalived

#切换到 /usr目录下
cd /usr

#安装keepalived环境依赖
yum install -y gcc openssl-devel popt-deve

#安装keepalived
yum install keepalived -y

#验证是否安装成功
rpm -q -a keepalived

#移除
yum remove keepalived

安装之后,在 /etc/keepalived目录下有个 keepalived.conf 配置文件

修改 keepalived.conf 配置文件,配置内容参考如下 (注意区分 主/备的配置不一样

! Configuration File for keepalived

global_defs {
  # 通知邮件服务器的配置
  # 当master失去VIP或则VIP的时候,会发一封通知邮件到your-email@qq.com
   notification_email {
    131xxxxx@qq.com   # 收件人
   }
   notification_email_from xxxxx@163.com  # 邮件发送方地址
   smtp_server smtp.163.com          # 163邮件服务器
   smtp_connect_timeout 30           # 邮件服务器超时时间
   router_id LVS_DEVEL               # 唯一ID,设置成IP也行
   vrrp_mcast_group4 192.168.1.104   # 当前服务器的IP
}

# 检查nginx状态的脚本,健康监测脚本
vrrp_script chk_http_port {
    script "/etc/keepalived/nginx_check.sh"     # 脚本路径
    interval 2     # 脚本执行间隔时间
    weight 3
}

vrrp_instance VI_1 {
    state MASTER           # 主机使用: MASTER  备机使用: BACKUP
    interface ens33        # 实例绑定的网卡, 用ip a命令查看网卡编号
    virtual_router_id 51   # 虚拟路由标识,主、备服务器ID必须一样
    priority 100           # 优先级,备份服务上将100改为小于100,可配置成90
    advert_int 1           # 主备之间同步检查的时间间隔单位秒
    authentication {       # 验证类型和密码
        auth_type PASS     # 验证类型有两种 PASS和HA
        auth_pass 1111     # 验证密码,在一个实例中主备密码保持一样
    }
    virtual_ipaddress {    # 虚拟IP地址,可以有多个,每行一个,不需要指定端口,端口使用的是Nginx容器的端口(Port:4001)
        192.168.1.110
    }
    track_script {         # 调用上边的脚本
        chk_http_port
    }

     notify_master "/etc/keepalived/notify.sh master"
     notify_backup "/etc/keepalived/notify.sh backup"
     notify_fault "/etc/keepalived/notify.sh fault"

}

健康监测脚本内容,如下:

#!/bin/bash
#version 0.0.1
A=`ps -C nginx --no-header |wc -l`
if [ $A -eq 0 ];then
     systemctl restart docker     #判断docker是否能启动
     sleep 2
     if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
        systemctl stop keepalived
     fi 
fi

脚本说明:

当nginx进程不存在时,会自动重启docker服务;

docker服务启动时会自动启动nginx容器;再次检查nginx进程,如果不存在,就停止keepalived服务,然后NGINX_BACKUP主机会自动接替NGINX_MASTER的工作;

将健康监测脚本文件:nginx_check.sh 放到配置文件中的路径下

有2个地方需要注意:

a,将Docker中的Nginx容器设置成开机自动启动,在每台nginx服务器上执行如下命令

docker update --restart=always nginx

b,给 keepalived 监控脚本添加执行权限,在每台机器上执行如下命令

chmod +x /etc/keepalived/nginx_check.sh

3,notify.sh 通知脚本

#!/bin/bash
#
contact='131xxxxx@qq.com'
notify() {
mailsubject="$(hostname) to be $1, vip floating"
mailbody="$(date +'%F %T'): vrrp transition, $(hostname) changed to be $1"
echo "$mailbody" | mailx -v -s "$mailsubject" $contact 
}
case $1 in
master)
notify master
;;
backup)
notify backup
;;
fault)
notify fault
;;
*)
echo "Usage: $(basename $0) {master|backup|fault}"
exit 1
;;
esac

 通知文件:notify.sh 同样放到路径 /etc/keepalived 下。

4,启动 keepalived 服务,两台都要启动

systemctl enable keepalived     #将 keepalived 设置开机启动
systemctl start keepalived #启动服务

systemctl status keepalived #查看服务状态

systemctl restart keepalived #重启服务

systemctl stop keepalived #停止服务

4,最后测试,使用虚拟Ip测试,(截图仅作参考 )

第一次访问:http://192.168.2.110:4001/weatherforecast

 刷新地址之后,返回另一个Service服务节点

这时候把主Nginx代理所在的服务停掉,继续访问以上地址,发现还是可以正常访问!

在主Nginx所在服务器使用命令   ip a  也能查看到 你设置的虚拟IP已经绑定到网卡上(查看备Nginx服务上是未绑定的

最后测试收到的邮件

遗留问题:

1,当Master的Nginx访问某个服务时,在请求还未返回时就宕机了,这时候备Nginx会接着上一个请求继续访问吗?有待验证!下次分解!

作者:PeterZhang
本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/peterzhang123/p/14691762.html