第一篇:Keepalived 高可用实战:VIP 漂移与 Nginx 主备切换完整指南

一、Keepalived 是什么

Keepalived 是一款运行在 Linux 下的高可用(HA)管理软件 ,基于 VRRP(Virtual Router Redundancy Protocol,虚拟路由冗余协议) 实现。它的核心作用是:通过一组服务器对外提供一个虚拟 IP(VIP) ,当主节点故障时,备用节点自动接管这个 VIP,实现服务的故障自动转移,从而保证业务不中断。

一句话概括:Keepalived 负责"IP 漂移",让多台机器伪装成同一个网关/入口,谁挂了另一个人顶上。

常见搭配:

  • Keepalived + Nginx → Web/反向代理高可用
  • Keepalived + HAProxy → 负载均衡入口高可用
  • Keepalived + MySQL → 数据库主从高可用(配合 MHA/MMM)
  • Keepalived 原生还可做 LVS 集群管理

本文以 Keepalived + Nginx 实现 Web 服务主备高可用 为实战案例,覆盖从安装到故障转移验证的全流程。

二、核心原理:VRRP 协议与 VIP 漂移

2.1 VRRP 是什么

VRRP 是标准的网络协议(RFC 5798),它把一组路由器(这里指运行 Keepalived 的服务器)组合成一个虚拟路由器组 ,对外只暴露一个虚拟 IP。

组内成员分为角色:

  • MASTER(主):真正持有 VIP,负责接收发往 VIP 的流量。
  • BACKUP(备):监听 MASTER 的心跳,MASTER 故障时抢过 VIP 顶替。

2.2 工作流程

  1. 多台服务器(主+备)通过 VRRP 组播报文互相发送心跳(默认每 1 秒一次)。
  2. MASTER 正常时,VIP 绑在 MASTER 网卡上,BACKUP 处于待命状态。
  3. 若 BACKUP 连续多个心跳周期没收到 MASTER 的报文(master_down),就判定 MASTER 故障。
  4. BACKUP 立即把 VIP 绑定到自己网卡,并发送 ARP 广播告知网关和客户端"VIP 的 MAC 地址变了",流量随之切到备机。
  5. MASTER 恢复后,根据**优先级(priority)**高低,优先级高者重新抢占(preempt)回 VIP。

2.3 关键概念

概念 说明
VIP 虚拟 IP,漂移的入口地址,客户端只认它
priority 优先级(1~255),数值越大越优先当 MASTER
vrrp_instance VRRP 实例,一组参与漂移的成员
state 角色声明:MASTER / BACKUP / BACKUP
virtual_router_id 虚拟路由器 ID(0~255),同组必须一致
unicast_src_ip 单播源 IP(跨网段或多播受限时用)
nopreempt 非抢占模式,MASTER 恢复后不主动抢回

重要提示 :state 只是初始声明,真正决定谁是 MASTER 的是 priority 和心跳状态。BACKUP 也可以因为 priority 更高而成为 MASTER。

三、架构设计

本文实战拓扑(2 台节点 + 1 个虚拟 IP):

复制代码
 

|---|-------------------------------------------------------|
| | +-------------------+ |
| | | 客户端/访问者 | |
| | | 访问 http://VIP | |
| | +---------+---------+ |
| | | |
| | (VIP 192.168.1.100) |
| | | |
| | +-----------------+-----------------+ |
| | | | |
| | +------+-------+ +------+-------+ |
| | | node1 | | node2 | |
| | | MASTER | VRRP心跳/组播 | BACKUP | |
| | | 192.168.1.11| <-----------------> | 192.168.1.12| |
| | | Nginx | | Nginx | |
| | +--------------+ +--------------+ |

  • node1:192.168.1.11,优先级 150,默认 MASTER
  • node2:192.168.1.12,优先级 100,默认 BACKUP
  • VIP:192.168.1.100
  • 系统:CentOS 7.x / 8.x
  • 软件:Keepalived 2.4.3 + Nginx 1.24

客户端永远访问 VIP(192.168.1.100)。node1 挂了,VIP 漂移到 node2,业务不断。

四、安装 Keepalived

4.1 方式一:YUM 安装(最快)

bash

复制代码
 

|---|-----------------------------------|
| | # CentOS/RHEL |
| | yum install -y keepalived nginx |
| | |
| | # 查看版本 |
| | keepalived --version |

4.2 方式二:源码编译安装(推荐,版本最新)

以官方最新稳定版 Keepalived 2.4.3 为例:

bash

复制代码
 

