高可用集群架构设计要点
Nginx+Keepalived是服务器运维中经典的负载均衡高可用方案。Keepalived基于VRRP协议实现虚拟IP漂移,Nginx负责七层负载均衡和请求分发。当主节点宕机时,备节点在秒级内接管虚拟IP,实现服务无感知切换。这套方案适用于Web服务、API网关、反向代理等场景,成本远低于商业F5设备。
架构拓扑:两台服务器运行Nginx+Keepalived,通过VRRP共享一个虚拟IP(VIP)。客户端请求到VIP,主节点处理请求并转发到后端Real Server。主节点故障时,VIP自动漂移到备节点,流量无缝切换。
环境准备与基础配置
测试环境使用两台CentOS 9服务器:
主节点 (MASTER):192.168.1.10
备节点 (BACKUP):192.168.1.11
虚拟IP (VIP):192.168.1.100
后端服务器:192.168.1.20, 192.168.1.21
两台机器安装Nginx和Keepalived:
# 安装EPEL源和必要组件
dnf install -y epel-release
dnf install -y nginx keepalived
# 开启IP转发(如果Nginx做四层代理需要)
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p
# 防火墙放行VRRP协议(关键步骤,很多故障出在这里)
firewall-cmd --add-rich-rule='rule protocol value="vrrp" accept' --permanent
firewall-cmd --reload
# 确保selinux不干扰
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
Nginx负载均衡配置
两台服务器的Nginx配置保持一致。编辑/etc/nginx/nginx.conf,配置反向代理和负载均衡:
http {
upstream backend {
# 后端Real Server,可加权轮询
server 192.168.1.20:8080 weight=1 max_fails=3 fail_timeout=30s;
server 192.168.1.21:8080 weight=1 max_fails=3 fail_timeout=30s;
# 备用服务器,当所有主服务器都down时启用
server 192.168.1.22:8080 backup;
}
server {
listen 80;
server_name 192.168.1.100;
location / {
proxy_pass http://backend;
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_connect_timeout 5s;
proxy_read_timeout 60s;
# 健康检查:后端返回502/503时自动剔除
proxy_next_upstream error timeout http_502 http_503;
proxy_next_upstream_tries 2;
}
# 健康检查端点,给Keepalived用
location /health {
access_log off;
return 200 "ok\n";
add_header Content-Type text/plain;
}
}
}
Nginx本身的健康检查是被动式的——只有请求失败才会触发剔除。主动健康检查需要Nginx Plus商业版或nginx_upstream_check_module第三方模块。免费方案是用Keepalived的脚本检测来间接实现。
Keepalived VRRP配置
主节点配置文件/etc/keepalived/keepalived.conf:
global_defs {
router_id NGINX_MASTER
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script chk_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 MyStr0ngP@ss
}
virtual_ipaddress {
192.168.1.100/24
}
track_script {
chk_nginx
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
备节点配置几乎相同,区别在于state和priority:
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 90 # 比主节点低
advert_int 1
# 其余配置与master一致
authentication {
auth_type PASS
auth_pass MyStr0ngP@ss
}
virtual_ipaddress {
192.168.1.100/24
}
track_script {
chk_nginx
}
}
健康检查脚本与故障切换逻辑
Nginx存活检测脚本/etc/keepalived/check_nginx.sh:
#!/bin/bash
# 检测Nginx进程是否存在
if [ -f /run/nginx.pid ]; then
pid=$(cat /run/nginx.pid)
if kill -0 "$pid" 2>/dev/null; then
exit 0
fi
fi
# Nginx进程不存在,尝试重启
systemctl restart nginx
sleep 2
# 重启后再次检查
if [ -f /run/nginx.pid ]; then
pid=$(cat /run/nginx.pid)
if kill -0 "$pid" 2>/dev/null; then
exit 0
fi
fi
# 重启失败,返回非零,Keepalived会降低优先级触发切换
exit 1
切换通知脚本/etc/keepalived/notify.sh:
#!/bin/bash
STATE=$1
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
HOSTNAME=$(hostname)
case "$STATE" in
master)
logger "[$TIMESTAMP] $HOSTNAME 成为MASTER,VIP已接管"
# 可选:发送告警通知到钉钉/飞书webhook
curl -s -X POST "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d "{"msgtype":"text","text":{"content":"Keepalived切换: $HOSTNAME 成为MASTER ($TIMESTAMP)"}}"
;;
backup)
logger "[$TIMESTAMP] $HOSTNAME 成为BACKUP"
;;
fault)
logger "[$TIMESTAMP] $HOSTNAME 进入FAULT状态"
;;
esac
# 赋予脚本执行权限
chmod +x /etc/keepalived/check_nginx.sh
chmod +x /etc/keepalived/notify.sh
# 启动服务
systemctl enable --now keepalived
systemctl restart nginx
故障排查与常见问题
问题1:VIP不漂移,主节点恢复后无法接管
检查两台机器是否在同一网段、virtual_router_id是否一致。用tcpdump抓VRRP报文确认心跳通信:
tcpdump -i eth0 vrrp -nn
# 应看到主节点每秒发送VRRP advertisement
# 如果没有任何报文,检查防火墙是否放行vrrp协议
问题2:脑裂(split-brain)
主备同时持有VIP,会导致MAC地址混乱。根因是主备之间网络不通,各自认为对方已宕机。排查方向:检查交换机是否启用了多播限制;尝试将VRRP改为单播模式:
vrrp_instance VI_1 {
# ...
unicast_src_ip 192.168.1.10 # 本机IP
unicast_peer {
192.168.1.11 # 对端IP
}
}
问题3:Nginx正常但keepalived频繁切换
查看/var/log/messages中的keepalived日志。常见原因是check脚本超时返回或weight配置不当。weight值要保证主节点脚本失败后priority降到低于备节点——主节点100-20=80小于备节点90,就会触发切换。如果weight设得太小(比如-5),100-5=95仍大于90,就不会切换。
问题4:切换后服务短暂不可用
VRRP切换本身只需1-3秒,但客户端ARP缓存中VIP对应的MAC地址还没更新。解决办法是在notify_master脚本中发送免费ARP(gratuitous ARP):
# 在notify.sh的master分支中添加
arping -I eth0 -c 5 -s 192.168.1.100 192.168.1.1
安全加固与生产环境建议
Keepalived的auth_pass默认明文传输,在生产环境中应配合网络隔离。VRRP通信局限在内网,不要暴露在公网。
服务器安全加固方面,限制SSH访问源IP,禁用密码登录只允许密钥认证。定期更新系统补丁,配置fail2ban防止暴力破解。Nginx层面隐藏版本号(server_tokens off),限制请求体大小和速率防止CC攻击。
监控方面,通过Prometheus + keepalived_exporter采集VRRP状态指标,设置告警规则:当某个节点持续处于BACKUP超过预期时间,或发生非计划性切换时立即告警。算力资源规划上,备节点配置不应低于主节点,确保接管后能承载相同流量。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/nginxkeepalived-gao-ke-yong-ji-qun-da-jian-shuang-ji-re-bei/