Keepalived的notify_master脚本调优核心是确保可靠性、幂等性、低延迟和可追溯性;需校验角色与VIP状态、异步执行耗时操作、记录详细日志并推送结果、通过轻量信号而非直接启停服务实现业务联动。

Keepalived 的 notify_master 脚本是实现主备切换后自动执行业务联动的核心机制,调优关键在于**确保脚本可靠性、幂等性、低延迟响应和状态可追溯**,而非单纯追求功能实现。
确保 notify_master 脚本具备幂等性和状态判别能力
Keepalived 在状态变化时会多次触发 notify 脚本(如网络抖动、进程重启),若脚本无状态校验,易导致重复操作(如重复启动服务、重复发告警)。建议在脚本开头加入当前角色与预期角色的比对:
- 通过
$1获取 Keepalived 传入的状态(MASTER/BACKUP/FAULT) - 用
ip addr show或检查 VIP 是否已绑定,确认本机当前真实网络状态 - 仅当「传入状态为 MASTER」且「VIP 尚未生效」时才执行接管逻辑;反之亦然
- 示例判断片段:
if [[ "$1" == "MASTER" ]] && ! ip addr show eth0 | grep -q "192.168.1.100/24"; then ... fi
避免阻塞 Keepalived 主进程,使用异步或超时控制
notify 脚本若执行耗时操作(如拉起数据库、同步大文件、调用外部 HTTP 接口),会阻塞 Keepalived 的状态机,导致健康检查超时、脑裂风险升高。必须做以下约束:
- 所有耗时操作放入后台子进程(
&)或使用nohup分离 - 关键步骤设置超时,例如:
timeout 10s systemctl start myapp.service - 禁止在脚本中使用
sleep等待式逻辑;状态等待应由独立监控进程完成 - Keepalived 配置中显式设置
notify_stop和notify_backup,使各状态路径清晰可控
增强可观测性:记录日志 + 通知结果反馈
生产环境中,无法快速定位“为何没切换”或“切换后服务未就绪”,往往因 notify 脚本静默失败。需强制落地以下实践:
- 脚本开头统一重定向 stdout/stderr 到带时间戳的日志文件,如:
exec >> /var/log/keepalived-notify.log 2>&1 - 每一步关键动作打印明确日志,含时间、角色、VIP、执行命令及返回码
- 成功接管后,向本地监控系统(如 Prometheus Pushgateway)或企业微信/钉钉推送结构化消息
- 失败时记录错误并触发告警(如调用
curl -X POST alert-api/trigger)
与业务生命周期解耦,用轻量信号协调
不推荐在 notify_master 中直接启停重量级服务(如 MySQL、Nginx),而应通过轻量机制触发业务侧响应:
- 写一个标记文件(如
/run/keepalived/state=master),由 systemd path unit 监听该文件变化,再触发对应 service - 发送
systemd-notify --ready或kill -USR1 $(cat /var/run/myapp.pid)通知已有进程重载配置 - 使用 Redis 或 etcd 作为状态总线,Keepalived 脚本只写 key,业务进程 watch 变更
- 这样既降低耦合,又便于单独测试、灰度和回滚

















