Nginx 高可用架构实践:Keepalived 实现故障自动切换,Keepalived主备模式(双机热备),Keepalived互备模式(互为主备,互持 VIP)

Nginx 高可用架构实践:Keepalived 实现故障自动切换,Keepalived主备模式(双机热备),Keepalived互备模式(互为主备,互持 VIP)

📖 为什么需要高可用架构?

在实际生产中,如果只有一台 Nginx 服务器,那么当它宕机(比如断电、系统崩溃、Nginx 服务停止)时,所有用户的请求都会失败,整个网站或系统将无法访问。

为了解决这个问题,我们需要部署多个 Nginx 实例,并通过高可用机制实现自动切换,这样即使一台服务器出问题,另一台也能接管工作,用户访问不会受到影响。


🏗️ 高可用部署方案详解

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

1️⃣ 主备模式(双机热备)

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

在这里插入图片描述

  • 虚拟IP数量:仅需要 1 个 VIP(例如:192.168.0.100)
  • 流量特点:所有请求始终流向主节点,一旦主节点宕机,备节点立即接管 VIP,继续提供服务
  • 使用场景:中小型系统,访问量不大,请求不均衡问题不明显
🧠 工作机制
  1. Master 节点绑定 VIP 192.168.0.100,对外提供服务
  2. Backup 节点处于监控状态,不处理请求
  3. 一旦 Master 节点检测失败(例如 Nginx 挂掉),Keepalived 自动将 VIP 漂移到 Backup
  4. 用户无感知切换,请求继续正常处理
  5. Master 恢复后,根据是否开启抢占模式,VIP 可以自动漂移回来

2️⃣ 互备模式(互为主备,互持 VIP)

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

在这里插入图片描述

  • 虚拟IP数量:需要 2 个 VIP(例如:192.168.0.100 和 192.168.0.101)
  • 流量特点:两个节点同时对外提供服务,用户请求可通过 DNS 轮询或负载均衡分发至任一 VIP
  • 使用场景:大中型系统,请求量大,需要并发负载分摊
🧠 工作机制
  1. A 节点绑定 VIP1(192.168.0.100),为 VIP2 的备份
  2. B 节点绑定 VIP2(192.168.0.101),为 VIP1 的备份
  3. 正常时两台机器同时提供服务
  4. 若任一节点宕机,另一节点自动绑定两个 VIP,完全接管服务
  5. 故障节点恢复后,可以重新分担流量

🧰 什么是 Keepalived?

Keepalived 是一种实现高可用的开源工具。它的核心原理是基于 VRRP 协议(虚拟路由冗余协议)。

它的作用主要是:

  • 让多台服务器共享一个或多个虚拟 IP(VIP)
  • 实时监控服务(如 Nginx)状态
  • 一旦发现主节点异常,自动切换 VIP 到备节点

注意: Keepalived 一般用于实现主备(Master-Backup)高可用架构,这是它设计和最常见的使用场景。仅用 Keepalived 做主主,适合简单场景或实验,生产环境建议结合 LVS、DNS 轮询、或反向代理等方案。


🚦 Keepalived 配置属性说明

下面分 父块 → 子属性 两级结构给出:

  1. global_defs(全局定义)
  2. vrrp_script(健康检查脚本)
  3. vrrp_instance·主备模式(Master‑Backup)
  4. vrrp_instance·主主模式(Active‑Active,模拟双主)

1. global_defs(全局定义)

子属性取值范围 / 格式示例作用说明
notification_email多行邮箱地址,任意合法 e‑mailadmin@163.com告警接收人列表
notification_email_from单行邮箱地址keepalived@163.com告警邮件发件人
smtp_serverIP / FQDN192.168.10.200SMTP 服务器地址
smtp_connect_timeout整数 1‑300 秒30连接 SMTP 超时
router_id任意字符串LVS_NODE_A当前 Keepalived 实例标识符
主备模式:
router_id 推荐相同(可不同),router_id 只是标识当前节点自身,用于日志显示或调试,不影响 VRRP 通讯。主备之间通过 virtual_router_id + interface + VIP 来标识一个虚拟路由组,router_id 只是逻辑名称,不会影响主备切换

