1. 从一个"主备切换慢半拍"的现场说起
最早接触VRRP,是在一个园区网的改造项目里。核心交换机做了双机热备,按设计文档的说法,主设备一挂,备设备应该在秒级内接管网关,终端用户几乎无感知。结果上线第一天就出问题:主设备断电后,下面几个网段的终端整整断了七八秒才恢复,有些长连接的会话直接超时断开。当时第一反应是"切换慢",但排查下来发现,问题根本不在切换动作本身,而在VRRP报文交互的细节上——通告间隔、抢占延迟、认证方式、链路状态联动,这几个参数任何一个没对齐,都会让"秒级切换"变成"看运气切换"。
这件事让我意识到,很多人对VRRP的理解停留在"配个vrid、配个优先级就完事"的层面,但真正决定这套机制好不好用的,是报文怎么发、怎么收、怎么判断、怎么响应这一整套交互逻辑。VRRP(Virtual Router Redundancy Protocol,虚拟路由器冗余协议)本质上是一个用组播报文维持"谁当主"共识的协议,它的可靠性完全建立在报文交互的稳定性上。报文丢了、延迟了、被过滤了,主备之间的"信任"就会动摇,切换要么不触发,要么误触发。
这篇内容适合谁看?如果你正在做双机热备、网关冗余、或者遇到过"主备切换不干脆""备机抢不走""双主"这类问题,那这篇就是写给你的。我会从VRRP报文的结构讲起,把通告、认证、状态机、抢占、链路联动这些交互环节拆开,再结合我实际踩过的坑,给出可复现的配置思路和排查方法。不堆理论,重点讲"报文交互"这条主线上的每一个关键动作。
2. VRRP报文长什么样:字段决定了交互行为
2.1 报文封装与组播地址的选择逻辑
VRRP报文是直接封装在IP层之上的,协议号是112,不是跑在TCP或UDP之上。这一点很关键,因为它意味着VRRP没有端口号的概念,抓包时不能按端口过滤,只能按协议号或者组播地址过滤。VRRPv2使用组播地址224.0.0.18,VRRPv3除了这个地址外还支持224.0.0.18的IPv6对应版本FF02::12。为什么用组播而不是单播?因为主设备并不知道当前有哪些备设备在监听,用组播可以一次性把通告发给所有潜在备机,备机只要加入这个组播组就能收到,不需要主设备维护备机列表。这个设计让VRRP的扩展性很好,加一台备机不需要改主设备任何配置。
TTL值默认是255,而且接收端会检查TTL是否为255。这个检查的目的是防止VRRP报文被路由转发到其他网段——VRRP是链路本地协议,只应该在同一个二层广播域内交互。如果你在抓包时发现VRRP报文TTL不是255,或者接收端丢弃了TTL不对的报文,那基本可以判断是中间有设备做了代理或者报文被跨网段转发了,这种情况下的主备关系是不可靠的。
2.2 关键字段逐个拆解
VRRP报文头部有几个字段直接决定了交互行为,我按重要性排一下:
| 字段 | 作用 | 交互中的影响 |
|---|---|---|
| VRID | 虚拟路由器标识,1-255 | 同一网段内VRID必须唯一,冲突会导致双主 |
| Priority | 优先级,0-255 | 决定谁当主,0有特殊含义(主动放弃) |
| Count IP Addrs | 虚拟IP数量 | 主备必须一致,否则备机可能不接管 |
| Auth Type | 认证类型 | 主备不一致会导致报文被丢弃 |
| Adver Int | 通告间隔,秒 | 主备不一致会导致备机误判主设备下线 |
| Checksum | 校验和 | 校验失败报文被丢弃,影响主备判断 |
Priority这个字段值得多说两句。默认值是100,数值越大越优先。0是保留值,当主设备主动放弃主角色时会发优先级为0的通告,备机收到后立即进入主状态,不需要等Master_Down_Timer超时。255是保留给IP地址拥有者的——如果虚拟IP恰好是某台设备的真实接口IP,那这台设备的优先级自动是255,且不能被配置成其他值。这个设计是为了保证"IP地址拥有者"永远是主,避免地址冲突。
Adver Int默认是1秒。这个值决定了主设备多久发一次通告,也决定了备机多久没收到通告就认为主设备挂了。备机的判断时间是3倍通告间隔加上一个偏移量(Skew_Time),所以默认情况下大约3秒多才会触发切换。如果你觉得切换太慢,可以调小通告间隔,但代价是报文频率上升,对设备和链路都是负担。我一般建议在1秒和0.5秒之间权衡,再小就要考虑链路抖动带来的误切换风险。
2.3 认证字段的实际价值与局限
VRRPv2支持三种认证:无认证、简单文本认证、MD5认证。VRRPv3把认证字段去掉了,因为协议本身设计上认为认证应该由IPsec等上层机制解决。但在实际项目里,简单文本认证和MD5认证还是经常被用到,主要目的是防止误配置导致的VRID冲突——比如两个不同的组配了相同的VRID,认证能挡住这种低级错误。
不过要清楚,VRRP认证不提供真正的安全性。简单文本认证是明文传输,MD5认证虽然做了哈希,但密钥是共享的,而且VRRP报文本身没有防重放机制。所以如果你的环境里有恶意设备,VRRP认证挡不住有意的攻击。它的定位是"防误配",不是"防攻击"。这一点在设计和排查时要想清楚,别把认证当成安全手段。
3. 状态机与定时器:主备切换的"心跳"逻辑
3.1 三种状态与它们之间的迁移条件
VRRP的状态机有三个状态:Initialize、Master、Backup。设备启动后先进入Initialize,然后根据优先级和是否收到通告决定进入Master还是Backup。
迁移逻辑大致是这样的:如果设备优先级是255(IP拥有者),或者优先级高于当前主设备,且没有收到更高优先级的通告,就进入Master;否则进入Backup。在Backup状态下,如果Master_Down_Timer超时(也就是连续一段时间没收到主设备通告),就切换到Master。在Master状态下,如果收到优先级更高的通告,就降为Backup;如果收到优先级为0的通告,也降为Backup。
这里有个容易忽略的点:Backup状态下的设备并不是完全被动的。它会监听通告,但不会主动发通告。只有当它认为主设备下线了,才会开始发通告并进入Master。这个"沉默监听"的设计是为了减少报文数量,但也意味着如果备机自己出问题(比如接口down了),主设备是不知道的,主设备会继续发通告,备机收不到而已。所以VRRP本身不提供备机健康检查,备机的可用性要靠其他机制(比如接口监控、BFD联动)来保证。
3.2 三个定时器的计算关系
VRRP的定时器有三个:Adver_Timer、Master_Down_Timer、Skew_Time。它们的关系决定了切换速度。
Adver_Timer是主设备发通告的间隔,默认1秒。Master_Down_Timer是备机判断主设备下线的等待时间,计算公式是:Master_Down_Timer = 3 × Adver_Int + Skew_Time。Skew_Time = (256 - Priority) / 256 秒。假设优先级是100,Skew_Time = (256-100)/256 ≈ 0.61秒,Master_Down_Timer ≈ 3.61秒。如果优先级是200,Skew_Time ≈ 0.22秒,Master_Down_Timer ≈ 3.22秒。
这个公式解释了一个现象:优先级越高的备机,等待时间越短,越容易先抢到主。这是有意设计的,让高优先级的设备在切换时更有优势。但这也意味着如果优先级配置不合理,可能出现低优先级设备先抢到主、然后又被高优先级设备抢回去的"抖动"。
我在实际项目里遇到过一种情况:两台备机优先级分别是110和105,主设备挂掉后,110的先抢到主,但105的因为Skew_Time更长,在110发通告之前还没超时,结果105也进入了Master,短暂出现双主。后来把优先级差距拉大,并且开启了抢占延迟,才解决这个问题。所以优先级不是随便配的,要结合Skew_Time和抢占机制一起考虑。
3.3 抢占模式:为什么默认开启反而容易出问题
VRRP默认是开启抢占的。意思是如果备机优先级比当前主设备高,它会等Master_Down_Timer超时后抢回主角色。这个机制在正常情况下没问题,但在某些场景下会带来麻烦。
比如主设备刚重启完,接口起来了,但路由还没收敛、业务还没就绪,这时候备机如果立刻抢占,流量会切到一台还没准备好的设备上,导致业务中断。再比如链路抖动,主设备短暂失联又恢复,备机已经抢走了主,主设备恢复后又要抢回来,来回切换对业务是灾难。
解决办法是配置抢占延迟(Preempt Delay)。让备机在决定抢占之前多等一段时间,给主设备恢复的机会。延迟时间设多少?我的经验是至少覆盖主设备重启到业务就绪的时间。如果是路由器,可能30秒到60秒;如果是防火墙,可能要120秒以上,因为防火墙的会话表重建更慢。这个值没有标准答案,要靠实际测试。
提示:抢占延迟只在设备从Backup切换到Master时生效,不影响故障切换的速度。故障切换还是按Master_Down_Timer来,抢占延迟是给"主动抢回"加的一道缓冲。
4. 报文交互的完整链路:从发通告到切换
4.1 主设备发通告的节奏与内容
主设备进入Master状态后,会立即发一个通告,然后每隔Adver_Int发一次。通告的内容包括VRID、优先级、虚拟IP列表、认证信息、通告间隔等。备机收到通告后,会重置Master_Down_Timer,并检查通告里的优先级和认证信息。
这里有个细节:主设备发通告的源IP是接口的真实IP,目的IP是224.0.0.18,源MAC是接口的真实MAC,目的MAC是VRRP的虚拟MAC(格式是00-00-5E-00-01-{VRID})。虚拟MAC的存在是为了让终端不需要改变ARP缓存——终端把网关的MAC学成虚拟MAC,主备切换时虚拟MAC不变,终端无感知。这个设计是VRRP能做到"透明切换"的关键。
如果主设备有多个虚拟IP,通告里会列出所有虚拟IP。备机收到后要检查自己配置的虚拟IP列表是否和通告一致。如果不一致,备机可能会拒绝进入Master,或者进入Master后不响应某些虚拟IP的ARP。这就是为什么主备的虚拟IP配置必须完全一致,差一个都会出问题。
4.2 备机收通告后的判断逻辑
备机收到通告后,按顺序做几件事:先检查VRID是否匹配,不匹配直接丢弃;再检查认证是否通过,不通过丢弃;然后检查优先级,如果通告里的优先级是0,说明主设备主动放弃,备机立即进入Master;如果优先级大于0,备机重置Master_Down_Timer,并根据优先级决定是否要抢占。
这里有个容易误解的地方:备机收到通告后,如果自己的优先级更高,它不会立即抢占,而是要等Master_Down_Timer超时。也就是说,即使备机优先级是200,主设备优先级是100,只要主设备还在正常发通告,备机就不会抢。抢占的前提是"主设备不再发通告"或者"主设备主动放弃"。这个设计是为了避免频繁切换,保证稳定性。
但如果配置了抢占并且没有抢占延迟,备机在Master_Down_Timer超时后会立即进入Master并发通告。这时候如果原主设备只是短暂失联(比如链路抖动),它恢复后会收到备机的通告,发现备机优先级更低,就会重新抢回主。这一来一回就是一次不必要的切换。
4.3 切换过程中的ARP与MAC行为
切换发生时,新主设备会做两件事:一是发一个免费ARP(Gratuitous ARP),把虚拟IP对应的虚拟MAC通告给全网;二是开始发VRRP通告,宣告自己成为新的主。
免费ARP的作用是刷新交换机和终端的ARP缓存。因为虚拟MAC不变,理论上终端不需要更新ARP,但交换机可能需要更新MAC地址表——原来虚拟MAC指向原主设备的端口,现在要指向新主设备的端口。免费ARP能加速这个更新过程。如果免费ARP丢了,交换机的MAC表可能还指向旧端口,导致流量黑洞,直到MAC表老化。这就是为什么有些场景下切换后要等几秒才恢复——不是VRRP没切换,是二层转发没跟上。
我在一个项目里遇到过切换后部分终端不通的问题,排查发现是接入交换机开启了某种ARP抑制功能,把免费ARP挡掉了。后来在接入层放行VRRP的免费ARP,问题解决。所以排查切换问题时,不要只看VRRP状态,还要看二层的ARP和MAC表有没有正确更新。
5. 那些让VRRP"失灵"的配置陷阱
5.1 通告间隔不一致导致的误切换
这是最常见的坑之一。主设备配了Adver_Int为1秒,备机配了2秒,或者反过来。备机用自己的Adver_Int去算Master_Down_Timer,如果备机的间隔比主设备大,它会等更久才判断主设备下线,切换变慢;如果备机的间隔比主设备小,它可能在主设备还在正常发通告的时候就误判下线,导致双主。
VRRP协议本身不强制主备的通告间隔一致,但接收端会用自己配置的间隔去计算超时。所以实际部署时,主备的Adver_Int必须一致。这个一致性不是协议保证的,是配置规范要求的。我在排查双主问题时,第一件事就是对比两边的Adver_Int配置。
5.2 认证不匹配:报文被静默丢弃
认证不匹配时,VRRP报文会被静默丢弃,不会有任何日志提示。这意味着主设备在正常发通告,备机也在正常收,但备机因为认证失败把报文扔了,Master_Down_Timer超时后进入Master,形成双主。这种问题最难排查,因为两边看起来都"正常"。
避免方法是部署时严格核对认证配置,并且在变更时同步修改。如果环境允许,可以考虑用无认证,减少一个故障点。但无认证的风险是VRID冲突时没有保护,所以要在VRID规划上做好隔离。
5.3 接口监控缺失:主设备"假活"
VRRP只监控自己发通告的能力,不监控上行链路。如果主设备的上行口断了,但它自己不知道,还会继续发通告,备机就不会切换。这时候终端把流量发给主设备,主设备转发不出去,业务就断了。
解决办法是配置接口监控(Track)。让VRRP跟踪上行接口的状态,接口down时自动降低优先级,让备机抢走主。这个机制在不同厂商的设备上叫法不同,但逻辑是一样的。配置时要注意:降低后的优先级要低于备机的优先级,否则备机还是抢不走。一般建议降低后的优先级比备机低至少10,留出余量。
5.4 双主问题的排查链路
双主是VRRP最严重的问题,会导致IP冲突、ARP混乱、流量时通时断。排查双主,我一般按这个顺序走:
- 先确认两边VRRP状态,是不是都显示Master。
- 检查VRID是否冲突,同一网段有没有其他组用了相同VRID。
- 检查认证配置是否一致。
- 检查通告间隔是否一致。
- 检查中间链路是否放行了VRRP组播报文,有没有ACL或风暴抑制挡掉了。
- 检查是否有接口监控配置不一致,导致一边降优先级一边没降。
- 抓包看两边是否都能收到对方的通告。
这个顺序是从最常见到最罕见,大部分双主问题在前三步就能定位。抓包是最后的手段,但也是最直接的——如果抓包看到两边都在发通告且都收不到对方的,那基本就是链路或过滤问题。
6. 让VRRP更可靠的几个进阶手段
6.1 BFD联动:把切换时间压到毫秒级
VRRP本身的切换时间受限于Master_Down_Timer,最快也要几百毫秒到几秒。如果业务对切换时间要求更高,可以引入BFD(Bidirectional Forwarding Detection)。BFD能在毫秒级检测到链路故障,然后通知VRRP立即切换,不用等Master_Down_Timer超时。
配置思路是:在主备之间建立BFD会话,VRRP跟踪BFD会话状态。BFD检测到故障后,直接触发VRRP状态切换。这样切换时间可以压到50毫秒以内,对大多数业务来说已经无感知了。但BFD的配置要注意检测时间和倍数,太激进会导致误切换,太保守又失去意义。一般建议检测时间设100毫秒,倍数3,也就是300毫秒内没收到BFD报文就认为故障。
6.2 负载分担:让备机不闲着
标准VRRP是主备模式,备机平时不转发流量,资源浪费。如果有多台设备,可以配置多个VRRP组,让不同组的主设备分散在不同设备上,实现负载分担。比如两台设备,配两个VRID,设备A是VRID 1的主、VRID 2的备,设备B是VRID 1的备、VRID 2的主。终端按网段或按VLAN分别指向不同的虚拟IP,流量就分散开了。
这种配置的复杂度在于要规划好VRID和虚拟IP的对应关系,以及确保每个组的优先级配置正确。好处是充分利用了设备资源,坏处是故障时的切换逻辑更复杂——一台设备挂了,它作为主的那些组都要切换,备设备要同时接管多个组,压力会集中。
6.3 与路由协议的联动
在有些网络里,VRRP不仅要做网关冗余,还要和路由协议联动。比如主设备是OSPF的DR,备设备是BDR,VRRP切换时希望OSPF也能快速收敛。这时候可以配置VRRP状态变化时触发路由协议的重新计算,或者用脚本联动。
这种联动不是VRRP标准的一部分,要靠厂商的私有功能或者外部脚本实现。配置时要小心,避免联动逻辑形成环路或者震荡。我的建议是,如果路由协议本身收敛够快,不一定非要联动;如果收敛慢,先优化路由协议本身,再考虑联动。
7. 我在实际项目里总结的几条经验
第一条,VRRP的配置一致性比什么都重要。主备的VRID、认证、通告间隔、虚拟IP列表,这四项必须完全一致。我见过太多问题都是因为"以为配一样了"但实际差了一个参数。建议部署时用配置对比工具逐项核对,变更时同步修改。
第二条,抓包是排查VRRP问题的终极手段。VRRP报文不大,抓包开销很小,但能直接看到谁在发、谁在收、内容是什么。抓包时注意过滤条件:协议号112,或者组播地址224.0.0.18。如果抓不到报文,先检查镜像口配置和ACL。
第三条,不要忽视二层。VRRP是三层协议,但它的报文交互依赖二层转发。交换机的MAC表、ARP表、风暴抑制、端口隔离,任何一个环节出问题都会影响VRRP。排查时要有全局视角,不要只盯着VRRP配置。
第四条,抢占延迟是个好东西,但要算清楚。延迟时间要覆盖主设备从故障恢复到业务就绪的完整时间,包括接口up、路由收敛、会话建立。设短了没效果,设长了切换慢。我的经验是,如果不确定,先设一个保守的值(比如60秒),观察一段时间再调整。
第五条,测试要模拟真实故障。不要只测"拔电源"这种硬故障,还要测"链路抖动""接口flapping""上行口down"这些软故障。软故障更容易暴露配置问题,也更容易导致误切换。测试时用打流工具持续发包,观察丢包情况,比只看VRRP状态更准确。
最后说一个细节:VRRP的虚拟MAC是00-00-5E-00-01-{VRID},这个MAC是标准规定的,所有厂商都一样。如果你在抓包时看到虚拟MAC不对,或者终端学到的网关MAC不是这个格式,那可能是配置有问题或者有代理ARP在干扰。这个细节在排查终端不通的问题时很有用,能快速判断流量到底走到了哪台设备。