一、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 工作流程
- 多台服务器(主+备)通过 VRRP 组播报文互相发送心跳(默认每 1 秒一次)。
- MASTER 正常时,VIP 绑在 MASTER 网卡上,BACKUP 处于待命状态。
- 若 BACKUP 连续多个心跳周期没收到 MASTER 的报文(master_down),就判定 MASTER 故障。
- BACKUP 立即把 VIP 绑定到自己网卡,并发送 ARP 广播告知网关和客户端"VIP 的 MAC 地址变了",流量随之切到备机。
- 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 高可用部署的核心要点可以归纳为"三个一":
- 一个 VIP:对外只暴露一个虚拟 IP,客户端无感知故障。
- 一组心跳:VRRP 组播/单播心跳 + 优先级,决定谁是 MASTER。
- 一套检查 :
vrrp_script健康检查业务进程,确保"VIP 跟业务走"。
关键经验:
- 云服务器记得用单播替代组播。
- 健康检查的 weight 必须保证"主挂后优先级低于备",否则漂移失败。
- 生产环境建议**非抢占(nopreempt)**模式,减少主备抖动。
- 先做故障转移演练(停服务、断网、重启)再上生产,别等出事了才发现配置有误。
本文基于 Keepalived 2.4.3 + CentOS 7/8 + Nginx 1.24 实战验证。