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-07-07
  • 详解Nginx 对访问量的控制

    详解Nginx 对访问量的控制

    本文详解的介绍了 Nginx 的 ngx_http_limit_conn_module 和 ngx_http_limit_req_module 模块,对请求访问量进行控制。非常具有实用价值,需要的朋友可以参考下
    2018-12-12
  • Nginx使用自签ssl证书实现https连接的方法

    Nginx使用自签ssl证书实现https连接的方法

    本文主要介绍了Nginx使用自签ssl证书实现https连接的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • nginx 某些url只能由特定ip访问的实现

    nginx 某些url只能由特定ip访问的实现

    在Nginx中针对某些URL只允许特定IP地址访问,本文就来介绍一下如何实现,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • Nginx中透传客户端真实IP的技巧

    Nginx中透传客户端真实IP的技巧

    为了记录日志、限制访问或进行其他基于 IP 地址的操作,获取客户端的真实 IP 地址非常重要,本文就来详细的介绍一下Nginx中透传客户端真实IP的技巧,感兴趣的可以了解一下
    2024-08-08
  • nginx+keepalived双主模式双主热备方式

    nginx+keepalived双主模式双主热备方式

    本文详细介绍了双主模式下Nginx和Keepalived的配置和测试,双主模式解决了单主备模式中资源利用率低的问题,通过两个虚拟IP和两个VRRP实例实现互相备份,配置文件包括nginx和keepalived的配置,以及检测脚本,测试部分验证了VIP的漂移和Nginx服务的自动恢复
    2026-01-01
  • Nginx 中 proxy_intercept_errors 实现后端 502/504 错误的优雅降级

    Nginx 中 proxy_intercept_errors 实现后端 502/

    本文主要介绍了Nginx 中 proxy_intercept_errors 实现后端 502/504 错误的优雅降级,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-04-04
  • 详解linux中 Nginx 常见502错误问题解决办法

    详解linux中 Nginx 常见502错误问题解决办法

    这篇文章主要介绍了详解linux中 Nginx 常见502错误问题解决办法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • Nginx配置http和https的实现步骤

    Nginx配置http和https的实现步骤

    Nginx是使用最多的代理服务器之一,本文主要介绍了Nginx配置http和https的实现步骤,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • Nginx 配置视频文件播放完全指南

    Nginx 配置视频文件播放完全指南

    本文指导在Ubuntu上配置Nginx支持MP4视频播放,涵盖安装、MIME类型设置、视频格式转换、权限配置及常见问题排查,确保视频可通过浏览器顺利播放,感兴趣的朋友跟随小编一起看看吧
    2025-09-09

最新评论