keepalived 不支持跨机房双机热备,因其依赖局域网内的 vrrp 组播通信,而跨机房存在路由隔离、组播不可达、无隧道封装及延迟敏感等问题,强行使用易致 vip 漂移异常或脑裂。

Keepalived 本身不支持跨机房双机热备——它依赖 VRRP 组播(224.0.0.18)在二层广播域内通信,而跨机房通常意味着路由隔离、三层转发、防火墙策略限制,VRRP 组播报文无法穿透。强行配置会导致 VIP 不漂移、状态震荡或主备同时抢 VIP,反而破坏可用性。
为什么跨机房不能直接用 Keepalived
VRRP 协议设计就是为局域网(LAN)服务的: - 必须同子网:VIP 和两节点物理 IP 必须在同一网段,且能通过 arp 直通; - 依赖组播:使用 UDP 端口 112 + 组播地址 224.0.0.18,跨路由器默认被丢弃; - 无隧道封装:Keepalived 不自带 GRE/IPsec/UDP 封装能力,无法构建虚拟二层通道; - 网络延迟敏感:advert_int 默认 1 秒,跨机房 RTT 波动大,易触发误切换。
生产级跨机房高可用的替代架构
真正可行的方案不是“改造 Keepalived”,而是用更合适的组件组合:
- DNS 轮询 + 健康探测 + 权重调度:用 Consul、Traefik 或云厂商 DNS(如阿里云云解析 PrivateZone)做服务发现,后端每机房部署健康探活服务(HTTP /health),DNS 根据探测结果动态调整 TTL 和记录权重,实现秒级故障屏蔽;
- BGP Anycast + 本地 Keepalived:每个机房部署独立 Keepalived 集群(VIP 各自收敛),再通过 BGP 将同一 IP(如 203.0.113.100/32)宣告到骨干网,由 ISP 路由器就近分发流量;需机房有 BGP 线路和 ASN;
- 应用层主动切换 + 共享存储:数据库用 MySQL MGR / PostgreSQL Patroni 实现跨机房自动选主,应用连接串指向逻辑服务名(如 myapp-db.service),配合客户端重试+熔断,避免强依赖 VIP;
- 云原生方案(推荐):Kubernetes Ingress + MetalLB(BGP 模式)或云负载均衡(如 AWS ALB + Target Group 健康检查),天然支持多可用区,无需维护 Keepalived 配置。
若必须保留 Keepalived,可做的有限适配
仅适用于网络条件极优、且可控的“准跨机房”场景(如同城双活,核心交换机开启 PIM-SM 或允许 VRRP 组播透传):
- 确认两端物理链路支持 VRRP 组播:需运营商或网络团队开通 224.0.0.18/32 的三层组播转发,并禁用 IGMP snooping 过滤;
- 改用单播 VRRP(Keepalived 2.0.20+ 支持):在
vrrp_instance中添加unicast_src_ip和unicast_peer,绕过组播依赖,但要求两端路由可达且策略放行 UDP 112; - 大幅调高
advert_int(如设为 5)和fall(如 fall 5),降低因网络抖动导致的误切; - 所有健康检查脚本必须带超时:
curl --connect-timeout 3 --max-time 5 -f http://127.0.0.1/health,避免检测阻塞拖慢切换; - 启用
non_preemptive模式,防止主节点恢复后立即抢回 VIP,造成客户端 TCP 连接中断。
关键验证动作(部署后必做)
不靠日志猜,要实测行为:
- 在机房 A 执行
tcpdump -i any host 224.0.0.18 and port 112,确认能否收到对端 VRRP 报文; - 手动停掉机房 A 的 keepalived,观察机房 B 的
ip addr show是否在 5 秒内出现 VIP; - 从第三方网络(如办公网)持续
ping -t VIP和curl -I http://VIP,记录中断时间是否 ≤ 8 秒; - 故意制造单边网络分区(如 iptables -A INPUT -s 对端IP -j DROP),验证是否会脑裂(两边都 claim VIP)。










