nopreempt仅在所有节点state均为BACKUP时生效;若任一节点设为MASTER,则无视nopreempt,恢复即抢VIP,因其违反VRRP协议中BACKUP才可参选、MASTER不参与选举的语义。

必须把所有节点的 state 都设为 BACKUP,否则 nopreempt 不生效。
为什么 nopreempt 不起作用?
最常见的错误是主节点仍配置 state MASTER。Keepalived 规定:nopreempt 仅在所有节点均为 BACKUP 时才启用。一旦任一节点设为 MASTER,它就无视 nopreempt,恢复即抢 VIP。
根本原因在于 VRRP 协议语义:MASTER 是“已当选”状态,不参与选举;BACKUP 才是“可参选”状态,nopreempt 控制的是 BACKUP 节点在检测到更高优先级 BACKUP 在线时是否发起新选举。
- 错误配置:
state MASTER+priority 100+nopreempt→nopreempt被忽略 - 正确配置:
state BACKUP+priority 100+nopreempt→ 主恢复后不抢
nopreempt 的真实行为边界
它只阻止“主恢复后主动切回”,但不改变故障转移逻辑:当当前 MASTER 挂了,BACKUP 依然会按优先级正常接管;如果接管后的 MASTER 又挂了,原主(只要还活着)仍会因优先级高而再次成为新 MASTER —— 这是预期行为,不是 bug。
也就是说:nopreempt 管的是“恢复时是否抢”,不管“故障时是否接”。它解决的是抖动,不是单点失效。
- 初始:KA1(
priority 100,state BACKUP)、KA2(priority 80,state BACKUP) → KA1 成 MASTER - KA1 宕机 → KA2 接管 VIP
- KA1 恢复 → 因
nopreempt,VIP 留在 KA2,KA1 保持 BACKUP - KA2 宕机 → KA1 立即接管(因它是唯一存活的高优 BACKUP)
配置时容易踩的三个坑
非抢占模式看似简单,但生产环境出问题基本都卡在这三处:
-
vrrp_strict开启时会强制校验 VRRP 包合法性,同时禁止state BACKUP和nopreempt共存 —— 必须关闭它,或干脆删掉这一行 -
virtual_router_id在所有节点上必须完全一致,否则它们压根不在同一个 VRRP 组里,nopreempt形同虚设 - ARP 缓存未刷新:VIP 切换后,下游交换机/客户端可能仍缓存旧 MAC,导致流量发向已释放 VIP 的节点;需配合
notify_master脚本发 gratuitous ARP,或调大arp_ignore/arp_announce内核参数
真正难的不是加一行 nopreempt,而是确保整个 VRRP 组的状态收敛逻辑被你完全掌控——比如当两台机器同时认为自己该是 MASTER 时,谁发的通告更早、谁的优先级更新更及时、谁的内核 ARP 表更干净,这些细节才决定震荡到底发不发生。