主主模式:
router_id 必须唯一,在主主(即多个实例都为 MASTER)场景下,为了方便区分节点身份、排查问题,建议配置成唯一的名字,避免日志混淆。仍然不会影响 VRRP 协议工作逻辑。
vrrp_garp_interval整数(秒)3GARP 报文间隔(更新 ARP 映射表)
vrrp_gna_interval整数(秒)3GNA 通知间隔(VRRP 通告包)

2. vrrp_script(健康检查脚本)

子属性取值范围 / 格式示例作用说明
script可执行文件绝对路径/etc/keepalived/nginx_check.sh健康检测脚本路径
interval整数 1‑60 秒2脚本执行间隔
weight‑100 ~ +100(可正可负)20成功时动态调整优先级(正值↑,负值↓)
假设原始 priority 为 100:
脚本运行正常 → 当前优先级:100 + 20;
脚本异常 → 优先级变为 80,将触发切换

3. vrrp_instance(主备模式 Master‑Backup)

子属性取值范围 / 格式示例作用说明
stateMASTER | BACKUPMASTER指定节点初始角色
interface网卡名(通过 ip a 查看)eth0发送 VRRP 广播或单播的接口
virtual_router_id整数 1‑25551VRRP 路由实例标识,主备需一致
priority整数 1‑255主:100,备:90节点优先级,越高越可能成为主
advert_int整数 1‑255(秒)1广播同步间隔,MASTER与BACKUP之间同步检查的时间间隔
authenticationauth_typePASS | AHPASS认证方式
authenticationauth_pass最多 8 字符1111主备需一致的密码
virtual_ipaddress每行一个 IP(IPv4/IPv6)192.168.10.50虚拟 IP(VIP)
track_scriptvrrp_script 名称chk_http_port引用上方定义的健康检查脚本
nopreempt无值(直接配置)nopreempt非抢占模式:主节点恢复后不会抢回 VIP
unicast_src_ip本机真实 IP 地址10.218.0.13单播场景下指定本节点 IP
unicast_peer对端节点 IP(可多行)10.218.0.14单播发送目标 IP
garp_master_delay整数(秒)1节点抢占主后等待多少秒发送 GARP 报文
garp_master_refresh整数(秒)5主节点周期性发送 GARP 报文的时间间隔
track_interface网卡名eth0检查网卡是否可用,网卡不可用时降低优先级

4. vrrp_instance(主主模式 Active‑Active 模拟)

子属性取值范围 / 格式示例与主备区别 / 说明
state所有节点统一设置为 MASTERMASTER所有节点都初始化为主,用于模拟主主高可用
priority建议所有节点设置相同优先级(如 100)100若无健康检测等动态调整,则由 IP 大小决定主
nopreempt建议开启nopreempt非抢占:避免主频繁变化
virtual_ipaddress单 VIP 共持 / 多 VIP 分配A 节点:.50,B 节点:.51多 VIP 更易实现流量分摊与容灾切换
其余属性同主备模式包括 advert_intauthenticationtrack_script 等通用参数均可复用

⚠️ 主主模式仅为模拟双主,不是 VRRP 标准特性。
多节点共享 VIP 可能导致 ARP 冲突,通常需搭配:

  • LVS/HAProxy 反向代理实现负载分担
  • 多 VIP 配合 DNS/SLB 实现服务分片
  • 网络设备(如交换机)允许多 MAC 绑定同 IP

⚙️ 主从模式配置示例

假设VIP为 192.168.0.100

Master 节点(192.168.0.11)

! Configuration File for keepalived
global_defs {
  router_id ka1
  vrrp_garp_interval 3
  vrrp_gna_interval 3
}

# 检查脚本
vrrp_script check1{
    script "/etc/keepalived/check_health.sh" # 脚本路径
    interval 2 #(检测脚本执行的间隔)
    weight 2
}

