Keepalived 通过 vrrp_script 执行自定义健康检查脚本,优先尝试重启卡死的 Nginx,失败后才触发 VIP 切换;脚本需基于真实 HTTP 请求探测(如 /healthz),而非仅检查进程存在。

Keepalived 本身不直接监控 Nginx 进程是否“死锁”,但它可以通过 vrrp_script 执行自定义脚本,检测 Nginx 是否响应正常(例如能否接受 HTTP 请求、worker 进程是否存活、端口是否可连通等),从而触发 VIP 切换或本地自愈动作。所谓“死锁自愈”,实际是指:当检测到 Nginx 异常(如无响应、进程卡住、502 频发),自动尝试重启 Nginx,失败后再触发 Keepalived 主备切换。
核心思路:用 vrrp_script 做健康探测 + 本地修复优先
Keepalived 的 vrrp_script 每隔几秒执行一次脚本,返回值决定权重增减。关键不是“判断进程是否存在”,而是“Nginx 是否真正可用”。死锁场景下,nginx -t 或 ps aux | grep nginx 可能仍显示进程在运行,但 worker 已卡住无法处理请求 —— 这时必须靠真实请求探测。
- 脚本应模拟客户端向本地 Nginx 发起 HTTP 请求(如
curl -s --connect-timeout 3 -m 5 http://127.0.0.1:80/healthz) - 返回码为 0 表示服务正常;非 0(超时、连接拒绝、返回 5xx)则视为异常
- 异常时,脚本内先执行
systemctl try-restart nginx或nginx -s reload,等待 2 秒后再次探测 - 若重试后仍失败,才让 Keepalived 降低本机优先级,触发备机升主
编写可靠的 vrrp_script 探测脚本
保存为 /etc/keepalived/check_nginx.sh,确保可执行(chmod +x):
#!/bin/bash # 检测 Nginx 是否真正在提供服务(防假活) URL="http://127.0.0.1:80/healthz" RETRY=2 <h1>第一次探测</h1><p>if curl -s --connect-timeout 3 -m 5 "$URL" >/dev/null 2>&1; then exit 0 fi</p><h1>尝试重启 Nginx</h1><p>systemctl try-restart nginx >/dev/null 2>&1 sleep 2</p><h1>重试探测</h1><p>for i in $(seq 1 $RETRY); do if curl -s --connect-timeout 3 -m 5 "$URL" >/dev/null 2>&1; then exit 0 fi sleep 1 done</p><h1>彻底失败,返回非 0,触发降权</h1><p>exit 1
注意:Nginx 需配置 /healthz location(返回 200,不依赖后端),例如:
location = /healthz {
return 200 "OK\n";
add_header Content-Type text/plain;
}
Keepalived 配置中集成该脚本
在 /etc/keepalived/keepalived.conf 中定义:
vrrp_script chk_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 5 # 每 5 秒执行一次
weight -10 # 失败时本节点优先级减 10(如原 priority 100 → 90)
fall 2 # 连续 2 次失败才触发降权
rise 2 # 连续 2 次成功才恢复权重
}
<p>vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1</p><pre class="brush:php;toolbar:false;">authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.100/24
}
track_script {
chk_nginx # 绑定上面定义的脚本
}}
这样,当 Nginx 卡死时,脚本会尝试重启;若重启无效,本机 priority 变为 90,低于备机(如备机 priority 95),VIP 自动漂移到备机 —— 实现“本地自愈优先,故障转移兜底”。
补充建议:避免误切与日志可观测
- 在脚本中添加日志记录(如
logger -t keepalived-nginx "Nginx recovered after restart"),便于排查是重启成功了还是切走了 - 避免使用
kill -9强杀 worker,优先用nginx -s reload或systemctl reload nginx,更安全 - 不要把探测 URL 设为业务路径(如
/api/user),防止探测请求干扰业务统计或触发限流 - 若 Nginx 启动慢(如加载大配置或 SSL 证书),适当调大
curl的--connect-timeout和脚本中的sleep


