|---|-------------------------------------------------------------------------------|
| | # 1. 安装编译依赖 |
| | yum install -y gcc openssl-devel libnl3-devel popt-devel ipset-devel \ |
| | libnfnetlink-devel |
| | |
| | # 2. 下载源码 |
| | cd /usr/local/src |
| | wget https://keepalived.org/software/keepalived-2.4.3.tar.gz |
| | tar zxf keepalived-2.4.3.tar.gz |
| | cd keepalived-2.4.3 |
| | |
| | # 3. 编译安装 |
| | ./configure --prefix=/usr/local/keepalived |
| | make -j$(nproc) && make install |
| | |
| | # 4. 拷贝配置与启停脚本(习惯放默认位置) |
| | cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/ |
| | cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/ |
| | mkdir -p /etc/keepalived |
| | ln -s /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/ |
| | |
| | # 5. 查看版本确认 |
| | /usr/local/keepalived/sbin/keepalived --version |

五、配置详解:keepalived.conf

Keepalived 的配置文件默认在 /etc/keepalived/keepalived.conf,由三大部分组成:

  • global_defs:全局配置
  • vrrp_instance:VRRP 实例(高可用的核心)
  • vrrp_script / track_script:自定义健康检查脚本

5.1 全局配置(global_defs)

conf

复制代码
 

|---|--------------------------------------------------|
| | global_defs { |
| | router_id KEEPALIVED_NODE1 # 路由器标识,仅用于区分,可自定义 |
| | notification_email { |
| | admin@example.com # 报警邮箱(需配置 sendmail) |
| | } |
| | notification_email_from keepalived@example.com |
| | smtp_server 127.0.0.1 |
| | smtp_connect_timeout 30 |
| | vrrp_skip_check_adv_addr # 跳过对通告地址的检查,防止误报 |
| | vrrp_strict # 严格模式,开启后限制较严,调试时可先注释 |
| | vrrp_garp_interval 0 |
| | vrrp_gna_interval 0 |
| | } |

5.2 实例配置(vrrp_instance)------主节点

conf

复制代码
 

|---|-------------------------------------------------------------|
| | vrrp_instance VI_1 { |
| | state MASTER # 初始角色:主 |
| | interface eth0 # 绑定网卡,务必与 VIP 所在网卡一致 |
| | virtual_router_id 51 # 虚拟路由器ID,同组两台必须一致 |
| | priority 150 # 优先级,越大越优先,主=150,备=100 |
| | advert_int 1 # 心跳通告间隔(秒),默认1秒 |
| | nopreempt # 非抢占(可选,两台都配则MASTER挂了不抢回) |
| | authentication { |
| | auth_type PASS # 认证方式:PASS / AH |
| | auth_pass 123456 # 认证密码,同组必须一致(≤8位) |
| | } |
| | unicast_src_ip 192.168.1.11 # 本机真实IP |
| | unicast_peer { |
| | 192.168.1.12 # 对端节点IP(单播模式必填) |
| | } |
| | virtual_ipaddress { |
| | 192.168.1.100/24 dev eth0 label eth0:0 # VIP,dev和label可省略 |
| | } |
| | track_script { |
| | check_nginx # 关联健康检查脚本(见6.2) |
| | } |
| | } |

5.3 备份节点配置

只需改三处,其余保持一致:

conf

复制代码
 

|---|------------------------------------------|
| | vrrp_instance VI_1 { |
| | state BACKUP # 初始角色:备 |
| | interface eth0 |
| | virtual_router_id 51 # 保持一致 |
| | priority 100 # 比主小 |
| | advert_int 1 |
| | authentication { |
| | auth_type PASS |
| | auth_pass 123456 # 保持一致 |
| | } |
| | unicast_src_ip 192.168.1.12 |
| | unicast_peer { |
| | 192.168.1.11 |
| | } |
| | virtual_ipaddress { |
| | 192.168.1.100/24 dev eth0 label eth0:0 |
| | } |
| | track_script { |
| | check_nginx |
| | } |
| | } |

多播 vs 单播 :同网段默认用多播 (不需要 unicast_src_ip/unicast_peer)。跨网段、云服务器(部分云商禁多播)时,必须改用单播 ,即显式配置 unicast_src_ip 和 unicast_peer。云环境务必用单播。

六、结合 Nginx 实现 Web 高可用

Keepalived 默认只保证"VIP 在",但它并不知道 Nginx 是否活着 。所以我们要用 vrrp_script 做业务健康检查:Nginx 挂了就降低优先级甚至剥夺 VIP,把流量切到备机。

6.1 先部署 Nginx(两台都要)

bash

复制代码
 

|---|-----------------------------------------------------------------------------|
| | yum install -y nginx |
| | # 或编译安装 |
| | # 配置一个测试页用于验证 |
| | echo "<h1>Nginx on node1</h1>" > /usr/share/nginx/html/index.html # node1 |
| | echo "<h1>Nginx on node2</h1>" > /usr/share/nginx/html/index.html # node2 |
| | |
| | systemctl start nginx |
| | systemctl enable nginx |