vrrp_instance VI_1 {
  # 主MASTER,备BACKUP
  state MASTER
  # 实例绑定的网卡
  interface eth0
  # 主备节点要保持一致
  virtual_router_id 11
  # 设置非抢占模式
  nopreempt
  # 主优先级高,备优先级低
  priority 100
  # MASTER与BACKUP之间同步检查的时间间隔,单位是秒
  advert_int 5
  
  authentication {
    auth_type PASS
    auth_pass 1111
  }
  
  # 出于安全、网络隔离等原因禁止多播时,可以使用单播模式
  # 配置成本机实际IP
  unicast_src_ip 192.168.0.11
  # 对端设备的IP地址
  unicast_peer {
      192.168.0.12
  }

  virtual_ipaddress {
    # 虚拟ip地址
    192.168.0.100
  }
  # 设置当切为主状态后多久更新 ARP 缓存
  garp_master_delay 1
  # 设置主节点发送 ARP 报文的时间间隔
  garp_master_refresh 5
  # 使用绑定VIP的网卡
   track_interface {
    eth0
  }
  # 调用上边的脚本
  track_script {
    check1
  }
}

Backup 节点(192.168.0.12)

! Configuration File for keepalived

global_defs {
  router_id ka1
  vrrp_garp_interval 3
  vrrp_gna_interval 3
}

# 检查脚本
vrrp_script check1{
    script "/etc/keepalived/check_health.sh" # 脚本路径
    interval 2 #(检测脚本执行的间隔)
    weight 2
}

vrrp_instance VI_1 {
  # 主MASTER,备BACKUP
  state BACKUP
  # 实例绑定的网卡
  interface eth0
  # 主备节点要保持一致
  virtual_router_id 11
  # 设置非抢占模式
  nopreempt
  # 主优先级高,备优先级低
  priority 90
  # MASTER与BACKUP之间同步检查的时间间隔,单位是秒
  advert_int 5
  
  authentication {
    auth_type PASS
    auth_pass 1111
  }
  
  # 出于安全、网络隔离等原因禁止多播时,可以使用单播模式
  # 配置成本机实际IP
  unicast_src_ip 192.168.0.12
  # 对端设备的IP地址
  unicast_peer {
      192.168.0.11
  }

  virtual_ipaddress {
    # 虚拟ip地址
    192.168.0.100
  }
  # 设置当切为主状态后多久更新 ARP 缓存
  garp_master_delay 1
  # 设置主节点发送 ARP 报文的时间间隔
  garp_master_refresh 5
  # 使用绑定VIP的网卡
   track_interface {
    eth0
  }
  # 调用上边的脚本
  track_script {
    check1
  }
}

⚙️ 主主模式配置示例

假设VIP为 192.168.0.100192.168.0.101

节点 A 配置

global_defs {
    notification_email {
        admin@163.loc
        dev@163.loc
    }
    notification_email_from Keepalived failure notification 
    smtp_server 192.168.10.200
    smtp_connect_timeout 30
    router_id NODE_A
}
vrrp_script chk_http_port {
    script "/etc/keepalived/check_health.sh" # 脚本路径
    interval 2 #(检测脚本执行的间隔)
    weight 2
}
# 节点A的VI_1为主节点
vrrp_instance VI_1 {
    state MASTER
    interface eth0 #实例绑定的网卡, 用ip a命令查看网卡编号
    virtual_router_id 11 # 虚拟路由标识,主、备服务器ID必须一样
    priority 100 # 优先级,备份服务上将100改为小于100,可配置成90
    advert_int 1 # 主备之间同步检查的时间间隔单位秒
    authentication { # 验证类型和密码
        auth_type PASS # 验证类型有两种 PASS和HA
        auth_pass 1111 # 验证密码,在一个实例中主备密码保持一样
    }
    virtual_ipaddress {
        192.168.0.100
    }
    track_script {  # 调用上边的脚本
        check1
    }
}
# 节点A的VI_2为备节点
vrrp_instance VI_2 {
    state BACKUP
    interface eth0 #实例绑定的网卡, 用ip a命令查看网卡编号
    virtual_router_id 12 # 虚拟路由标识,主、备服务器ID必须一样
    priority 90 # 优先级,备份服务上将100改为小于100,可配置成90
    advert_int 1 # 主备之间同步检查的时间间隔单位秒
    authentication { # 验证类型和密码
        auth_type PASS # 验证类型有两种 PASS和HA
        auth_pass 1111 # 验证密码,在一个实例中主备密码保持一样
    }
    virtual_ipaddress {
        192.168.0.101
    }
    track_script {  # 调用上边的脚本
        check1
    }
}

