Nginx系列-Nginx高可用(主从、主主模式)

news/2025/2/26 15:30:04

文章目录

  • Nginx系列-Nginx高可用(主从、主主模式)
    • 1. 引言
    • 2. 高可用架构设计
    • 3. 基础环境准备
    • 4. Nginx安装
    • 5. keepalived安装
    • 4. 配置主备模式
    • 5. 配置主主(双主)模式
    • 6. 注意事项

Nginx系列-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容器部署两种方案

  1. 准备两台服务器
  2. 分别安装docker
  3. 分别安装nginx
    Nginx两个端口要保持一致
  4. 分别安装keepalive

4. 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

docker stop nginx1
docker rm nginx1

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

http://www.niftyadmin.cn/n/5868887.html

相关文章

Java中的Stream API:从入门到实战

引言 在现代Java开发中,Stream API 是处理集合数据的强大工具。它不仅让代码更加简洁易读,还能通过并行处理提升性能。本文将带你从基础概念入手,逐步深入Stream API的使用,并通过实战案例展示其强大功能。 1. 什么是Stream API…

ROS的action通信——实现阶乘运算(一)

在ROS中除了常见的话题(topic)通信、服务(server)通信等方式,还有action通信这一方式,由于可以实时反馈任务完成情况,该通信方式被广泛运用于机器人导航等任务中。本文将通过三个小节的分享,实现基于action通信的阶乘运…

PXE 安装ubuntu22.04自动判断UEFI或者Legacy引导

UEFI引导安装:https://blog.csdn.net/qq_50247813/article/details/145777563 Legacy引导安装:https://blog.csdn.net/qq_50247813/article/details/145730754 本篇根据上两篇快速部署pxe服务器,并自动判断uefi或者legacy引导 一、服务器必要…

C/C++后端开发面试表述、技术点摸底——基础组件篇

前端时间笔者系统学习了基础组件中的池式结构(包括线程池、内存池、连接池),原子操作,锁,无锁队列,网络缓冲区,定时器设计,分布式锁,有些内容笔者已经总结整理成了相关技…

linux centos8 安装redis 卸载redis

准备环境 系统:linux CentOS8 安装步骤 一、下载redis 1.进入官网找到下载地址 https://redis.io/download 2.右键点击复制链接地址 3.进入到Xshell控制台(默认当前是root根目录),,输入wget 加你复制的地址 (示例 &#xff…

爱普生汽车用显示控制器IC:ScalerIC,汽车接口IC,相机接口IC

爱普生汽车显示控制器IC,汽车显示控制器芯片可以分为三类:爱普生显示控制芯片Scaler IC ,爱普生汽车接口IC,爱普生相机接口IC。下面就给大家分别介绍下这三类芯片的具体型号的特征及用途。 爱普生显示控制芯片 Scaler IC Scaler…

在 JMeter 中使用 Python 脚本

JMeter本身基于Java开发,但可以借助JSR223元件编写Python脚本实现更灵活的功能,以下为你详细介绍具体实现方式: 1. 配置Python环境 在使用Python脚本前,需要确保你的系统已经安装了Python环境,同时还需要安装jpype1库,它允许Python程序调用Java代码,这对于在JMeter中使…

DeepSeek-R1 满血版和蒸馏版鉴别方法

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于大模型算法的研究与应用。曾担任百度千帆大模型比赛、BPAA算法Q大赛评委,编写微软OpenAI考试认证指导手册。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第名。授权多项发明专利。对机器学…