Nginx负载均衡叠加Keepalived双机热备如何落地?

来源:IOS教程作者:不吃香菜头衔:草根站长
导读:本期聚焦于不吃香菜创作的《Nginx负载均衡叠加Keepalived双机热备如何落地?》,敬请观看详情。如果只用单台Nginx做反向代理,后端即使部署了十个节点,Nginx所在的机器一旦重启,整个入口就断了。Keepalived基于VRRP协议,能够把两台Nginx绑定在同一个虚拟IP上,主节点故障时备节点自动接管,客户端几乎无感知。本文会从零开始搭建一套Nginx加Keepalived的负载均衡与双机热备环境:先说明为什么负载均衡器自身也需要高可用,再给出Nginx的upstream配置、反向代理参数以及被动健康检查的调优方式;接着分别配置两台Keepalived,包含vrrp_script检测Nginx进程、MASTER与BACKUP角色、优先级和抢占行为;最后演示如何验证VIP漂移,并讨论脑裂、脚本误判、防火墙放行VRRP等生产环境常见问题。配置全部基于Linux服务器,示例IP和路径可直接替换。

单台Nginx做反向代理,能解决后端应用的水平扩展问题,但引出了一个新的单点:如果这台Nginx所在机器抖动、重启或内核崩溃,所有请求都会失败。Keepalived引入到Nginx层,本质上是给负载均衡器自己加一层主备冗余。两台Nginx同时在线,对外只暴露一个虚拟IP,主节点出现异常时备节点自动顶上去,整个切换过程不需要修改DNS,也不需要客户端重新建立连接。

Nginx负载均衡叠加Keepalived双机热备如何落地?

一、先看清单点故障在哪里

很多环境下,Nginx被配置成入口网关,后面挂着多个应用节点,例如192.168.10.21和192.168.10.22分别运行Java服务。流量经过Nginx时,根据upstream里的策略分发到不同节点。这个方案在应用层实现了冗余,但Nginx自身变成了最脆弱的一环。只要负责反向代理的机器需要停机维护、升级内核或发生硬件故障,即使后端服务全部健康,外部请求依然无法进入。

Keepalived解决这个问题的思路来自VRRP协议。VRRP可以在多台路由器或服务器之间选举出一个主设备,主设备持有虚拟IP和虚拟MAC地址,其他设备处于备份状态。主设备周期性发送通告报文,备份设备在超时后认为主设备失效,随即接管虚拟IP。由于虚拟IP是独立的,客户端始终访问同一个地址,后端完全不知道入口已经切换到了另一台物理机。

实际部署时,至少需要两台Linux服务器,每台都安装Nginx和Keepalived。为了便于后文说明,这里假设节点A的物理IP是192.168.10.11,节点B的物理IP是192.168.10.12,虚拟IP是192.168.10.100。两台Nginx的配置保持一致,后端应用池也指向同一组应用节点。Keepalived只负责决定哪台机器持有虚拟IP,一旦持有虚拟IP的机器上的Nginx进程异常,Keepalived要么尝试拉起Nginx,要么主动降低自己的优先级让虚拟IP漂移到对端。

二、Nginx侧:让负载均衡和健康检查先跑通

在配置Keepalived之前,登录节点A和节点B,先确认两台机器上的Nginx都能独立访问后端。最简单的反向代理配置如下,重点在upstream块和proxy_pass。示例中定义了一个名为backend的服务器组,包含两个应用节点,并设置了权重和被动健康检查阈值。

upstream backend {
    server 192.168.10.21:8080 weight=3 max_fails=2 fail_timeout=15s;
    server 192.168.10.22:8080 weight=1 max_fails=2 fail_timeout=15s;
    keepalive 32;
}

server {
    listen 80;
    server_name localhost;

    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_connect_timeout 3s;
        proxy_read_timeout 10s;
    }
}

这里的max_fails和fail_timeout是开源Nginx自带的被动健康检查机制。比如max_fails=2表示在fail_timeout规定的时间内,如果某个后端节点连续失败两次,Nginx就会暂时把它摘除,不再转发请求。这种方式依赖真实请求触发,不像主动健康检查那样定时探测,但胜在无需额外模块,配置简单,适合大多数业务场景。如果业务对故障感知要求更高,可以编译第三方模块nginx_upstream_check_module实现主动探测,不过那会增加维护成本,通常不推荐一上来就引入。

配置完成后使用nginx -t检查语法,再执行nginx -s reload。此时在两台机器上分别访问http://192.168.10.11和http://192.168.10.12,都应该能看到后端返回的内容。这就是Keepalived介入前需要达到的状态:任何一台Nginx单独工作都能正常转发。很多人跳过这一步直接配Keepalived,导致切换后VIP虽然漂移了,但备机自己的Nginx配置其实不能转发,最终依然访问失败。