6.2 编写健康检查脚本

创建脚本 /etc/keepalived/check_nginx.sh,两台都要放:

bash

复制代码
 

|---|--------------------------------------------|
| | #!/bin/bash |
| | # 检查 Nginx 进程是否存活 |
| | if pgrep -x nginx > /dev/null 2>&1; then |
| | exit 0 # 存活,返回0 |
| | else |
| | exit 1 # 挂了,返回非0 |
| | fi |

bash

复制代码
chmod +x /etc/keepalived/check_nginx.sh

6.3 在配置中声明脚本

在 keepalived.conf 的 global_defs 之后、vrrp_instance 之前加:

conf

复制代码
 

|---|--------------------------------------------------|
| | vrrp_script check_nginx { |
| | script "/etc/keepalived/check_nginx.sh" # 脚本路径 |
| | interval 2 # 每2秒执行一次检查 |
| | weight -20 # 检查失败时优先级减20(150-20=130 < 100?) |
| | fall 2 # 连续2次失败才判定失败 |
| | rise 1 # 连续1次成功即恢复 |
| | } |

weight 的坑 :主 priority=150,若 weight -20,挂了变 130;备 priority=100。130 > 100,VIP 不会漂移!所以要保证"主挂了之后 priority 仍低于备"。正确做法:

  • 主 priority=150,weight=-60 → 挂了变 90 < 100,正常漂移。
  • 或用 weight 0 + state 主备切换配合,本文用减法方案,保证主失败后必让位。

修正后的主节点脚本声明:

conf

复制代码
 

|---|-------------------------------------------|
| | vrrp_script check_nginx { |
| | script "/etc/keepalived/check_nginx.sh" |
| | interval 2 |
| | weight -60 # 150-60=90 < 备的100,确保漂移 |
| | fall 2 |
| | rise 1 |
| | } |

备节点也声明同名脚本(weight 可不设或一致),保持逻辑统一。

七、启动与验证

7.1 启动服务(两台)

bash

复制代码
 

|---|-------------------------------|
| | systemctl start keepalived |
| | systemctl enable keepalived |
| | systemctl status keepalived |

7.2 查看 VIP 归属

bash

复制代码
 

|---|---------------------|
| | ip addr show eth0 |
| | # 或 |
| | ip a |

正常情况下 VIP 192.168.1.100 应绑定在主节点 node1 上:

text

复制代码
 

|---|-----------------------------------------------------------------|
| | 3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> ... |
| | inet 192.168.1.11/24 scope global eth0 |
| | inet 192.168.1.100/24 scope global secondary eth0 # ← VIP在主节点 |

7.3 验证客户端访问

bash

复制代码
 

|---|--------------------------------|
| | # 在任意客户端 |
| | curl http://192.168.1.100 |
| | # 返回:<h1>Nginx on node1</h1> |

7.4 查看 Keepalived 运行状态

bash

复制代码
 

|---|--------------------------------------------------|
| | # 实时查看 VRRP 状态 |
| | ps -ef | grep keepalived |
| | # 主节点日志 |
| | tail -f /var/log/messages | grep -i keepalived |
| | # 或 journalctl |
| | journalctl -u keepalived -f |

主节点日志应出现:

text

复制代码
 

|---|--------------------------------------------------------------------------|
| | Keepalived_vrrp[xxx]: Sending gratuitous ARP on eth0 for 192.168.1.100 |
| | Keepalived_vrrp[xxx]: Entering MASTER STATE |

八、故障转移验证(重点实战)

8.1 场景一:停掉主节点 Nginx(业务级故障)

bash

复制代码
 

|---|------------------------|
| | # 在 node1 上 |
| | systemctl stop nginx |

等待健康检查判定失败(fall 2 × interval 2 ≈ 4 秒 + 1 心跳):

bash

复制代码
 

|---|----------------------------------------------------------------------------------|
| | # node1 日志 |
| | Keepalived_vrrp[xxx]: (VI_1) Entering BACKUP STATE # 主降级为备 |
| | Keepalived_vrrp[xxx]: (VI_1) removing VIP from eth0 # 释放VIP |
| | |
| | # node2 日志 |
| | Keepalived_vrrp[xxx]: (VI_1) Entering MASTER STATE # 备升级为主 |
| | Keepalived_vrrp[xxx]: Sending gratuitous ARP on eth0 for 192.168.1.100 # 抢过VIP |

验证:

bash

复制代码
 

|---|-----------------------------------------------------------------|
| | ip addr show eth0 # VIP 已漂移到 node2 |
| | curl http://192.168.1.100 # 返回 <h1>Nginx on node2</h1>,业务无缝切换 |

