keepalived进程退出但vip未删除是最易忽略的“假死”状态,根源在于退出时未执行清理逻辑,导致主备冲突、双vip及切换失败;需校验配置、用restart而非reload、完善systemd execstop、杜绝双backup无nopreempt、确保vrrp组播畅通。

Keepalived进程退出但VIP没删,是最容易被忽略的“假死”状态——表面服务停了,实则虚拟IP还挂在网卡上,导致主备冲突、双VIP、客户端连不上、切换失败全由此引发。问题核心不是进程挂了,而是退出时没执行清理逻辑。
检查是否用了错误信号强制终止
用 kill -USR1 或 systemctl reload 想“动态提权”或“热重载”,却没意识到:如果配置有语法错误、VRID冲突、认证密码不一致,keepalived会在重载瞬间直接退出,且不触发VIP清理流程。这不是崩溃,是“静默放弃”。
正确做法是:
• 先用 keepalived -t -f /etc/keepalived/keepalived.conf 校验配置
• 修改后用 systemctl restart keepalived(非 reload)确保完整启停流程
• 绝对避免向生产环境发 USR1 信号做优先级调整——它不干这事,那是 vrrp_script 的活
确认退出路径是否绕过了清理钩子
当 keepalived 被 service keepalived stop 或 systemctl stop 停止时,若 systemd 单元文件未正确定义 ExecStop,或脚本中存在 set -e 未捕获的异常,会导致主进程退出但子进程(尤其是 vrrp 子进程)残留,VIP仍绑定在接口上。
验证方式:
• 执行 ip a | grep your_vip,停服务后仍存在即为僵死
• 查看 ps aux | grep keepalived,确认无任何相关进程
• 若 VIP 还在,立即手动清理:ip addr del 10.191.22.247/32 dev bond0
• 长期解法:在 systemd service 文件中补充 ExecStop=/usr/bin/killall -q keepalived,并加 ExecStopPost=-/sbin/ip addr flush label bond0 scope link
排查双BACKUP+无nopreempt引发的竞争残留
主备都配成 state BACKUP,又没启用 nopreempt,启动顺序稍有偏差就会让两节点短暂同时抢到 MASTER 状态;一旦其中一方异常退出,另一方未必能及时感知并接管,反而留下“旧VIP未撤、新VIP未升”的空窗。
必须做到:
• 主节点明确设为 state MASTER(哪怕只是语义约定)
• 备节点设为 state BACKUP,且 nopreempt 保持关闭(默认行为即可)
• 两边 virtual_router_id、auth_pass、interface 严格一致,差一个空格都会导致 VRRP 报文被丢弃,心跳失效却不报错
验证内核与防火墙是否阻断了退出通知链路
VRRP 依赖组播(协议号 112)传递状态变更。若防火墙 DROP 了 VRRP 包,主节点退出时无法广播“我退位了”,备节点就永远等不到切换信号,自然不会去绑 VIP;而主节点自身因异常退出,也没来得及执行 del ip 操作。
快速验证:
• tcpdump -i bond0 ip proto 112 -nn,看是否有 VRRP 流量进出
• 开放规则(生产环境必须用此替代停防火墙):
firewall-cmd --permanent --add-rich-rule='rule protocol value="112" accept'
firewall-cmd --reload
• 同时检查 /proc/sys/net/ipv4/conf/bond0/forwarding 是否为 1,转发关闭会导致本地 VRRP 报文发不出










