服务器运维场景中,单点故障是导致业务中断的常见原因。Keepalived基于VRRP协议实现VIP(虚拟IP)浮动,配合Nginx反向代理负载均衡,可构建秒级故障切换的高可用集群。本文以两台CentOS 9服务器为例,完整演示Keepalived+Nginx高可用架构的搭建、配置与故障切换验证过程。
高可用集群架构设计与网络规划
典型双机高可用架构包含以下组件:
- 主服务器(MASTER):192.168.1.10,运行Nginx,持有VIP
- 备服务器(BACKUP):192.168.1.11,运行Nginx,监听VIP
- 虚拟IP(VIP):192.168.1.100,对外提供服务的浮动IP
- 后端应用服务器:192.168.1.20-22,运行业务应用
VRRP协议通过组播(224.0.0.18)在主备之间发送优先级通告。MASTER默认每1秒发送一次VRRP Advertisement,BACKUP在3个通告周期(3秒)内未收到MASTER通告时,自动接管VIP。
Keepalived安装与VRRP协议配置
在主备两台服务器上分别安装Keepalived:
# 安装Keepalived
dnf install -y keepalived
# 确认内核加载VRRP模块
modprobe vrrp
lsmod | grep vrrp
主服务器(MASTER)配置文件 /etc/keepalived/keepalived.conf:
global_defs {
router_id NGINX_HA_MASTER
enable_script_security
script_user root
}
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -20
fall 2
rise 1
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass YourVrrpPass2026
}
virtual_ipaddress {
192.168.1.100/24 dev eth0
}
track_script {
check_nginx
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
备服务器(BACKUP)配置文件:
global_defs {
router_id NGINX_HA_BACKUP
enable_script_security
script_user root
}
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -20
fall 2
rise 1
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass YourVrrpPass2026
}
virtual_ipaddress {
192.168.1.100/24 dev eth0
}
track_script {
check_nginx
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
}
关键参数说明:
priority:MASTER设为100,BACKUP设为90,差值需大于weight调整值weight -20:检测脚本失败时优先级减20,MASTER降为80低于BACKUP的90,触发切换virtual_router_id:主备必须一致,同一网段内不同VRRP实例必须唯一fall 2:连续2次检测失败才判定为故障,避免网络抖动误判
Nginx健康检查脚本编写与负载均衡配置
Nginx健康检查脚本 /etc/keepalived/check_nginx.sh:
#!/bin/bash
# 检查Nginx进程存活状态
if ! pidof nginx > /dev/null 2>&1; then
# 尝试重启Nginx
systemctl restart nginx
sleep 2
if ! pidof nginx > /dev/null 2>&1; then
echo "$(date) - Nginx is DOWN" >> /var/log/keepalived-check.log
exit 1
fi
fi
# 检查Nginx端口可用性
if ! curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:80 | grep -q '200\|301\|302'; then
echo "$(date) - Nginx port check failed" >> /var/log/keepalived-check.log
exit 1
fi
exit 0
chmod +x /etc/keepalived/check_nginx.sh
Nginx负载均衡配置 /etc/nginx/conf.d/load-balancer.conf:
upstream backend_servers {
# 后端应用服务器池
server 192.168.1.20:8080 weight=3 max_fails=3 fail_timeout=30s;
server 192.168.1.21:8080 weight=2 max_fails=3 fail_timeout=30s;
server 192.168.1.22:8080 weight=1 max_fails=3 fail_timeout=30s;
# 备用服务器,所有主服务器故障时启用
server 192.168.1.23:8080 backup;
keepalive 32;
keepalive_timeout 60s;
}
server {
listen 80;
server_name 192.168.1.100;
# 健康检查端点
location /health {
access_log off;
return 200 "OK\n";
}
location / {
proxy_pass http://backend_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 5s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
proxy_next_upstream error timeout http_502 http_503 http_504;
proxy_next_upstream_tries 3;
}
}
故障切换测试与脑裂防护验证
启动服务并验证初始状态:
# 主服务器启动
systemctl enable --now keepalived
systemctl enable --now nginx
# 查看VIP绑定状态
ip addr show eth0 | grep 192.168.1.100
# 输出: inet 192.168.1.100/24 scope global secondary eth0
# 查看VRRP状态
journalctl -u keepalived -f
# 输出: Entering MASTER STATE
模拟主服务器Nginx故障,验证切换过程:
# 在主服务器上停止Nginx
systemctl stop nginx
# 2秒后检查脚本检测到故障(check_nginx.sh重启失败)
# 4秒后Keepalived将优先级从100降为80
# BACKUP(90) > MASTER(80),触发VIP切换
# 在备服务器上验证VIP已接管
ip addr show eth0 | grep 192.168.1.100
# 输出: inet 192.168.1.100/24 scope global secondary eth0
# 在主服务器上查看状态变更
journalctl -u keepalived --since "1 min ago"
# 输出: VRRP_Instance(VI_1) Entering BACKUP STATE
脑裂(Split-Brain)防护是高可用集群的关键风险点。当主备之间的网络中断但两台服务器均正常运行时,双方都无法收到对方的VRRP通告,导致同时持有VIP。防护方案:
# 方案1:使用串口线作为备用心跳通道
vrrp_instance VI_1 {
# ...
unicast_src_ip 192.168.1.10
unicast_peer {
192.168.1.11
}
}
# 方案2:仲裁脚本检测网关可达性
vrrp_script check_gateway {
script "ping -c 2 -W 1 192.168.1.1 > /dev/null 2>&1"
interval 2
weight -30
fall 2
}
# 方案3:fencing机制 - 检测到脑裂时强制关机
notify_fault "/etc/keepalived/fence.sh"
服务器高可用集群生产环境加固清单
防火墙需放行VRRP协议和Nginx端口:
firewall-cmd --add-rich-rule='rule protocol value="vrrp" accept' --permanent
firewall-cmd --add-port=80/tcp --permanent
firewall-cmd --add-port=443/tcp --permanent
firewall-cmd --reload
SELinux策略调整,避免Keepalived执行脚本被拦截:
setsebool -P keepalived_connect_any 1
audit2allow -a -M keepalived_custom
semodule -i keepalived_custom.pp
日志集中收集与告警通知脚本 /etc/keepalived/notify.sh:
#!/bin/bash
STATE=$1
HOSTNAME=$(hostname)
VIP="192.168.1.100"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
MESSAGE="${TIMESTAMP} - ${HOSTNAME} VRRP状态变更: ${STATE} (VIP: ${VIP})"
# 写入日志
echo "$MESSAGE" >> /var/log/keepalived-notify.log
# 发送WebHook告警
curl -s -X POST "https://alert.example.com/api/webhook" \
-H "Content-Type: application/json" \
-d "{"text": "$MESSAGE", "priority": "critical"}"
# 邮件通知
echo "$MESSAGE" | mail -s "HA集群告警: ${HOSTNAME} -> ${STATE}" ops@yunthe.com
切换通知脚本需配合企业IM(钉钉/飞书)WebHook实现即时告警,确保运维团队在30秒内感知故障切换事件。定期进行混沌测试——每月模拟一次主服务器宕机、网络分区、Nginx进程崩溃场景,验证RTO(恢复时间目标)是否在5秒以内。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/linux-gao-ke-yong-ji-qun-da-jian-jiao-cheng-keepalivednginx/