Vrrp_Script返回0未触发切换,因需weight生效且与track_script绑定;须设正确权限、路径、shebang及interval/fall;所有节点配state BACKUP,用带符号weight动态调priority;curl检查需超时和状态码验证;多脚本为“与”逻辑,权重累加;SELinux权限常被忽略。

为什么Vrrp_Script脚本返回0却没触发主备切换
Keepalived只把Vrrp_Script返回值为0视为“健康”,但光返回0还不够——必须确保weight配置生效且与track_script正确绑定。常见错误是脚本权限不足(没+x)、路径写错、或脚本里用了bash特有语法但shebang写的是/bin/sh。另外,Keepalived默认每1秒执行一次脚本,但interval未显式设置时会用默认值,容易误判瞬时抖动为故障。
实操建议:
- 脚本开头固定写
#!/bin/bash,所有命令用绝对路径(如/usr/bin/curl而非curl) - 在
vrrp_script块中显式声明interval 2和fall 3(连续3次失败才降权) - 用
log syslog local0开启日志,并在脚本末尾加echo "$(date): health check result $?" >> /var/log/keepalived_health.log辅助排查
如何让Vrrp_Script影响VIP切换权重而不是直接抢主
直接靠state MASTER硬指定角色会导致脑裂,正确做法是所有节点都配state BACKUP,再通过weight动态调整优先级。比如主节点初始priority 100,脚本健康时weight +5,故障时weight -30,这样故障后优先级变成70,低于备用节点的100,自然让出VIP。
关键点:
-
weight值必须带符号(+5或-30),不带符号会被忽略 - 备用节点也要定义同样的
vrrp_script和track_script,否则权重无法比较 - 两节点
priority差值要大于weight绝对值,否则可能卡在中间态(如主100、备90,而weight -15会让主变85,仍高于备)
监控HTTP服务时curl超时导致VRRP状态抖动
curl默认无超时,遇到后端卡住会hang住整个检查周期,拖慢VRRP状态更新。更糟的是,如果脚本被kill掉(比如systemd杀超时进程),Keepalived可能收不到退出码,误判为“成功”。
稳妥写法:
- 强制加
--max-time 3 --connect-timeout 2,避免单次检查超过5秒 - 检查返回码同时验证HTTP状态码:
if [ $? -eq 0 ] && [[ "$http_code" == "200" ]]; then exit 0; else exit 1; fi - 别用
set -e,Keepalived依赖明确的退出码,异常中断反而难定位
多个Vrrp_Script如何协同控制同一实例的权重
一个vrrp_instance可以track_script多个脚本,但Keepalived对它们是“与”逻辑:任一脚本失败,就触发weight变化。想实现“数据库挂了才切,Nginx挂了只告警”,得把不同严重度的检查拆到不同脚本,再用weight数值区分影响程度(比如DB脚本weight -40,Nginx脚本weight -5)。
注意:
- 所有被
track_script引用的脚本必须在同一个vrrp_instance下定义,跨实例无效 - 权重变化是累加的,两个脚本分别
-20和-30,最终总权重变化是-50 - 如果需要“或”逻辑(任一失败就切),只能合并进一个脚本里做判断
curl也可能因SELinux阻止网络访问而静默失败。先跑ausearch -m avc -ts recent | grep keepalived看有没有拒绝记录,比反复改配置更省时间。

















