原创

高可用架构(一):Keepalived

温馨提示:
本文最后更新于 2026年04月05日,已超过 39 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

 

你是否遇到过单点故障导致服务中断?在分布式系统和微服务架构盛行的今天,服务的高可用性已成为系统设计的核心指标。今天我们来聊聊如何用Keepalived实现秒级故障切换,让你的服务永不宕机。

一、引言:为什么需要Keepalived?

在当今的互联网架构中,没有任何硬件或软件是永远不宕机的。服务器可能因为硬件故障、软件bug、网络问题或人为操作失误而停止服务。对于关键业务系统,即使是几分钟的停机也可能造成巨大的经济损失和用户体验下降。

Keepalived正是这样一个轻量级、功能强大的开源工具,它常被用于解决单点故障问题,是构建高可用集群的"瑞士军刀"。通过Keepalived,我们可以确保当主节点发生故障时,备用节点能够在秒级甚至毫秒级内接管服务,实现真正的业务连续性。

二、Keepalived核心概览

2.1 什么是Keepalived?

Keepalived是一个基于**VRRP(Virtual Router Redundancy Protocol,虚拟路由器冗余协议)**实现的负载均衡和高可用解决方案。它最初是为LVS(Linux Virtual Server)负载均衡器设计的心跳检测工具,但随着时间的推移,它的功能已经远远超出了LVS的范畴。

如今,Keepalived广泛用于各类服务的主备高可用部署,包括:

  • Web服务:Nginx、Apache
  • 数据库:MySQL、Redis
  • 应用服务:各种微服务
  • 网络设备:路由器、防火墙

2.2 三大核心功能

  1. 健康检查(Health Check)
    • 实时监控后端服务或本地进程的状态
    • 支持自定义检查脚本
    • 可配置检查间隔和失败阈值
  1. 故障转移(Failover)
    • 当检测到主节点故障时,自动将虚拟IP(VIP)漂移到备用节点
    • 切换过程对客户端透明
    • 支持抢占和非抢占模式
  1. 负载均衡(Load Balancing)
    • 内置简单的四层负载均衡能力(配合LVS使用)
    • 虽然不如Nginx或HAProxy功能丰富,但对于基础负载均衡需求足够

三、VRRP协议深度解析

3.1 VRRP机制详解

**VRRP(Virtual Router Redundancy Protocol)**是一种容错协议,旨在提高网络默认网关的可用性。它的核心思想很简单:将多台物理设备组合成一个虚拟设备

核心概念

  • 虚拟路由器:由多台物理设备组成的逻辑设备
  • 虚拟IP地址(VIP):虚拟路由器对外提供的IP地址
  • 虚拟MAC地址:虚拟路由器对应的MAC地址
  • Master(主节点):当前负责处理流量的设备
  • Backup(备节点):处于待命状态的设备

工作机制

  1. 选举机制:组内优先级最高的设备成为Master
  2. 心跳机制:Master定期发送VRRP通告报文
  3. 监听机制:Backup监听Master的通告
  4. 故障切换:当Backup超时未收到通告时,自动选举新的Master

3.2 为什么选择VRRP而不是TCP/UDP?

这是一个关键的技术选型问题。Keepalived选择VRRP而不是基于TCP/UDP的应用层协议,主要基于以下原因:

1. 工作层级不同(最关键原因)

  • Keepalived的核心任务:管理虚拟IP的漂移,确保网关或服务入口IP始终可达。这属于网络层的功能
  • TCP/UDP的局限性:属于传输层(Layer 4),它们依赖于IP地址已经存在且路由可达。如果用TCP/UDP来做主备切换,当主节点宕机时,IP地址本身可能还绑定在主节点上,客户端依然会尝试连接那个可能已失效的IP。
  • VRRP的优势:是一种网络层协议(IP Protocol 112),直接封装在IP报文中。它能直接操作网卡的IP别名和ARP表,实现IP的物理漂移,这是传输层协议无法做到的。

2. 标准化与兼容性

  • VRRP是IETF标准协议(RFC 5798),网络设备(交换机、路由器)原生支持识别和处理VRRP报文。
  • 如果使用自定义的TCP/UDP协议,中间的网络设备可能无法理解其意图,且在处理IP地址接管时需要额外的非标准逻辑。

3. 效率与开销

  • VRRP使用组播发送心跳,无需建立连接,开销极小,检测速度快。
  • TCP需要三次握手建立连接,维护状态复杂;UDP虽然无连接,但缺乏标准的组播选举机制。

总结:Keepalived使用VRRP是因为只有网络层/链路层协议才能直接控制IP地址的归属权。TCP/UDP是在IP地址确定之后才进行数据传输的,无法解决"IP地址由哪台机器持有"这个根本问题。

3.3 故障切换全流程

让我们通过一个具体的场景来理解VRRP的故障切换过程:

