Nginx高可用(主从、主主模式)的项目实践

 更新时间:2025年02月28日 09:58:32   作者:为什么要做囚徒  
本文介绍了Nginx高可用性的两种主要解决方案,主从架构和主主架构,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1. 引言

在单机部署的Nginx环境中,一旦Nginx服务器出现故障,整个系统服务将受到影响,导致服务中断。为了解决这个问题,我们需要引入Nginx的高可用性(HA)架构。本文将详细探讨Nginx高可用性的两种主要解决方案:主从架构和主主架构。

2. 高可用架构设计

  • KeepAlived是什么?

KeepAlived是一款基于VRRP(Virtual Router Redundancy Protocol,虚拟路由冗余协议)的开源软件,主要用于解决网络服务的单点故障问题,特别是在集群环境中提供VIP(Virtual IP,虚拟IP地址)共享和故障切换功能

  • Nginx+keepalived 双机主从模式(也叫双机热备):

即前端使用两台服务器,一台主服务器和一台热备服务器,正常情况下,主服务器绑定一个虚拟IP,提供负载均衡服务,热备服务器处于空闲状态;当主服务器发生故障时,热备服务器接管主服务器的虚拟IP,提供负载均衡服务;但是热备服务器在主机器不出现故障的时候,永远处于浪费状态,对于服务器不多的网站,该方案不经济实惠。

  • Nginx+keepalived 双机主主模式(也叫双机互备):

即前端使用两台负载均衡服务器,互为主备,且都处于活动状态,同时各自绑定一个虚拟IP,提供负载均衡服务;当其中一台发生故障时,另一台接管发生故障服务器的虚拟IP(这时由非故障机器一台负担所有的请求)

3. 基础环境准备

本片采用 nginx容器部署+keepalived宿主机部署、nginx容器部署+keepalived容器部署两种方案

  • 准备两台服务器
  • 分别安装docker
  • 分别安装nginx
    ① Nginx两个端口要保持一致
  • 分别安装keepalive

4. Nginx安装

  • 创建nginx目录
mkdir -p /home/xmc/nginx1/conf.d /home/xmc/nginx1/html /home/xmc/nginx1/logs
  • 临时构建nginx容器(目的是获取配置文件)
docker run -d --name=nginx1 nginx:latest
  • 从临时nginx容器获取配置文件
docker cp nginx1:/etc/nginx/nginx.conf /home/xmc/nginx1
docker cp nginx1:/etc/nginx/conf.d /home/xmc/nginx1
docker cp nginx1:/usr/share/nginx/html /home/xmc/nginx1
  • 删除临时nginx容器
docker stop nginx1
docker rm nginx1
  • 重新构建nginx容器
docker run \
-d -p 8081:80 \
--name nginx1 \
--privileged=true \
--restart=always \
-v /home/xmc/nginx1/nginx.conf:/etc/nginx/nginx.conf \
-v /home/xmc/nginx1/logs:/var/log/nginx \
-v /home/xmc/nginx1/conf.d:/etc/nginx/conf.d \
-v /home/xmc/nginx1/html:/usr/share/nginx/html \
nginx:latest

5. keepalived安装

keepalived安装包下载地址

  • 安装目录准备
# 进入一下目录,解压的时候会自动创建keepalived文件夹
cd /opt/module
  • 解压
tar -zxvf keepalived-2.2.7.tar.gz
  • 安装
./configure --prefix=/usr/local/keepalived make && make install
  • 启停
# 启动
systemctl start keepalived
# 状态
systemctl status keepalived
# 停止
systemctl stop keepalived
  • 设置开机自启动
sudo systemctl enable keepalived
  • 日志查看
Keepalived默认所有的日志都是写入到/var/log/message,
你可以使用命令 tail -f /var/log/messages|grep Keepalived 进行查看

4. 配置主备模式

  • 主机: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.10.200
    smtp_connect_timeout 30
    router_id LVS_DEVEL
}
vrrp_script chk_http_port {
    script "/etc/keepalived/nginx_check.sh" # 脚本路径
    interval 2 #(检测脚本执行的间隔)
    weight 2
}
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 {
        192.168.10.50 # 虚拟IP地址,可以有多个,每行一个,不需要指定端口,端口使用的是Nginx容器的端口
    }
     track_script {  # 调用上边的脚本
        chk_http_port
     }
}
  • 备机: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.10.200
    smtp_connect_timeout 30
    router_id LVS_DEVEL
}
vrrp_script chk_http_port {
    script "/etc/keepalived/nginx_check.sh" # 脚本路径
    interval 2 #(检测脚本执行的间隔)
    weight 2
}
vrrp_instance VI_1 {
    state BACKUP    # 主机使用: MASTER  备机使用: BACKUP
    interface ens33 #实例绑定的网卡, 用ip a命令查看网卡编号
    virtual_router_id 51 # 虚拟路由标识,主、备服务器ID必须一样
    priority 90 # 优先级,备份服务上将100改为小于100,可配置成90
    advert_int 1 # 主备之间同步检查的时间间隔单位秒
    authentication { # 验证类型和密码
        auth_type PASS # 验证类型有两种 PASS和HA
        auth_pass 1111 # 验证密码,在一个实例中主备密码保持一样
    }
    virtual_ipaddress {
        192.168.10.50 # 虚拟IP地址,主、备节点必须一致,可以有多个,每行一个,不需要指定端口,端口使用的是Nginx容器的端口
    }
     track_script {  # 调用上边的脚本
        chk_http_port
     }
}
  • 检测脚本(主机和备机一致):
