Appearance
VRRP 协议与 Keepalived:虚拟 IP 是如何“漂移”起来的

上一章我们提到,虚拟 IP(VIP)可以在主备机器之间“漂移”,实现入口高可用。
但 VIP 到底是怎么漂起来的?背后的原理是什么?
答案就是 VRRP 协议——虚拟路由冗余协议(Virtual Router Redundancy Protocol)。
本章将从最底层的协议机制讲起,配合 Keepalived 的配置示例,彻底搞懂 VIP 漂移的来龙去脉。
一、VRRP 协议是什么?
VRRP 是一个标准的网络协议,最早在 RFC 3768 中定义。它的目标很简单:让多台路由器共享同一个虚拟 IP,实现网关的高可用。
传统上,VRRP 用于路由器的主备切换。但在我们的场景中,它同样适用于普通的 Linux 服务器——Keepalived 就是 VRRP 协议的一个完整实现。
核心概念:
| 概念 | 说明 |
|---|---|
| 虚拟路由器 | 多台物理机器组成的逻辑组,对外表现为一台“虚拟”设备 |
| 虚拟 IP(VIP) | 虚拟路由器的对外 IP,客户端实际访问的地址(本文为 192.168.0.200) |
| 虚拟 MAC | VRRP 生成的虚拟 MAC 地址(00-00-5E-00-01-{VRID}) |
| Master | 当前实际处理请求的节点,拥有 VIP |
| Backup | 备用节点,监听 Master 心跳,准备接管 |
| VRID | 虚拟路由器 ID,同一网络下必须唯一 |
二、VRRP 的核心机制
2.1 优先级决定谁是 Master
VRRP 使用一个简单的规则来决定谁是 Master:优先级最高的节点成为 Master。
yaml
# 主节点配置(192.168.0.201)
priority: 100
# 备节点配置(192.168.0.202)
priority: 90
# 备节点配置(192.168.0.203)
priority: 80优先级范围是 1-255。数值越高,越有可能成为 Master。
当多个节点优先级相同时,IP 地址最大的节点获胜(这是一种防冲突的兜底策略)。
2.2 心跳检测:Master 定期“报平安”
Master 会每隔一段时间(默认 1 秒)向组播地址 224.0.0.18 发送 VRRP 通告报文,告诉所有 Backup 节点:“我还活着”。
通告报文中包含:
- Master 的优先级
- 虚拟 IP 地址(
192.168.0.200) - VRID
- 通告间隔
2.3 故障检测:Backup 等待超时
Backup 节点会持续监听 Master 的通告。如果连续 3 秒(默认 3 个通告周期)没有收到 Master 的心跳,就判定 Master 已宕机。
2.4 抢占模式:优先级高的说了算
VRRP 默认是抢占模式。这意味着:
- 如果当前 Master 宕机,Backup 中优先级最高的节点接管成为新 Master
- 如果原来的 Master 恢复(且它的优先级更高),它会重新抢占 VIP,恢复为 Master
这种模式的好处是:永远让配置优先级最高的节点提供服务。
如果需要避免频繁切换(比如网络抖动导致短暂失联),可以开启 nopreempt 非抢占模式,我们会在后续的“生产最佳实践”章节详细讨论。
2.5 MAC 地址迁移:网络拓扑如何感知切换?
VRRP 最精妙的设计是 MAC 地址漂移。
每个 VRRP 虚拟路由器会生成一个虚拟 MAC 地址:
00-00-5E-00-01-{VRID}00-00-5E:IANA 分配给 VRRP 的 OUI00-01:固定值{VRID}:虚拟路由器 ID(1-255)
当 Master 切换时,新 Master 会发送一个免费 ARP(Gratuitous ARP) 广播,告诉整个网络:“虚拟 MAC 地址现在在我这里,更新你们的 ARP 缓存!”
这个过程对客户端完全透明。客户端自始至终访问同一个 VIP 192.168.0.200 和对应的虚拟 MAC,不需要任何配置变更。
三、Keepalived:VRRP 的完整实现
Keepalived 是 Linux 上最流行的 VRRP 实现。它不仅实现了 VRRP 协议,还集成了健康检查机制。
3.1 Keepalived 的核心组件
| 组件 | 职责 |
|---|---|
| VRRP 协议栈 | 实现心跳、竞选、抢占逻辑 |
| VIP 管理 | 添加/删除虚拟 IP |
| 健康检查框架 | 定期检查服务状态,影响优先级 |
3.2 一个最小化的 Keepalived 配置
下面是三台机器的主备配置示例(基于家庭网络 192.168.0.0/24 网段):
Master 节点(192.168.0.201):
bash
global_defs {
router_id KEEPALIVED_MASTER
}
vrrp_instance VI_1 {
state MASTER # 初始角色:主
interface eth0 # 监听的网卡
virtual_router_id 51 # VRID,同一集群必须一致
priority 100 # 优先级:主比备高
advert_int 1 # 心跳间隔:1秒
authentication {
auth_type PASS
auth_pass 1234 # 简单认证,防止恶意加入
}
virtual_ipaddress {
192.168.0.200/24 dev eth0 label eth0:vip
}
}Backup 节点 1(192.168.0.202):
bash
global_defs {
router_id KEEPALIVED_BACKUP_1
}
vrrp_instance VI_1 {
state BACKUP # 初始角色:备
interface eth0
virtual_router_id 51
priority 90 # 优先级:比主低
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
virtual_ipaddress {
192.168.0.200/24 dev eth0 label eth0:vip
}
}Backup 节点 2(192.168.0.203):
bash
global_defs {
router_id KEEPALIVED_BACKUP_2
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 80 # 优先级最低
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
virtual_ipaddress {
192.168.0.200/24 dev eth0 label eth0:vip
}
}3.3 Keepalived + Nginx 健康检查
生产环境中,我们希望 Keepalived 不仅检测机器是否存活,还要检测 Nginx 是否正常工作。
bash
# 健康检查脚本(三台机器都需要配置)
cat > /usr/local/bin/check_nginx.sh << 'EOF'
#!/bin/bash
if pgrep -x "nginx" > /dev/null; then
exit 0 # Nginx 存活,正常
else
exit 1 # Nginx 挂了,触发切换
fi
EOF
chmod +x /usr/local/bin/check_nginx.sh在 Keepalived 配置中引用这个脚本:
bash
vrrp_script check_nginx {
script "/usr/local/bin/check_nginx.sh"
interval 2 # 每2秒检查一次
weight -20 # 检查失败时,优先级减20
fall 2 # 连续失败2次才判定失败
rise 2 # 连续成功2次才判定恢复
}
vrrp_instance VI_1 {
# ... 其他配置 ...
track_script {
check_nginx
}
}工作原理:
- 正常情况下,Master(
192.168.0.201)优先级为 100 - 如果 Master 的 Nginx 挂了,优先级降至 80(100 - 20)
- 此时 Backup 1(
192.168.0.202)优先级为 90 > 80,Backup 1 接管成为新 Master - Nginx 恢复后,优先级回到 100,重新抢占
四、VRRP 状态机
VRRP 定义了三种状态,理解了状态机就理解了整个协议:
| 状态 | 拥有 VIP | 发送通告 | 监听心跳 |
|---|---|---|---|
| Initialize | ❌ | ❌ | ❌ |
| Backup | ❌ | ❌ | ✅ |
| Master | ✅ | ✅ | ❌ |
五、常见问题与误区
Q1:VRRP 和 Keepalived 是什么关系?
VRRP 是协议标准(RFC 3768),Keepalived 是 VRRP 的一个具体实现。除了 VRRP,Keepalived 还集成了健康检查、负载均衡(LVS)等功能。
Q2:VIP 必须和物理 IP 在同一网段吗?
是的。 VIP 192.168.0.200 必须与物理 IP(192.168.0.201/202/203)处于同一子网 192.168.0.0/24,否则交换机无法正确转发数据包。
Q3:Master 和 Backup 之间需要独立的网络吗?
不必须,但推荐。 生产环境中建议使用独立的心跳网络,避免业务流量抖动影响心跳检测。
Q4:VRRP 能跨网段吗?
不能。 VRRP 的通告报文是二层组播(224.0.0.18),TTL 为 1,无法跨路由器。VIP 漂移只能在同一广播域内发生。
Q5:如果网络分区(脑裂)发生会怎样?
脑裂是 VRRP 最棘手的问题。当 Master 和 Backup 之间的网络中断时,两边都收不到对方的心跳,都会认为自己是 Master,同时拥有 VIP 192.168.0.200。
解决方案我们会在第 7 章详细展开(独立心跳网络、非抢占模式、外部仲裁等)。
六、实践环境回顾
本系列的实战环境使用以下家庭网络配置:
| 配置项 | 值 | 说明 |
|---|---|---|
| 网段 | 192.168.0.0/24 | 标准家庭局域网 |
| 网关 | 192.168.0.1 | 路由器地址 |
| VIP | 192.168.0.200 | 虚拟 IP,不实际绑定网卡 |
| node1 | 192.168.0.201 | 优先级 100,初始 Master |
| node2 | 192.168.0.202 | 优先级 90,Backup 1 |
| node3 | 192.168.0.203 | 优先级 80,Backup 2 |
💡 如果你的家庭网络网段不同(如
192.168.1.0/24),只需将所有192.168.0.x替换为你自己的网段即可。
七、小结
本章深入讲解了 VRRP 协议的核心机制:
- 优先级决定角色:优先级最高的节点成为 Master(本例中
192.168.0.201优先级 100) - 心跳检测故障:Master 每秒发送通告,Backup 超时 3 秒后接管
- MAC 地址迁移:通过免费 ARP 通知网络拓扑变更
- Keepalived 实现:VRRP + 健康检查的完整方案
理解这些原理后,下一章我们将进入实战环节:用 Golang + Gin 实现一个“会说话”的健康检查服务,为后续的 Nginx 和 Keepalived 部署做好准备。
💡 本文是《分布式高可用入口架构实战系列》第 2 篇