正常状态

  • Master:每1秒向组播地址224.0.0.18发送VRRP通告报文
  • Backup:监听组播地址,收到通告后保持备份状态

故障检测

  1. Master宕机或网络中断,停止发送通告
  2. Backup启动计时器(默认3-4秒)
  3. 超时未收到通告,判定Master失效

选举与接管

  1. Backup将自己提升为Master状态
  2. 新Master在网卡上绑定虚拟IP(VIP)
  3. 发送免费ARP广播,更新交换机的MAC地址表和主机的ARP缓存
  4. 流量切换到新的主节点

故障恢复

  • 如果原Master恢复且配置了preempt(抢占模式,默认开启),它会重新抢回Master角色
  • 若配置为nopreempt,则保持当前状态直到再次故障

3.4 通信特征

重要提醒:VRRP不使用端口号!

  • 协议类型:不是基于TCP或UDP,因此不存在端口号的概念
  • 协议号:直接封装在IP包中,使用IP协议号112
  • 通信方式:使用组播(Multicast)
    • IPv4组播地址:224.0.0.18
    • IPv6组播地址:FF02::12
  • TTL:通常为255,确保只在本地链路传播

3.5 网络配置实战

由于VRRP不使用端口,防火墙规则不能基于端口配置,而必须基于协议号和组播地址。

方法一:使用firewalld

# 添加VRRP协议到公共区域
sudo firewall-cmd --permanent --add-protocol=vrrp
# 重载防火墙以生效
sudo firewall-cmd --reload
# 验证配置
sudo firewall-cmd --list-all

方法二:使用ufw

修改/etc/ufw/before.rules文件:

# 允许VRRP协议
-A ufw-before-input -p vrrp -j ACCEPT
# 或者使用协议号写法
# -A ufw-before-input -p 112 -j ACCEPT

然后重启ufw服务:

# 重载规则
sudo systemctl restart ufw
# 验证规则
sudo ufw status verbose

重要注意事项

  1. 云环境限制
    • 在阿里云、AWS、腾讯云等公有云的VPC环境中,底层网络设备通常不支持组播或协议号112的透传
    • 解决方案:使用单播模式配置Keepalived,修改keepalived.conf指定unicast_peer
  1. 交换机配置
    • 物理交换机环境需要确保连接Keepalived节点的交换机端口允许组播流量通过
    • 有时需要配置igmp snooping相关选项以避免组播报文被泛洪或丢弃

四、VRRP连通性测试与故障排查

4.1 安装tcpdump工具

确保两台服务器都安装了tcpdump:

# CentOS/RedHat
sudo yum install -y tcpdump

# Ubuntu/Debian
sudo apt-get install -y tcpdump

4.2 VRRP报文抓包

在备节点上执行抓包命令(假设网卡名称为eth0):

# -n: 不解析域名
# -i eth0: 监听网卡
# -v: 显示详细信息
# "vrrp": 只过滤VRRP协议的数据包
sudo tcpdump -n -i eth0 -v vrrp

观察现象

情况A:正常通信

15:20:01.123456 IP 192.168.1.10 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
  • 192.168.1.10:主节点的真实IP
  • 224.0.0.18:VRRP专用的组播地址
  • vrid 51:必须和配置文件里的virtual_router_id一致
  • prio 100:主节点的优先级

结论:网络通畅,防火墙未拦截,Keepalived工作正常。

情况B:通信异常

  • 屏幕一片空白,或者很久才跳一下无关的包
  • 结论:心跳包被拦截了,或者主节点没发出来。这会导致脑裂

4.3 连通性异常排查

如果抓不到包,按以下顺序排查:

1. 检查防火墙(最常见原因)

VRRP使用的是协议号112,不是TCP也不是UDP,普通的端口放行规则无效。

临时测试法

# CentOS
sudo systemctl stop firewalld

# Ubuntu
sudo ufw disable

关闭后,再看备节点的tcpdump是否有包。如果有包了,说明是防火墙问题。

2. 检查云安全组/交换机策略

  • 云服务器:大多数云厂商的安全组默认禁止组播
  • 现象:防火墙关了也没包
  • 解决方案:修改keepalived.conf,将默认的组播改为单播

配置示例:

vrrp_instance VI_1 {
    # ... 其他配置
    unicast_src_ip 192.168.1.10  # 本机内网IP
    unicast_peer {
        192.168.1.11  # 对端内网IP
    }
}

3. 检查网卡配置

  • 确认keepalived.conf中的interface eth0填写的网卡名称与实际通信的网卡名称一致
  • 确认两台机器是否在同一个子网(掩码一致)

五、业务级高可用:track_script详解

5.1 track_script的作用

track_script是Keepalived实现"业务级高可用"的核心配置块。它的核心作用是:将外部脚本的执行结果与VRRP实例的优先级动态绑定