vim /etc/keepalived/nginx_check.sh
#!/bin/bash

# 容器名称
container_name="nginx1"

# 检查容器状态
container_status=$(docker inspect -f '{{.State.Status}}' "$container_name" 2>/dev/null)

# 如果容器不存在
if [ -z "$container_status" ]; then
    echo "容器 $container_name 不存在! 关闭 keepalived..."
    systemctl stop keepalived
    echo "Keepalived 已关闭。"
    exit 1
fi

echo "容器 $container_name 当前状态为: $container_status"

# 如果容器未运行,尝试重新启动
if [ "$container_status" != "running" ]; then
    echo "容器 $container_name 未运行,尝试重新启动..."
    docker start "$container_name"
    sleep 5  # 等待 5 秒,确保容器有足够时间启动

    # 再次检查容器状态
    container_status=$(docker inspect -f '{{.State.Status}}' "$container_name" 2>/dev/null)

    if [ "$container_status" != "running" ]; then
        echo "容器 $container_name 重启后仍未运行,将关闭 Keepalived。"
        systemctl stop keepalived
        echo "Keepalived 已关闭。"
        exit 1
    else
        echo "容器 $container_name 已成功启动。"
    fi
else
    echo "容器 $container_name 已处于运行状态,无需重启。"
fi

赋予执行权限

chmod +x /etc/keepalived/nginx_check.sh 

5. 配置主主(双主)模式

  • 主机1: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.10.200
    smtp_connect_timeout 30
    router_id LVS_DEVEL
}
vrrp_script chk_http_port {
    script "/etc/keepalived/nginx_check.sh" # 脚本路径
    interval 2 #(检测脚本执行的间隔)
    weight 2
}
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 {
        192.168.10.50 # 虚拟IP地址,可以有多个,每行一个,不需要指定端口,端口使用的是Nginx容器的端口
    }
    track_script {  # 调用上边的脚本
        chk_http_port
    }
}
vrrp_instance VI_2 {
    state BACKUP   # 主机使用: MASTER  备机使用: BACKUP
    interface ens33 #实例绑定的网卡, 用ip a命令查看网卡编号
    virtual_router_id 52 # 虚拟路由标识,主、备服务器ID必须一样
    priority 90 # 优先级,备份服务上将100改为小于100,可配置成90
    advert_int 1 # 主备之间同步检查的时间间隔单位秒
    authentication { # 验证类型和密码
        auth_type PASS # 验证类型有两种 PASS和HA
        auth_pass 1111 # 验证密码,在一个实例中主备密码保持一样
    }
    virtual_ipaddress {
        192.168.10.51 # 虚拟IP地址,可以有多个,每行一个,不需要指定端口,端口使用的是Nginx容器的端口
    }
    track_script {  # 调用上边的脚本
        chk_http_port
    }
}
  • 主机2: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.10.200
    smtp_connect_timeout 30
    router_id LVS_DEVEL
}
vrrp_script chk_http_port {
    script "/etc/keepalived/nginx_check.sh" # 脚本路径
    interval 2 #(检测脚本执行的间隔)
    weight 2
}
vrrp_instance VI_1 {
    state BACKUP    # 主机使用: MASTER  备机使用: BACKUP
    interface ens33 #实例绑定的网卡, 用ip a命令查看网卡编号
    virtual_router_id 51 # 虚拟路由标识,主、备服务器ID必须一样
    priority 90 # 优先级,备份服务上将100改为小于100,可配置成90
    advert_int 1 # 主备之间同步检查的时间间隔单位秒
    authentication { # 验证类型和密码
        auth_type PASS # 验证类型有两种 PASS和HA
        auth_pass 1111 # 验证密码,在一个实例中主备密码保持一样
    }
    virtual_ipaddress {
        192.168.10.50 # 虚拟IP地址,主、备节点必须一致,可以有多个,每行一个,不需要指定端口,端口使用的是Nginx容器的端口
    }
     track_script {  # 调用上边的脚本
        chk_http_port
     }
}

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

检测脚本(主机和备机一致):

#!/bin/bash

# 容器名称
container_name="nginx1"

