1. 项目概述
在互联网服务架构中,Nginx作为前端流量入口的重要性不言而喻。我曾经历过一次线上事故:凌晨3点Nginx进程意外崩溃,导致整个电商平台无法访问,损失惨重。这次教训让我深刻认识到单点故障的风险,也促使我研究出了这套基于Keepalived的Nginx高可用方案。
这套方案的核心原理是通过VRRP协议实现虚拟IP(VIP)在两台服务器间的自动漂移。当主节点Nginx服务异常时,自定义监控脚本会触发Keepalived状态变更,使VIP自动切换到备用节点。整个过程无需人工干预,切换时间可控制在5秒以内,真正实现了服务的高可用性。
2. 环境准备与架构设计
2.1 硬件配置建议
在实际生产环境中,我建议采用以下配置方案:
| 组件 | 主节点配置 | 备节点配置 |
|---|---|---|
| 服务器 | 物理机/云主机 | 物理机/云主机 |
| CPU | 4核以上 | 同等或略低配置 |
| 内存 | 8GB以上 | 8GB以上 |
| 网络 | 千兆网卡 | 千兆网卡 |
| 存储 | SSD 100GB以上 | SSD 100GB以上 |
注意:备节点配置不必与主节点完全一致,但应保证能承担同等流量压力。我曾遇到过备节点配置过低导致切换后性能不足的情况。
2.2 网络拓扑设计
code复制[客户端]
|
[VIP:192.168.211.100]
├── [主节点:192.168.211.134]
└── [备节点:192.168.211.135]
关键网络配置要点:
- 确保两台服务器在同一二层网络(相同VLAN/子网)
- 建议使用独立的心跳线(交叉线直连)作为备份通信通道
- 组播地址默认使用224.0.0.18,需确保网络设备未过滤
3. 软件安装与配置
3.1 系统基础优化
在安装服务前,建议先进行系统优化:
bash复制# 关闭不必要的服务(根据实际情况调整)
systemctl stop postfix && systemctl disable postfix
# 调整文件描述符限制
echo "* soft nofile 65535" >> /etc/security/limits.conf
echo "* hard nofile 65535" >> /etc/security/limits.conf
# 内核参数优化
cat >> /etc/sysctl.conf <<EOF
net.ipv4.ip_nonlocal_bind=1
net.ipv4.ip_forward=1
EOF
sysctl -p
3.2 Nginx安装与加固
bash复制# 安装最新稳定版Nginx
yum install -y yum-utils
yum-config-manager --add-repo https://nginx.org/packages/centos/$(rpm -E %{rhel}).0/x86_64/
yum install -y nginx
# 安全加固配置
sed -i 's/# server_tokens off;/server_tokens off;/' /etc/nginx/nginx.conf
mkdir /etc/nginx/conf.d/ssl
chmod 700 /etc/nginx/conf.d/ssl
# 创建健康检查端点
cat > /etc/nginx/conf.d/health.conf <<EOF
server {
listen 127.0.0.1:8080;
location /status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
}
EOF
4. Keepalived深度配置
4.1 主节点配置详解
bash复制cat > /etc/keepalived/keepalived.conf <<'EOF'
! Configuration File for keepalived
global_defs {
notification_email {
admin@example.com
}
notification_email_from keepalived@$(hostname)
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id LVS_MASTER # 必须全局唯一
vrrp_skip_check_adv_addr
vrrp_strict # 严格模式检查配置
script_user root # 脚本执行用户
enable_script_security
}
vrrp_script chk_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
timeout 2
weight -20
fall 3
rise 2
}
vrrp_instance VI_1 {
state MASTER
interface eth0 # 使用ip a确认网卡名
virtual_router_id 51 # 同一组实例必须相同
priority 100 # 主节点值更高
# 通信设置
advert_int 1
authentication {
auth_type PASS
auth_pass d7f5x9 # 建议使用复杂密码
}
# 虚拟IP配置
virtual_ipaddress {
192.168.211.100/24 dev eth0 label eth0:1
}
# 跟踪脚本
track_script {
chk_nginx
}
# 抢占模式配置
nopreempt # 是否允许优先级低的节点抢占
preempt_delay 300 # 抢占延迟(秒)
# 通知脚本(可选)
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
EOF
4.2 监控脚本增强版
经过多次生产环境验证,我优化了监控脚本:
bash复制#!/bin/bash
# 增强版Nginx监控脚本
# 定义重试参数
MAX_RETRY=3
RETRY_INTERVAL=2
# 检查Nginx进程
check_nginx_process() {
pgrep -x nginx >/dev/null
return $?
}
# 检查Nginx端口
check_nginx_port() {
netstat -tlnp | grep -w nginx | grep -q ':80 '
return $?
}
# 检查Nginx健康端点
check_nginx_status() {
curl -s --connect-timeout 3 http://127.0.0.1:8080/status >/dev/null 2>&1
return $?
}
# 主检查逻辑
for ((i=1; i<=$MAX_RETRY; i++)); do
if check_nginx_process && check_nginx_port && check_nginx_status; then
exit 0
fi
# 尝试重启
systemctl restart nginx
sleep $RETRY_INTERVAL
done
# 所有重试失败后停止keepalived
systemctl stop keepalived
exit 1
5. 高级调优与故障排查
5.1 Keepalived性能调优
bash复制# 调整内核参数优化VRRP
cat >> /etc/sysctl.conf <<EOF
# Keepalived调优
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_ignore = 1
net.ipv4.conf.default.arp_announce = 2
EOF
# 日志分离配置
cat > /etc/rsyslog.d/keepalived.conf <<EOF
:programname, isequal, "keepalived" /var/log/keepalived.log
& ~
EOF
systemctl restart rsyslog
5.2 常见故障处理手册
我在实践中总结的典型问题及解决方案:
| 故障现象 | 可能原因 | 解决方案 |
|---|---|---|
| VIP不漂移 | 防火墙阻止VRRP通信 | firewall-cmd --add-rich-rule='rule protocol value="vrrp" accept' --permanent |
| 脑裂(双主) | 网络分区 | 检查网络连通性,配置nopreempt选项 |
| 切换延迟高 | advert_int设置过大 | 调整为1秒,但会增加网络负载 |
| 脚本不执行 | SELinux限制 | setsebool -P keepalived_connect_any 1 |
| VIP漂移但服务不可用 | Nginx配置不一致 | 使用rsync保持配置同步:rsync -avz /etc/nginx/ backup:/etc/nginx/ |
6. 生产环境最佳实践
6.1 监控与告警集成
建议将Keepalived状态纳入监控系统:
bash复制# Prometheus监控配置示例
scrape_configs:
- job_name: 'keepalived'
static_configs:
- targets: ['192.168.211.134:9666', '192.168.211.135:9666']
# Keepalived开启Prometheus exporter
vrrp_instance VI_1 {
...
track_script {
chk_nginx
}
prometheus_uri http://0.0.0.0:9666/metrics
}
6.2 自动化维护脚本
这是我使用的维护脚本集:
bash复制#!/bin/bash
# 高可用集群管理工具
case "$1" in
status)
echo "=== VIP状态 ==="
ip addr show | grep -A2 "eth0:"
echo "=== Keepalived状态 ==="
systemctl status keepalived -l
echo "=== Nginx状态 ==="
systemctl status nginx -l
;;
failover)
echo "模拟故障切换..."
systemctl stop keepalived
;;
sync)
echo "同步配置到备节点..."
rsync -avz --delete /etc/nginx/ backup:/etc/nginx/
rsync -avz /etc/keepalived/ backup:/etc/keepalived/
ssh backup "systemctl reload nginx keepalived"
;;
*)
echo "用法: $0 {status|failover|sync}"
exit 1
esac
经过三年在生产环境的运行验证,这套方案成功将我们的服务可用性从99.9%提升到了99.99%。最关键的是要定期进行故障演练,我建议每月至少执行一次人工切换测试,确保整个故障转移流程始终处于就绪状态。