三、Keepalived侧:用VRRP让虚拟IP自动漂移

Keepalived的配置分为全局定义、检测脚本和VRRP实例三部分。先在节点A上编辑/etc/keepalived/keepalived.conf,配置为MASTER角色,优先级设高一些。关键是要关联一个检测Nginx进程的脚本,否则Keepalived只能感知机器是否宕机,无法感知Nginx是否崩溃。

global_defs {
    router_id LB_NODE_A
}

vrrp_script chk_nginx {
    script "/etc/keepalived/check_nginx.sh"
    interval 2
    weight -20
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1234
    }
    virtual_ipaddress {
        192.168.10.100/24 dev eth0
    }
    track_script {
        chk_nginx
    }
}

节点B的配置结构相同,只需要把router_id改为LB_NODE_B,state改为BACKUP,priority改为90即可。两台机器的virtual_router_id必须一致,否则会被认为是不同的VRRP组,无法互通。认证密码也需要完全一致,不然心跳报文会被丢弃。

检测脚本的内容很简单,先检查nginx进程是否存在,如果不存在则尝试启动一次,等待两秒后再次检查。如果仍然失败,脚本返回非零退出码,Keepalived会按照weight -20的规则把本机优先级从100降到80。此时对端节点B优先级为90,自然就能抢占虚拟IP。脚本如下:

#!/bin/bash
if ! killall -0 nginx >/dev/null 2>&1; then
    systemctl start nginx
    sleep 2
    if ! killall -0 nginx >/dev/null 2>&1; then
        exit 1
    fi
fi
exit 0

注意脚本必须赋予执行权限,例如chmod +x /etc/keepalived/check_nginx.sh。Keepalived默认以root权限运行,能够执行systemctl start nginx。如果脚本中使用了systemctl,需要确保Keepalived进程能够调用该命令。在一些精简版系统里,如果Keepalived被限制在非特权用户下运行,脚本会执行失败,通常检查日志会发现权限拒绝。

关于抢占行为,默认情况下MASTER恢复后会自动抢回虚拟IP,这在某些场景会导致短暂抖动。如果希望避免频繁切换,可以在两边的vrrp_instance里都加上nopreempt参数,并且把节点A设置为state BACKUP、优先级仍为100,让最初启动的那台成为实际主节点。但这种模式对排障要求更高,生产环境需要根据网络质量评估。

四、切换验证与生产避坑指南

配置完成后,先启动节点A的Keepalived,再启动节点B。在节点A上执行ip addr show eth0,应该能看到除了192.168.10.11之外,还多出一个192.168.10.100。使用客户端访问http://192.168.10.100,能正常获得后端响应。此时虚拟IP确实绑定在节点A上。

接下来做故障模拟:在节点A上手动停掉Nginx,例如systemctl stop nginx。由于Keepalived的检测脚本间隔为2秒,脚本会先尝试启动Nginx,如果启动失败才会降低优先级。因此为了看到漂移,应当先把Nginx彻底禁用,例如systemctl stop nginx后立即改掉nginx.service或删除执行权限,制造无法恢复的状态。约2到4秒后,在节点B上执行ip addr show eth0,能看到虚拟IP已经转移到节点B。客户端再次访问192.168.10.100仍然正常,说明切换成功。

生产环境需要额外注意几个细节。VRRP默认使用组播地址224.0.0.18,如果两台机器之间有防火墙或云平台安全组,必须放行对应的VRRP协议流量。部分虚拟化环境禁止组播,此时可以在Keepalived配置中改用单播,通过unicast_src_ip和unicast_peer指定两边的物理IP。这样虽然绕开了组播限制,但配置文件更依赖准确的IP,迁移时容易出错。

另一个容易踩坑的地方是脑裂。当心跳链路中断时,两边都认为自己是主节点,同时持有虚拟IP,会导致间歇性访问失败。预防脑裂的常见做法包括使用独立的私网心跳、设置合理的advert_int和preempt_delay,以及在交换机上配置端口隔离。真正的强一致需要借助仲裁节点或云厂商的浮动IP能力,Keepalived本身只能提供尽力而为的高可用。对大多数中小型业务来说,只要网络稳定,Nginx加Keepalived的双机热备已经足够降低入口故障。

最后要强调一点,Keepalived解决的是入口层的高可用,不等于业务系统整体高可用。如果后端数据库、缓存或应用节点本身没有冗余,仍然可能在其他位置出现单点。把负载均衡层做扎实之后,应该继续审视整个请求链路,从DNS解析、Nginx入口、应用服务到数据库连接,每一层都具备冗余能力,整个系统才算真正具备抗故障能力。

Nginx负载均衡Keepalived双机热备高可用修改时间:2026-09-27 21:55:55

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0927/62718.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。