# 检查容器状态
container_status=$(docker inspect -f '{{.State.Status}}' "$container_name" 2>/dev/null)

# 如果容器不存在
if [ -z "$container_status" ]; then
    echo "容器 $container_name 不存在! 关闭 keepalived..."
    systemctl stop keepalived
    echo "Keepalived 已关闭。"
    exit 1
fi

echo "容器 $container_name 当前状态为: $container_status"

# 如果容器未运行,尝试重新启动
if [ "$container_status" != "running" ]; then
    echo "容器 $container_name 未运行,尝试重新启动..."
    docker start "$container_name"
    sleep 5  # 等待 5 秒,确保容器有足够时间启动

    # 再次检查容器状态
    container_status=$(docker inspect -f '{{.State.Status}}' "$container_name" 2>/dev/null)

    if [ "$container_status" != "running" ]; then
        echo "容器 $container_name 重启后仍未运行,将关闭 Keepalived。"
        systemctl stop keepalived
        echo "Keepalived 已关闭。"
        exit 1
    else
        echo "容器 $container_name 已成功启动。"
    fi
else
    echo "容器 $container_name 已处于运行状态,无需重启。"
fi
  • 双主模式keepalived的主要区别
    • 互为主备,两个实例,两个虚拟ip
    • 每个实例都拥有自己独立的虚拟路由id(virtual_router_id这个属性)

6. 注意事项

没有出现虚拟ip,如果出现主备都抢用了虚拟ip的情况,那很可能是firewall的原因,keepalived 是基于vrrp做到虚拟ip漂移的,这里不开启的话,主备均会认为对方挂掉了,会造成主备都能获取到虚拟ip(vip)

防火墙开启vrrp

firewall-cmd --add-rich-rule='rule protocol value="vrrp" accept' --permanent

重新载入配置

firewall-cmd –reload

到此这篇关于Nginx高可用(主从、主主模式)的项目实践的文章就介绍到这了,更多相关Nginx高可用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • nginx日常维护常用命令

    nginx日常维护常用命令

    这篇文章主要介绍了nginx日常维护如nginx启动、重启、关闭等常用命令,需要的朋友可以参考下
    2014-03-03
  • Nginx实现不同域名输出不同的服务器头信息方法

    Nginx实现不同域名输出不同的服务器头信息方法

    这篇文章主要介绍了Nginx实现不同域名输出不同的服务器头信息方法,本文使用了一个ngx_headers_more模块实现这个特殊需求,需要的朋友可以参考下
    2015-02-02
  • Nginx带宽控制(限速模块使用)

    Nginx带宽控制(限速模块使用)

    这篇文章主要介绍了Nginx带宽控制(限速模块使用),本文讲解了使用limit_rate和limit_rate_aft以及limit_conn实现带宽控制的例子,需要的朋友可以参考下
    2015-03-03
  • Nginx+Windows负载均衡配置方法

    Nginx+Windows负载均衡配置方法

    Nginx负载均衡如何才能实现呢?这个问题有很多的程序员都希望知道,下面我们就向大家详细的介绍有关Nginx负载均衡的信息
    2012-11-11
  • Nginx文件下载站点搭建的实现步骤

    Nginx文件下载站点搭建的实现步骤

    本文主要介绍了Nginx文件下载站点搭建的实现步骤,包含配置Nginx和Fancyindex来搭建文件下载站点,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • nginx使用nginx-rtmp-module模块实现直播间功能

    nginx使用nginx-rtmp-module模块实现直播间功能

    做的过程出现很多问题,环境其实就需要nginx就可以,然后就是在播放的问题,m3u8的格式,mac直接访问就支持,苹果系统原生H5支持m3u8,还有就是手机直接访问也支持!但是其他其他系统PC端不支持,尝试了好多都不行,最后终于找到了一个支持m3u8格式H5播放
    2017-10-10
  • nginx服务器通过配置来解决API的跨域问题

    nginx服务器通过配置来解决API的跨域问题

    这篇文章主要给大家介绍了关于nginx服务器是如何配置来解决API跨域问题的相关资料,文中介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-05-05
  • nginx的zabbix 5.0安装部署的方法步骤

    nginx的zabbix 5.0安装部署的方法步骤

    之前大家可能经常会基于apache去部署zabbix,但是这样会偶尔遇到一些问题,今天小编就带大家操作一下基于nginx的zabbix5.0的部署。感兴趣的可以了解一下
    2021-07-07
  • 使用Nginx配置浏览器缓存,页面展示更快一步

    使用Nginx配置浏览器缓存,页面展示更快一步

    这篇文章主要介绍了使用Nginx配置浏览器缓存,页面展示更快一步问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • nginx ingress限速那些事浅析

    nginx ingress限速那些事浅析

    这篇文章主要为大家介绍了nginx ingress限速的一些知识的浅析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04

最新评论