高可用架构(一):Keepalived
你是否遇到过单点故障导致服务中断?在分布式系统和微服务架构盛行的今天,服务的高可用性已成为系统设计的核心指标。今天我们来聊聊如何用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 三大核心功能
- 健康检查(Health Check)
- 实时监控后端服务或本地进程的状态
- 支持自定义检查脚本
- 可配置检查间隔和失败阈值
- 故障转移(Failover)
- 当检测到主节点故障时,自动将虚拟IP(VIP)漂移到备用节点
- 切换过程对客户端透明
- 支持抢占和非抢占模式
- 负载均衡(Load Balancing)
- 内置简单的四层负载均衡能力(配合LVS使用)
- 虽然不如Nginx或HAProxy功能丰富,但对于基础负载均衡需求足够
三、VRRP协议深度解析
3.1 VRRP机制详解
**VRRP(Virtual Router Redundancy Protocol)**是一种容错协议,旨在提高网络默认网关的可用性。它的核心思想很简单:将多台物理设备组合成一个虚拟设备。
核心概念
- 虚拟路由器:由多台物理设备组成的逻辑设备
- 虚拟IP地址(VIP):虚拟路由器对外提供的IP地址
- 虚拟MAC地址:虚拟路由器对应的MAC地址
- Master(主节点):当前负责处理流量的设备
- Backup(备节点):处于待命状态的设备
工作机制
- 选举机制:组内优先级最高的设备成为Master
- 心跳机制:Master定期发送VRRP通告报文
- 监听机制:Backup监听Master的通告
- 故障切换:当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:监听组播地址,收到通告后保持备份状态
故障检测
- Master宕机或网络中断,停止发送通告
- Backup启动计时器(默认3-4秒)
- 超时未收到通告,判定Master失效
选举与接管
- Backup将自己提升为Master状态
- 新Master在网卡上绑定虚拟IP(VIP)
- 发送免费ARP广播,更新交换机的MAC地址表和主机的ARP缓存
- 流量切换到新的主节点
故障恢复
- 如果原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
重要注意事项
- 云环境限制
- 在阿里云、AWS、腾讯云等公有云的VPC环境中,底层网络设备通常不支持组播或协议号112的透传
- 解决方案:使用单播模式配置Keepalived,修改
keepalived.conf指定unicast_peer
- 交换机配置
- 物理交换机环境需要确保连接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:主节点的真实IP224.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(静态优先级)
- 检测阶段:Keepalived仅检查网卡链路层状态
- 决策阶段:节点A继续以优先级100发送心跳
- 结果:VIP死死绑定在节点A,即使Nginx挂了,流量依然进来直接报错
配置track_script(动态优先级)
- 检测阶段:Keepalived定期调用脚本,发现Nginx挂了
- 判定阶段:达到fall阈值后,判定业务故障
- 降权阶段:节点A的优先级从100自动降至50
- 切换阶段:节点B发现自身优先级90 > 50,立即抢占成为Master
- 结果:流量被引导至节点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级别的故障切换。它的核心价值在于:
- 简单易用:配置相对简单,学习成本低
- 高效可靠:秒级切换,对业务影响小
- 灵活扩展:支持自定义健康检查脚本
- 广泛适用:适用于各种服务的高可用部署
然而,Keepalived也不是银弹,它有自己的局限性:
- 对网络环境要求较高
- 在云环境中需要特殊配置
- 不适合跨地域的高可用场景
在实际使用中,我们需要根据具体的业务需求和技术环境,合理设计高可用架构。Keepalived通常与其他技术(如Nginx、HAProxy、数据库复制等)结合使用,构建完整的高可用解决方案。
- 本文标签: Java 高可用
- 本文链接: https://xiaolanzi.cyou/article/86
- 版权声明: 本文由卓原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权
