Keepalived 健康检查需用真实请求(如 curl + HTTP 状态码/JSON 内容校验)替代进程或端口检查,并组合多目标探测、设超时与阈值,配合 weight 与 priority 差值确保准确切换。

Keepalived 本身不判断业务是否真正可用,它只认脚本返回的退出码:0 表示健康,非 0 表示异常。所谓“更智能切换”,核心是让脚本能准确反映服务的真实状态,而不是仅看进程是否存在或端口是否开放。
用真实请求代替进程检查
只检查 ps -C nginx 或 netstat -tlnp | grep :80 容易误判。比如 Nginx master 进程还在,但 worker 全崩了;或者端口通了,但后端 API 返回 502/503。应该模拟客户端行为:
- 用
curl -s --max-time 2 -o /dev/null -w "%{http_code}" http://127.0.0.1:8080/health获取 HTTP 状态码,再判断是否等于 200 - 对 JSON 接口,加
jq -e '.status == "up"'验证响应内容,避免返回 200 却带错误 body - 若服务依赖数据库或缓存,health 接口里必须包含这些下游组件的连通性检查
避免单点误判和网络抖动干扰
一次探测失败不代表服务不可用,尤其在物理机断网、DNS 故障等场景下:
- 不要只 ping 一个外部地址(如 8.8.8.8),更不能用域名——全部用 IP,绕过 DNS
- 建议组合多个探测目标(例如同时检查本地 API + 同机房另一台服务的健康接口),任一通即认为网络基本正常
- 通过
fall 3 rise 2设置连续失败/成功次数阈值,防止因瞬时抖动触发频繁切换
脚本执行要快、稳、权限明确
Keepalived 是单线程调用脚本,阻塞会导致 VIP 切换延迟甚至脑裂:
- 所有命令必须设超时:
timeout 3 curl ...或curl -m 3 ...,别让脚本卡住 - 路径全用绝对路径,比如
/usr/bin/curl、/usr/bin/jq,避免 PATH 不一致导致命令找不到 - 脚本必须 root 可执行,且开头加
#!/bin/bash,末尾显式写exit 0或exit 1,别依赖上一条命令的默认退出码
权重变化要匹配 priority 差值
切换不是靠“脚本失败就切”,而是靠优先级动态调整后触发选举:
- 假设主节点 priority 是 100,备节点是 90,差值为 10
- 那么脚本的
weight -12就能让主节点降为 88,低于备节点,触发切换;但weight -5只降到 95,仍高于备节点,不会切 - 务必确保
abs(weight)>priority_master - priority_backup,否则权重变化无效