如果没有track_script,Keepalived只是一个"网卡存活检测器";有了它,Keepalived就变成了一个"业务健康检测器"。

5.2 配置示例

# 1. 定义脚本逻辑
vrrp_script check_nginx {
    script "/etc/keepalived/check_nginx.sh"  # 检查脚本路径
    interval 2    # 每2秒检查一次
    fall 2        # 连续2次失败才认定失败(防抖动)
    rise 1        # 连续1次成功即认定恢复
    weight -50    # 【关键】失败时优先级降低50分
}

# 2. 在实例中引用
vrrp_instance VI_1 {
    state MASTER
    priority 100  # 初始优先级
    
    track_script {
        check_nginx  # 【关键】这里名字必须和上面定义的vrrp_script名字一致
    }
    
    # ... 其他配置
}

5.3 工作流程对比

不配置track_script(静态优先级)

  1. 检测阶段:Keepalived仅检查网卡链路层状态
  2. 决策阶段:节点A继续以优先级100发送心跳
  3. 结果:VIP死死绑定在节点A,即使Nginx挂了,流量依然进来直接报错

配置track_script(动态优先级)

  1. 检测阶段:Keepalived定期调用脚本,发现Nginx挂了
  2. 判定阶段:达到fall阈值后,判定业务故障
  3. 降权阶段:节点A的优先级从100自动降至50
  4. 切换阶段:节点B发现自身优先级90 > 50,立即抢占成为Master
  5. 结果:流量被引导至节点B,服务恢复

六、常见故障与生产最佳实践

6.1 脑裂故障(Split-Brain)

脑裂是指在Keepalived集群中,主节点和备节点同时认为自己是Master,导致两者都持有虚拟IP,进而引发IP冲突、数据写入混乱或服务不可用的严重故障。

1. 心跳网络中断(最常见)

  • 表现:两台机器上都绑定了VIP,客户端请求被随机分配
  • 诱因
    • 防火墙拦截VRRP协议包
    • 交换机/路由器故障
    • 网线/网卡松动
    • 云环境禁止组播

2. 主节点负载过高

  • 机制:主节点CPU 100%、内存耗尽或IO阻塞,无法及时发送心跳
  • 结果:备节点在3秒内收不到心跳,判定主节点死亡并抢占VIP

3. 配置错误

  • VRID不一致:主备配置的virtual_router_id不同,属于不同的组
  • 优先级相同:两台机器都配置了相同的最高优先级
  • 认证密码不一致auth_pass不一致,接收方丢弃心跳包

4. 网络延迟过大

  • 场景:跨机房或广域网部署
  • 问题:网络延迟超过VRRP的超时阈值
  • 注意:Keepalived默认设计用于局域网,不建议直接用于高延迟场景

5. 健康检查脚本误判

  • 场景:业务进程活着,但检测脚本返回"失败"
  • 结果:主节点优先级被降低,备节点抢占VIP

6.2 生产环境最佳实践

1. 使用单播模式

在现代云环境和复杂网络中,强烈建议放弃组播,改用单播(Unicast)。单播是点对点通信,不依赖组播地址,穿透性更强,配置更可控。

配置示例:

vrrp_instance VI_1 {
    # ... 其他配置
    
    # 填写【本机】的真实物理IP地址
    unicast_src_ip 192.168.1.52
    
    # 填写【对端】的真实物理IP地址
    unicast_peer {
        192.168.1.62
    }
}

2. 合理配置优先级

  • 主节点优先级:100-150
  • 备节点优先级:50-99
  • 避免优先级相同
  • 根据业务重要性设置不同的权重

3. 配置抢占模式

  • preempt:默认开启,主节点恢复后抢回VIP
  • nopreempt:非抢占模式,适合对切换敏感的场景
  • 根据业务需求选择合适的模式

4. 完善的监控告警

  • 监控Keepalived进程状态
  • 监控VRRP心跳包
  • 监控业务健康检查状态
  • 设置合理的告警阈值

5. 定期演练

  • 定期模拟主节点故障
  • 验证切换时间和数据一致性
  • 更新应急预案

七、总结

Keepalived是一个强大而灵活的高可用解决方案,通过VRRP协议实现了IP级别的故障切换。它的核心价值在于:

  1. 简单易用:配置相对简单,学习成本低
  2. 高效可靠:秒级切换,对业务影响小
  3. 灵活扩展:支持自定义健康检查脚本
  4. 广泛适用:适用于各种服务的高可用部署

然而,Keepalived也不是银弹,它有自己的局限性:

  • 对网络环境要求较高
  • 在云环境中需要特殊配置
  • 不适合跨地域的高可用场景

在实际使用中,我们需要根据具体的业务需求和技术环境,合理设计高可用架构。Keepalived通常与其他技术(如Nginx、HAProxy、数据库复制等)结合使用,构建完整的高可用解决方案。

正文到此结束