解决服务单点故障!Nginx+Keepalived 双机热备,故障秒切换生产方案
前言🤔
很多 Linux 小白学习 Keepalived 时全程混乱,普遍存在这些痛点:
- 看不懂 VRRP 底层协议,搞不清 VIP、Master、Backup、VRID、优先级核心概念;
- 实验逻辑断裂,不知道先配 IP 还是先装软件,敲完上一行完全不知道下一条命令;
- 配置文件几十行参数分不清含义,state/priority/nopreempt/auth 完全不懂作用;
- 搭建完集群出现脑裂双主抢 VIP,网站同时访问两台服务器,数据错乱找不到原因;
- 主节点宕机 VIP 不会自动漂移,切换失败只会盲目重启服务;
- 分不清抢占模式、不抢占模式适用场景,线上业务频繁抖动;
- 所有命令只会复制,-y、–now、cp {,.ori} 等参数不懂含义,输出结果不会解读。
📌统一实验环境 CentOS7
主机名 IP 地址 集群角色 核心任务 web1.jhl.cloud 10.1.8.11 Keepalived 主节点(抢占模式) 优先持有 VIP,Nginx 业务主服务 web2.jhl.cloud 10.1.8.12 Keepalived 备节点 主故障自动接管 VIP client1.jhl.cloud 10.1.8.21 测试客户端 访问虚拟 IP 验证业务切换 虚拟 VIP 10.1.8.100 统一业务访问入口 主节点持有,故障自动漂移备机
第一部分 Keepalived&VRRP 底层原理
1.1 Keepalived 是什么?线上运维核心作用⚠️
Keepalived 是 C 语言编写的 Linux 高可用软件,底层依托VRRP 虚拟路由冗余协议,核心解决服务单点故障问题。
企业生产真实价值:
- 消除单点故障:Nginx、MySQL、Redis等单服务器服务宕机,VIP自动漂移至备机,业务无感知切换;
- 统一访问入口:客户端只需要访问一个固定VIP,无需区分后端多台服务器;
- 多层故障检测:支持3/4/7层健康检测,网卡、端口、程序故障均可触发自动切换;
- 轻量化部署,配置简单,无需额外复杂集群软件,中小企业HA首选;
- 配套nopreempt不抢占模式,避免主节点恢复后频繁切流量,保障业务稳定。
1.2 VRRP 协议核心解决的痛点
传统单网关 / 单 Web 服务器一旦宕机,所有客户端完全断网 / 网站打不开;VRRP 将把多台物理服务器,虚拟成一台逻辑上的网关 / 服务器,共用同一个虚拟 IP(VIP),主设备故障时备份设备自动接管 IP,业务不中断。
| 名词 | 全称 | 通俗解释 | 实验示例 |
|---|---|---|---|
| VRRP 组 | 虚拟路由组 | 同一套高可用集群,VRID 必须完全一致 | VRID 51 |
| VRID | 虚拟路由 ID | 区分不同集群,1-255,同组所有机器相同 | 51 |
| VIP | 虚拟 IP | 对外统一访问地址,仅 Master 持有 | 10.1.8.100/24 |
| Master | 主节点 | 优先级更高,正常持有 VIP,每秒发心跳包 | web1 priority=110 |
| Backup | 备节点 | 监听心跳,主失联自动升级为主 | web2 priority=100 |
| Priority | 优先级 | 数值 0-255,越大越优先抢占 VIP | 110>100 |
| Advert_int | 心跳间隔 | Master 发送 VRRP 心跳包周期,默认 1 秒 | advert_int 1 |
| 组播地址 | VRRP 通信地址 | 224.0.0.18,节点间心跳通信固定地址 | UDP 112 端口 |
1.3 VRRP 完整工作流程🤔
- 集群初始化,两台机器全部进入 Backup 状态;
- 各自等待 MASTER_DOWN 定时器,优先级高的 web1 更快完成等待,率先竞选 Master;
- web1 成为 Master,绑定 VIP 10.1.8.100,每秒向 224.0.0.18 发送心跳通告;
- web2 持续监听心跳包,收到则维持 Backup;
- web1 宕机 / 关闭 Keepalived,web2 收不到心跳,定时器超时自动升级 Master,绑定 VIP;
- web1 恢复服务,抢占模式下立刻夺回 VIP;不抢占模式则保持 web2 为主。
1.4 脑裂(Split-Brain)致命故障解析🚨
脑裂定义:主备节点心跳通信中断,但两台服务器本身正常,两台机器同时竞选Master、同时绑定VIP,客户端流量分裂,读写业务出现数据错乱、页面交替跳转。 产生核心原因:
- 服务器之间UDP 112端口防火墙拦截,心跳包无法互通;
- 网卡故障、交换机链路断开,组播报文无法传输;
- 集群VRID、认证密码配置不一致,节点无法识别同组设备;
- 服务器CPU/内存耗尽,无法发送心跳包。
脑裂线上危害:数据库双写冲突、网站随机跳转,业务完全不可用!
5套生产脑裂预防方案表格
| 方案 | 实操配置 | 核心作用 |
|---|---|---|
| VRRP 密码认证 | 所有节点 auth_pass 配置完全一致 | 拒绝非法节点加入集群,防止异常节点抢占 VIP |
| 放行 VRRP 协议 | firewall-cmd --add-protocol=vrrp --permanent && firewall-cmd --reload | 打通 112 端口 VRRP 心跳通信,确保节点间心跳报文正常传输 |
| 多网卡心跳检测 | track_interface 配置多块物理网卡 | 单网线 / 网卡故障时,自动通过备用网卡传输心跳,避免心跳中断 |
| nopreempt 不抢占模式 | 高优先级节点配置中添加 nopreempt 参数 | 主节点故障恢复后,不强行抢占 VIP,避免业务流量频繁切换抖动 |
| 故障隔离脚本 | 配置 notify_master 监控脚本 | 检测到脑裂 / 双主异常时,自动执行关机 / 停服务脚本,实现故障隔离 |
1.5 Keepalived 三层检测机制
- 三层网络层(ICMP):ping 检测对端 IP,不通判定故障;
- 四层传输层(TCP 端口):检测 80/22 等端口,Nginx 宕机自动切换;
- 七层应用层(自定义脚本):执行业务脚本,程序异常触发 VIP 漂移。
第二部分 完整高可用集群实验
业务诉求:希望有一个永不变化的统一访问入口,一台 web 坏了,另一台自动顶上,全程不需要人工操作,用户感知不到故障。
实现这个诉求的技术方案,就是 Keepalived + VRRP 虚拟 IP(VIP)高可用架构,也就是本次实验要验证的能力。
实验最终想要验证的目标
- 对外提供一个固定不变的虚拟 IP VIP=10.1.8.100,用户永远只访问这个地址;
- 正常情况下 VIP 在主节点 web1;客户端访问 VIP,流量落到 web1 处理网页请求;
- 当 web1 故障(关机、断网、web 服务停止),VIP自动漂移到备机 web2;
- 客户端继续访问 10.1.8.100,流量自动切换到 web2,用户不用修改任何地址,无感知切换;
- web1 故障修复上线后,可以配置两种策略:
- 抢占模式:web1 恢复后,VIP 重新抢回来;
- 非抢占模式:VIP 继续留在 web2,避免二次波动。
实验价值:
这个实验就是模拟线上服务器故障场景,验证 VRRP 协议实现虚拟 IP 自动故障转移,搭建一套具备自动容灾能力的 Web 服务集群,解决单点服务器故障导致业务中断的问题,理解生产环境高可用服务最基础、最经典的主备架构原理。
结合拓扑完整复盘整条访问链路
正常状态:
client1 (10.1.8.21) →交换机 →访问 VIP (10.1.8.100) →web1 (持有 VIP) →返回网页
故障状态:
web1 宕机 →VIP 自动漂移 web2
client1 (10.1.8.21) →交换机 →访问 VIP (10.1.8.100) →web2 (持有 VIP) →返回网页
用户全程只访问 10.1.8.100,后端服务器切换完全透明。
实验思路:
- 三台机器分别修改主机名、配置静态固定 IP;
- web1、web2 两台服务器安装 Nginx,写入区分页面;
- web1、web2 安装 Keepalived,备份原始配置文件;
- 编写主节点 web1 抢占模式配置(priority110、state MASTER);
- 编写备节点 web2 配置(priority100、state BACKUP);
- 两台服务器防火墙放行 VRRP 协议;
- 启动 Keepalived,验证 VIP 默认在 web1;
- 客户端 curl VIP 访问,页面返回 web1 内容;
- 停止 web1 Keepalived,验证 VIP 自动漂移 web2;
- web1 重启服务,抢占模式下自动夺回 VIP;
- 进阶不抢占模式实验:修改 web1 配置增加 nopreempt,主恢复不切流量;
- 配置 Keepalived 独立日志,方便故障排查;
- 脑裂模拟与修复实操。
实验1 三台机器初始化(主机名 + 静态 IP)
实验目的🤔
固定静态 IP 防止 DH 地址变动导致心跳通信失败,区分三台机器角色,方便后续实验操作。
线上运维作用
高可用集群必须静态 IP,动态 IP 会导致 VRRP 心跳永久中断,直接触发脑裂故障。
一、web1.jhl.cloud 全套命令(每行逐项参数解释,保留完整提示符)
# hostnamectl set-hostname:永久修改系统主机名,重启永久生效# set-hostname 后跟自定义完整主机域名[root@localhost ~]# hostnamectl set-hostname web1.jhl.cloud# nmcli connection modify:修改网卡参数,ens33为网卡设备名# ipv4.method manual:关闭DH,启用静态IP手动模式# ipv4.addresses 10.1.8.11/24:本机IP,/24代表24位子网掩码# ipv4.gateway 10.1.8.2:内网网关地址# ipv4.dns 10.1.8.2:内网DNS解析服务器# autoconnect yes:开机自动激活网卡[root@localhost ~]# nmcli connection modify ens33 ipv4.method manual ipv4.addresses 10.1.8.11/24 ipv4.gateway 10.1.8.2 ipv4.dns 10.1.8.2 autoconnect yes# nmcli connection up:重载网卡配置,无需重启立即生效# up 参数:启用网卡连接,应用刚修改的静态IP配置[root@localhost ~]# nmcli connection up ens33二、web2.jhl.cloud 全套初始化命令
[root@localhost ~]# hostnamectl set-hostname web2.jhl.cloud[root@localhost ~]# nmcli connection modify ens33 ipv4.method manual ipv4.addresses 10.1.8.12/24 ipv4.gateway 10.1.8.2 ipv4.dns 10.1.8.2 autoconnect yes[root@localhost ~]# nmcli connection up ens33三、client1.jhl.cloud 全套初始化命令
[root@localhost ~]# hostnamectl set-hostname client1.jhl.cloud[root@localhost ~]# nmcli connection modify ens33 ipv4.method manual ipv4.addresses 10.1.8.21/24 ipv4.gateway 10.1.8.2 ipv4.dns 10.1.8.2 autoconnect yes[root@localhost ~]# nmcli connection up ens33实验 2 两台 Web 服务器部署 Nginx 业务
实验目的🤔
搭建后端 Web 服务,用于验证 VIP 切换后页面自动变更,直观观察故障漂移效果。
运维作用
模拟企业网站业务,完整复现线上 Web 高可用架构。
web1、web2 两台服务器统一执行全套命令
# wget:下载阿里EPEL软件源# -O 参数:指定下载文件输出路径[root@web1 ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo# yum install -y:yum在线安装软件# -y 参数:自动确认所有交互提问,无需手动输入y# nginx:Web网站服务程序[root@web1 ~]# yum install -y nginx# echo 输出文本重定向写入网站首页# $(hostname) 自动获取本机主机名,区分两台服务器页面[root@web1 ~]# echo Welcome to $(hostname) > /usr/share/nginx/html/index.html# systemctl enable --now:设置开机自启并立刻启动服务# enable:开机自动运行;--now:当前会话立即启动;nginx:服务名[root@web1 ~]# systemctl enable nginx.service --now客户端测试业务连通性
# curl:HTTP访问工具,直接输出页面内容[root@client1 ~]# curl 10.1.8.11Welcome to web1.jhl.cloud[root@client1 ~]# curl 10.1.8.12Welcome to web2.jhl.cloud实验 3 安装 Keepalived + 备份原始配置
实验目的🤔
安装高可用核心程序,备份默认配置防止改错无法恢复。
web1、web2 两台机器全部执行
# yum安装keepalived高可用软件包[root@web1 ~]# yum install -y keepalived# cp {,.ori} 文件备份语法# cp:复制文件;/etc/keepalived/keepalived.conf 原配置# {,.ori} 等价于复制为 keepalived.conf.ori 备份文件[root@web1 ~]# cp /etc/keepalived/keepalived.conf{,.ori}实验 4 抢占模式 Keepalived 完整配置(web1 主节点)
实验思路
- global_defs 全局段设置 router_id,集群内唯一标识;
- vrrp_instance 定义 VRRP 集群,state 初始 MASTER;
- priority 110 高于备机,故障恢复自动抢占 VIP;
- 开启密码认证,防止脑裂;
- 定义虚拟 VIP 10.1.8.100/24。
# vim:文本编辑器打开Keepalived主配置文件[root@web1 ~]# vim /etc/keepalived/keepalived.conf完整配置逐行逐字段详细注释
!Configuration Fileforkeepalived# 全局配置段 global_defsglobal_defs{router_id web1.jiang.cloud# router_id:本机集群标识,集群所有机器不能重复}# VRRP集群实例,自定义名称nginxvrrp_instance nginx{state MASTER# 机器启动初始状态,仅初始化生效,最终由priority竞选interface ens33# VRRP心跳、VIP绑定的物理网卡virtual_router_id51# VRID集群编号,同组所有机器必须完全一致(1-255)priority110# 优先级,数值越大优先成为Master,高于备机100advert_int1# Master心跳发送间隔,单位秒,默认1秒# VRRP身份认证配置,防止脑裂、非法节点接入authentication{auth_type PASS# 认证类型:PASS明文密码;AH加密认证auth_pass jhl@123# 集群统一密码,所有节点必须完全相同,最多8位有效字符}# 定义集群虚拟VIP地址virtual_ipaddress{10.1.8.100/24}}[root@web1 ~]# ip -br alo UNKNOWN127.0.0.1/8 ::1/128 ens33 UP10.1.8.11/2410.1.8.100/24重点结论:VIP 出现在 web1机器上,代表当前 web2 已经成为 VRRP 主节点(MASTER),接管了虚拟 IP。
web2 备节点抢占模式配置
[root@web2 ~]# vim /etc/keepalived/keepalived.conf!Configuration Fileforkeepalived global_defs{router_id web2.jiang.cloud}vrrp_instance nginx{state BACKUP# 备机初始状态interface ens33 virtual_router_id51priority100# 优先级低于web1,正常不会抢占advert_int1authentication{auth_type PASS auth_pass jhl@123}virtual_ipaddress{10.1.8.100/24}}[root@web2 ~]# ip -br alo UNKNOWN127.0.0.1/8 ::1/128 ens33 UP10.1.8.12/24实验 5 放行 VRRP 防火墙规则(防脑裂核心步骤⚠️)
实验目的
放开 UDP112 端口 VRRP 组播心跳,两台机器可正常收发心跳报文,避免脑裂故障。
web1、web2 两台服务器执行
# firewall-cmd --add-protocol=vrrp:临时放行VRRP协议# --permanent 参数:永久写入防火墙规则,重启不失效[root@web1 ~]# firewall-cmd --add-protocol=vrrp --permanent# --reload:重载防火墙配置,永久规则立即生效[root@web1 ~]# firewall-cmd --reload实验 6 启动服务,验证 VIP 抢占模式切换
步骤 1 两台机器开机自启并启动 Keepalived
# systemctl enable --now:开机自启+立即启动服务[root@web1 ~]# systemctl enable keepalived.service --now[root@web2 ~]# systemctl enable keepalived.service --now步骤 2 查看网卡 VIP 绑定状态
# ip -br a show:简洁查看网卡IP地址# -br 参数:brief简洁输出模式,过滤冗余信息[root@web1 ~]# ip -br a show ens33ens33 UP10.1.8.11/2410.1.8.100/24 fe80::xxxx/64# 现象解读:web1持有虚拟VIP,为主节点[root@web2 ~]# ip -br a show ens33ens33 UP10.1.8.12/24 fe80::xxxx/64# 现象解读:web2无VIP,为备份节点步骤 3 客户端访问虚拟 IP 验证业务
[root@client1 ~]# curl 10.1.8.100Welcome to web1.jhl.cloud# 输出web1页面,当前主节点正常提供服务步骤 4 模拟主节点故障,停止 Keepalived
# stop:立即停止Keepalived服务,断开心跳发送[root@web1 ~]# systemctl stop keepalived.service# 再次查看web1网卡,VIP消失[root@web1 ~]# ip -br a show ens33ens33 UP10.1.8.11/24 fe80::xxxx/64# web2自动升级Master,绑定VIP[root@web2 ~]# ip -br a show ens33ens33 UP10.1.8.12/2410.1.8.100/24# 客户端再次访问VIP,自动切换web2页面[root@client1 ~]# curl 10.1.8.100Welcome to web2.jhl.cloud步骤 5 恢复 web1 服务,抢占模式自动夺回 VIP
# start 启动Keepalived服务[root@web1 ~]# systemctl start keepalived.service# 查看web1重新持有VIP[root@web1 ~]# ip -br a show ens33ens33 UP10.1.8.11/2410.1.8.100/24# 客户端页面切回web1[root@client1 ~]# curl 10.1.8.100Welcome to web1.jhl.cloud⚠️抢占模式缺点:业务高峰期主节点维护重启,流量瞬间全部切回主,会造成业务抖动,生产核心业务推荐不抢占模式!
实验 7 进阶:不抢占 nopreempt 模式(生产推荐)
实验目的🤔
高优先级主节点恢复后,不强行抢占 VIP,流量停留在当前备机,避免业务频繁切换抖动。
完整修改配置(仅 web1 操作)
[root@web1 ~]# vim /etc/keepalived/keepalived.conf修改后核心片段(新增 nopreempt)
vrrp_instance nginx{state BACKUP# 所有节点统一写BACKUP,不再写MASTERnopreempt# 不抢占开关,高优先级机器恢复不抢VIPinterface ens33 virtual_router_id51priority110advert_int1authentication{auth_type PASS auth_pass jhl@123}virtual_ipaddress{10.1.8.100/24}}重载配置生效
[root@web1 ~]# systemctl restart keepalived.service验证不抢占效果
- 关闭 web1,web2 接管 VIP;
- 启动 web1,web1 优先级 110 更高,但不会抢夺 VIP;
- 客户端持续访问,页面始终是 web2;
- 只有 web2 停止服务后,web1 才会自动接管 VIP。
# 关闭web1[root@web1 ~]# systemctl stop keepalived.service# web2持有VIP,curl输出web2页面[root@client1 ~]# curl 10.1.8.100Welcome to web2.jhl.cloud# 启动web1,不抢占[root@web1 ~]# systemctl start keepalived.service# 客户端页面不变[root@client1 ~]# curl 10.1.8.100Welcome to web2.jhl.cloud# 关闭web2,web1自动接管[root@web2 ~]# systemctl stop keepalived.service[root@client1 ~]# curl 10.1.8.100Welcome to web1.jhl.cloud实验 8 Keepalived 独立日志分离(排错必备)
实验目的
默认日志混杂在 /var/log/messages,单独拆分日志方便快速定位 VIP 漂移、脑裂、心跳报错。
1.让 keepalived 把日志发送到 local0 日志设施;
2.配置 rsyslog 抓取 local0 的所有日志,单独保存到 /var/log/keepalived.log,实现日志分离;
3.同时可选开启 debug 模式,打印 VRRP 详细交互过程,方便排错。
步骤 1 修改 keepalived 启动参数
# vim编辑服务启动配置文件[root@web1 ~]# vim /etc/sysconfig/keepalived修改内容:
# 这个文件是 systemd 启动 keepalived 服务时读取的启动命令行参数。KEEPALIVED_OPTIONS="-D -S 0"# 参数逐项解释:# -D:后台守护进程运行,默认必选# -S 0:指定syslog日志输出通道为local0。keepalived 输出日志时,统一打上 local0.* 标签发给系统 rsyslog 服务。# 补充:-d 开启debug调试日志,排错临时使用,生产不要长期开启简单类比:
keepalived 生产日志,并盖上一个邮戳 local0;
rsyslog 根据邮戳,决定这份日志投递到哪个文件。
步骤 2 配置 rsyslog 分流日志
rsyslog 格式标准
格式:设施.优先级 存储目标
local0:设施(对应上面-S 0),Linux 预留出来给自定义程序使用(local0~local7 共 8 组)*:代表所有优先级(info、notice、warning、error、debug 全部收下)/var/log/keepalived.log:日志写入的独立文件
rsyslog 是 CentOS/RHEL 系统里默认的系统日志服务。
服务器上所有程序(systemd、ssh、nginx、keepalived 等)产生的日志,理论上都交给 rsyslog 统一接收、筛选、保存。
默认主配置文件:
/etc/rsyslog.conf
# /etc/rsyslog.d/keepalived.conf,专门给 keepalived 自定义的一条日志过滤规则文件。[root@web1 ~]# vim /etc/rsyslog.d/keepalived.conf# local0通道日志全部输出到独立文件local0.* /var/log/keepalived.log步骤 3 重启日志服务 + Keepalived
# restart 重启rsyslog日志服务,加载新分流规则,keepalived 日志策略[root@web1 ~]# systemctl restart rsyslog# 让 keepalived 读取 /etc/sysconfig/keepalived 里面新的启动参数 -D -d -S 0。不重启 keepalived,新参数不会生效,依然使用旧的日志输出方式![root@web1 ~]# systemctl restart keepalived.service# 实时监控高可用切换日志# tail -f:实时追踪日志输出[root@web1 ~]# tail -f /var/log/keepalived.log第三部分 Keepalived 高频故障排查指南🚨
1. 脑裂双主同时持有 VIP
| 故障根因 | 完整解决方案 |
|---|---|
| 防火墙未放行 VRRP 协议 | 执行 firewall-cmd --add-protocol=vrrp --permanent && reload |
| 两台机器 VRID / 认证密码不一致 | 统一 virtual_router_id、auth_pass jhl@123 |
| 跨网段组播 224.0.0.18 不通 | 同网段部署,或配置单播 VRRP |
2 主节点宕机 VIP 不漂移
- 备机防火墙拦截 VRRP 心跳;
- advert_int 心跳间隔过大,MASTER_DOWN 超时久;
- 网卡名称 interface 配置错误。
3 主恢复频繁抢占,业务抖动
解决方案:主节点配置 nopreempt 不抢占模式。
核心排错命令全注释
# 实时查看Keepalived切换日志tail-f/var/log/keepalived.log# 查看网卡VIP绑定状态ip-bra# 重启服务重载配置systemctl restart keepalived# 查看服务运行状态systemctl status keepalived文末总结💬
- Keepalived 基于 VRRP 协议实现 Linux 服务高可用,虚拟 VIP 是统一业务访问入口;
- Master 由 priority 优先级竞选,抢占模式主恢复自动切流量,生产优先 nopreempt 不抢占;
- 集群所有节点 VRID、VRRP 密码必须完全一致,防火墙放行 VRRP 协议防止脑裂;
- 故障切换逻辑:Master 停止发送心跳→Backup 超时升级为主,自动绑定 VIP;
- 线上 Web / 数据库高可用,双机热备是最低成本消除单点故障方案。
互动提问💬 你们线上 Keepalived 用抢占还是不抢占模式?搭建集群踩过脑裂故障吗?评论区交流排坑经验!