节点 B 配置

global_defs {
    notification_email {
        admin@163.loc
        dev@163.loc
    }
    notification_email_from Keepalived failure notification 
    smtp_server 192.168.10.200
    smtp_connect_timeout 30
    router_id NODE_B
}
vrrp_script chk_http_port {
    script "/etc/keepalived/check_health.sh" # 脚本路径
    interval 2 #(检测脚本执行的间隔)
    weight 2
}
# 节点B的VI_1为备节点
vrrp_instance VI_1 {
    state BACKUP
    interface eth0 #实例绑定的网卡, 用ip a命令查看网卡编号
    virtual_router_id 11 # 虚拟路由标识,主、备服务器ID必须一样
    priority 90 # 优先级,备份服务上将100改为小于100,可配置成90
    advert_int 1 # 主备之间同步检查的时间间隔单位秒
    authentication { # 验证类型和密码
        auth_type PASS # 验证类型有两种 PASS和HA
        auth_pass 1111 # 验证密码,在一个实例中主备密码保持一样
    }
    virtual_ipaddress {
        192.168.0.100
    }
    track_script {  # 调用上边的脚本
        check1
    }
}
# 节点B的VI_2为主节点
vrrp_instance VI_2 {
    state MASTER
    interface eth0 #实例绑定的网卡, 用ip a命令查看网卡编号
    virtual_router_id 12 # 虚拟路由标识,主、备服务器ID必须一样
    priority 100 # 优先级,备份服务上将100改为小于100,可配置成90
    advert_int 1 # 主备之间同步检查的时间间隔单位秒
    authentication { # 验证类型和密码
        auth_type PASS # 验证类型有两种 PASS和HA
        auth_pass 1111 # 验证密码,在一个实例中主备密码保持一样
    }
    virtual_ipaddress {
        192.168.0.101
    }
    track_script {  # 调用上边的脚本
        check1
    }
}

一句话总结

  • 节点 AVI_1(priority 高),VI_2(priority 低)
  • 节点 BVI_1VI_2

🔍 监控脚本示例: check_health.sh

脚本功能说明

  • 使用 curl 访问本地端口(如 80、8080)
  • 若访问成功(HTTP 状态码 200),则返回 0(健康)
  • 否则返回非 0(不健康,会降低权重或触发 VIP 迁移)
#!/bin/bash

# 要检查的服务地址(可以换成 127.0.0.1、localhost、实际 IP 等)
URL="http://127.0.0.1:80"

# 使用 curl 请求,最多超时 3 秒,只取状态码
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 3 "$URL")

# 如果状态码为 200,表示正常
if [ "$HTTP_CODE" -eq 200 ]; then
  exit 0
else
  echo "Health check failed, HTTP status: $HTTP_CODE"
  exit 1
fi

脚本权限

chmod +x /etc/keepalived/check_health.sh

🛠️ 启动与验证

sudo systemctl start keepalived
sudo systemctl enable keepalived
ip addr | grep 192.168.0.100
  • 停掉 master 的 nginx 服务 → VIP 漂移到 backup
  • 恢复服务 → VIP 可根据配置漂移回来

✅ 总结对比

模式VIP 数量可用性负载分担复杂度推荐场景
主从1 个✅ 高❌ 无✅ 简单小型系统
主主2 个✅ 更高✅ 支持⚠️ 较复杂大并发系统

📚 延伸阅读


感谢阅读,如有帮助欢迎点赞与转发!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值