8.2 场景二:直接宕机/断网(节点级故障)

bash

复制代码
 

|---|--------------------------------------------------------|
| | # 在 node1 上直接关闭网络或关机 |
| | systemctl stop network # 或 ifdown eth0 / 直接 poweroff |

备节点 node2 在心跳超时(默认 advert_int × 3 ≈ 3 秒)后抢占 VIP,业务自动切到 node2。

8.3 恢复主节点

bash

复制代码
 

|---|----------------------------------------------------|
| | # 在 node1 上 |
| | systemctl start nginx # 恢复业务 |
| | systemctl start keepalived # 若keepalived也停了,一并启动 |

重启后按优先级,node1(priority 150)会重新抢占回 VIP,流量切回 node1。

若希望"主恢复后不抢回" :两台配置都加上 nopreempt,且 state 都写 BACKUP,此时纯靠 priority 决定,主恢复后 VIP 不自动回切,避免频繁抖动。

九、常见问题与排障

现象 原因与解决
VIP 起不来 网卡名不对(ip a 确认 eth0 还是 ens33);virtual_router_id 冲突
两台都是 MASTER 心跳不通:多播被禁 → 改单播;防火墙放行 VRRP(vrrp 协议 112)
Nginx 挂了 VIP 不漂移 weight 设置导致主失败后优先级仍高于备(见 6.3 的坑)
主恢复后频繁抖动 两台都加 nopreempt 改为非抢占
备机日志无输出 防火墙拦截组播/单播,放行:iptables -A INPUT -p vrrp -j ACCEPT
认证失败 auth_pass 长度超 8 位或两台不一致
云服务器上漂移失败 云商禁组播,务必用 unicast_* 单播;安全组放行对应端口

防火墙放行 VRRP

bash

复制代码
 

|---|------------------------------------------------|
| | # firewalld |
| | firewall-cmd --permanent --add-protocol=vrrp |
| | firewall-cmd --reload |
| | |
| | # iptables |
| | iptables -A INPUT -p vrrp -j ACCEPT |
| | iptables -A INPUT -d 224.0.0.0/8 -j ACCEPT |

手动切换排障技巧

bash

复制代码
 

|---|------------------------------------------------------|
| | # 手工停用主节点,观察备节点是否立即接管 |
| | ip addr del 192.168.1.100/24 dev eth0 # 仅测试,生产不建议 |
| | # 或直接查看状态变化 |
| | watch -n1 'ip addr show eth0 | grep 192.168.1.100' |

十、总结

Keepalived 高可用部署的核心要点可以归纳为"三个一":

  1. 一个 VIP:对外只暴露一个虚拟 IP,客户端无感知故障。
  2. 一组心跳:VRRP 组播/单播心跳 + 优先级,决定谁是 MASTER。
  3. 一套检查 :vrrp_script 健康检查业务进程,确保"VIP 跟业务走"。

关键经验:

  • 云服务器记得用单播替代组播。
  • 健康检查的 weight 必须保证"主挂后优先级低于备",否则漂移失败。
  • 生产环境建议**非抢占(nopreempt)**模式,减少主备抖动。
  • 先做故障转移演练(停服务、断网、重启)再上生产,别等出事了才发现配置有误。

本文基于 Keepalived 2.4.3 + CentOS 7/8 + Nginx 1.24 实战验证。

相关推荐
荣合技术服务1 小时前
VMware ESXi 虚拟化平台服务器虚拟机数据恢复服务
linux·运维·服务器
爱吃香菜的初学者1 小时前
十三.Linux——信号量
linux·运维·服务器·开发语言
吴声子夜歌1 小时前
Nginx应用与运维——Nginx在Kubernetes中的应用(三)
运维·nginx·kubernetes
小小龙学IT2 小时前
ROS2 安装完全指南(Ubuntu 版):从零开始到跑通第一个节点本文
linux·运维·ubuntu
Ruiery2 小时前
Linux 6.6内核 CPU 深度解析(十二):SMT 进阶 — core scheduling 与共享算力的负载平衡
linux·运维·服务器
2401_872418782 小时前
Windows服务器:错误 403 - 禁止访问:本地 FTP 上传文件到网站服务器后提示无访问权限
运维·服务器·windows
吴声子夜歌2 小时前
Nginx应用与运维——Nginx在Kubernetes中的应用(二)
运维·nginx·kubernetes
Ruiery11 小时前
Linux 6.6内核 CPU 深度解析(七):调度器启动 — 从单核到多核,调度器分阶段点亮
linux·运维·服务器
50万马克的面包11 小时前
CSDN-栈队列数组-知识点整理
linux·运维·服务器