目录
一、Nginx 与 Keepalived 基础概念
1.1 Keepalived 原理详解
Keepalived 是 Linux 系统下实现 VRRP(Virtual Router Redundancy Protocol,虚拟路由冗余协议)的高可靠性软件。其核心功能是通过 VRRP 协议实现服务器的故障切换,确保服务的高可用性。
VRRP 协议的工作机制如下:
- 将多台提供相同服务的设备组成一个路由器组(Router Group),其中包含一个 master 和多个 backup
- 对外呈现一个虚拟 IP(VIP),master 负责处理 ARP 响应和数据包转发
- master 定期发送组播消息(VRRP 包),backup 通过接收该消息监控 master 状态
- 当 backup 在超时时间内未收到 VRRP 包时,认为 master 故障,会根据优先级选举新的 master
- 新旧 master 切换时,VIP 会从原 master 转移到新 master,实现服务的无缝接管
1.2 服务架构概述
本次实践采用的架构包含:
- 两台 Nginx 服务器(nginx01 和 nginx02)
- 两台 Web 服务器(web01 和 web02)
- 虚拟 IP(VIP)用于对外提供服务
二、环境准备与 IP 规划
2.1 服务器角色与 IP 分配
服务器角色 | IP 地址 | 备注 |
---|---|---|
web01 | 192.168.10.103 | 提供 Web 服务,端口 8081 |
web02 | 192.168.10.104 | 提供 Web 服务,端口 8082 |
nginx01 | 192.168.10.101 | Nginx 主服务器(主从架构中为 master) |
nginx02 | 192.168.10.102 | Nginx 从服务器(主从架构中为 backup) |
虚拟 IP(主从) | 192.168.10.100 | 对外服务 IP |
虚拟 IP1(双主) | 192.168.10.100 | nginx01 为主时使用 |
虚拟 IP2(双主) | 192.168.10.200 | nginx02 为主时使用 |
2.2 基础环境配置
在所有服务器上执行以下操作,关闭防火墙和 SELinux:
# 停止防火墙
systemctl stop firewalld
# 禁用防火墙开机自启动
systemctl disable firewalld
# 临时关闭SELinux
setenforce 0
# 永久关闭SELinux(修改配置文件)
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
三、Web 服务安装与配置
3.1 安装 HTTPD 服务
在 web01 和 web02 上分别安装 HTTPD:
# 安装httpd
yum -y install httpd
3.2 配置 Web 测试页面
在 web01 上创建测试页面:
# 创建测试页面
echo "test01" > /var/www/html/index.html
# 修改监听端口为8081
vim /etc/httpd/conf/httpd.conf
# 找到Listen 80行,修改为
Listen 8081
# 启动httpd服务
systemctl start httpd
# 设置开机自启动
systemctl enable httpd
在 web02 上执行类似操作,但测试页面内容为 "test02",监听端口为 8082:
echo "test02" > /var/www/html/index.html
vim /etc/httpd/conf/httpd.conf
Listen 8082
systemctl start httpd
systemctl enable httpd
四、Nginx 服务安装与配置
4.1 安装依赖包
在 nginx01 和 nginx02 上安装编译所需的依赖包:
yum -y install pcre-devel zlib-devel gcc*
4.2 创建 Nginx 用户
创建专用的 Nginx 用户,提高安全性:
useradd -M -s /sbin/nologin nginx
4.3 编译安装 Nginx
下载 Nginx 源码并编译安装:
# 解压源码包
tar zxvf nginx-1.12.0.tar.gz
# 进入源码目录
cd nginx-1.12.0
# 配置编译参数
./configure --prefix=/usr/local/nginx --user=nginx --group=nginx
# 编译并安装
make && make install
# 创建软链接,方便命令行调用
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
# 验证安装结果
ls -l /usr/local/sbin/nginx
4.4 配置 Nginx 代理
在 nginx01 和 nginx02 上配置 Nginx 代理参数,指向后端 Web 服务器:
vim /usr/local/nginx/conf/nginx.conf
修改 http 块内容如下:
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream webserver {
server 192.168.10.103:8081;
server 192.168.10.104:8082;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://webserver;
}
}
}
五、Keepalived 主从架构搭建
5.1 Nginx01 上的 Keepalived 配置
安装 Keepalived 并配置为主节点:
# 安装keepalived
yum -y install keepalived
# 修改配置文件
vim /etc/keepalived/keepalived.conf
配置内容如下:
! Configuration File for keepalived
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_01
vrrp_skip_check_adv_addr
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.100
}
track_script {
check_nginx
}
}
5.2 Nginx02 上的 Keepalived 配置
安装 Keepalived 并配置为从节点:
yum -y install keepalived
vim /etc/keepalived/keepalived.conf
配置内容如下:
! Configuration File for keepalived
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_02
vrrp_skip_check_adv_addr
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.100
}
track_script {
check_nginx
}
}
5.3 编写健康检查脚本
在 nginx01 和 nginx02 上创建检查 Nginx 运行状态的脚本:
cd /etc/keepalived/
vim check_nginx.sh
脚本内容如下:
#!/bin/bash
pidof nginx
if [ $? -ne 0 ];then
/etc/init.d/keepalived stop
fi
赋予脚本执行权限:
chmod +x check_nginx.sh
5.4 启动 Keepalived 服务
在 nginx01 和 nginx02 上启动 Keepalived:
systemctl start keepalived
systemctl enable keepalived
5.5 主从架构测试
5.5.1 正常状态测试
在客户端访问 VIP,验证负载均衡效果:
curl 192.168.10.100
# 输出应为test01或test02
5.5.2 故障切换测试
关闭 nginx01 上的 Nginx 服务,模拟主节点故障:
# 停止nginx服务
/usr/local/sbin/nginx -s stop
观察 VIP 是否转移到 nginx02,并验证服务可用性:
# 在nginx02上查看VIP是否存在
ip addr show ens33 | grep 192.168.10.100
# 客户端访问VIP
curl 192.168.10.100
# 此时应能正常返回test01或test02
当 nginx01 恢复后,VIP 会重新转移回 nginx01:
# 启动nginx服务
/usr/local/sbin/nginx
# 等待片刻后,在nginx01上查看VIP
ip addr show ens33 | grep 192.168.10.100
六、Nginx 双主架构搭建
6.1 双主架构介绍
双主架构使用两个 VIP,两台 Nginx 服务器互为主备,同时工作,提高资源利用率。当一台服务器故障时,另一台服务器接管两个 VIP 的请求。
6.2 Nginx01 的双主配置
在 nginx01 上修改 Keepalived 配置,添加第二个 VRRP 实例:
vim /etc/keepalived/keepalived.conf
完整配置如下:
! Configuration File for keepalived
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_01
vrrp_skip_check_adv_addr
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.100
}
track_script {
check_nginx
}
}
vrrp_instance VI_2 {
state BACKUP
interface ens33
virtual_router_id 52
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.200
}
track_script {
check_nginx
}
}
6.3 Nginx02 的双主配置
在 nginx02 上修改 Keepalived 配置,与 nginx01 形成互补:
vim /etc/keepalived/keepalived.conf
完整配置如下:
! Configuration File for keepalived
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_02
vrrp_skip_check_adv_addr
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.100
}
track_script {
check_nginx
}
}
vrrp_instance VI_2 {
state MASTER
interface ens33
virtual_router_id 52
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.200
}
track_script {
check_nginx
}
}
6.4 双主架构测试
6.4.1 正常状态测试
在客户端访问两个 VIP,验证负载均衡效果:
curl 192.168.10.100
# 输出应为test01或test02
curl 192.168.10.200
# 输出应为test01或test02
6.4.2 故障切换测试
关闭 nginx01 上的 Nginx 服务,模拟故障:
/usr/local/sbin/nginx -s stop
观察两个 VIP 是否都转移到 nginx02:
# 在nginx02上查看VIP
ip addr show ens33 | grep 192.168.10.100
ip addr show ens33 | grep 192.168.10.200
# 客户端访问两个VIP
curl 192.168.10.100
curl 192.168.10.200
# 此时两个VIP应都能正常返回结果
当 nginx01 恢复后,VIP 会按配置转移回各自的主节点。
6.5 非抢占模式配置
如需配置 master 重新接入后不抢占 VIP,需在配置中添加 nopreempt 参数:
# 在需要设置非抢占的实例中添加
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.100
}
track_script {
check_nginx
}
nopreempt # 添加非抢占参数
}
注意:state 必须设置为 BACKUP,MASTER 角色不能设置 nopreempt 参数。
七、架构对比与总结
7.1 主从架构与双主架构对比
指标 | 主从架构 | 双主架构 |
---|---|---|
VIP 数量 | 1 个 | 2 个 |
服务器利用率 | 只有 master 工作,backup 闲置 | 两台服务器同时工作 |
资源消耗 | 较低 | 较高 |
适用场景 | 服务器资源有限,对高可用性要求较高 | 服务器资源充足,追求资源利用率和高可用性 |
故障影响 | 一台服务器故障,服务不受影响 | 一台服务器故障,另一台服务器负载增加 |
7.2 高可用架构关键点
- 健康检查机制:通过脚本实时监控 Nginx 状态,确保故障及时发现
- VRRP 协议:实现 VIP 的自动切换,保证服务连续性
- 配置一致性:主从服务器配置需保持一致,避免切换失败
- 测试验证:定期进行故障切换测试,确保架构可靠性
7.3 进一步优化方向
- 添加日志记录:在检查脚本中添加日志,方便故障排查
# 修改检查脚本
vim /etc/keepalived/check_nginx.sh
#!/bin/bash
LOG_FILE="/var/log/keepalived/nginx_check.log"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Checking Nginx status..." >> $LOG_FILE
pidof nginx
if [ $? -ne 0 ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Nginx process not found, stopping keepalived..." >> $LOG_FILE
/etc/init.d/keepalived stop
else
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Nginx is running normally." >> $LOG_FILE
fi
# 创建日志目录并赋予权限
mkdir -p /var/log/keepalived
chmod 755 /var/log/keepalived
chown nginx:nginx /var/log/keepalived -R
- 配置邮件告警:当 Keepalived 发生切换时发送邮件通知
# 修改keepalived.conf配置文件
vim /etc/keepalived/keepalived.conf
global_defs {
notification_email {
admin@example.com # 替换为实际邮箱
}
notification_email_from keepalived@example.com # 替换为实际发件邮箱
smtp_server 192.168.1.1 # 替换为实际SMTP服务器IP
smtp_connect_timeout 30
router_id LVS_01
# 其他配置保持不变...
}
- 优化 Nginx 配置:添加健康检查和连接超时参数
vim /usr/local/nginx/conf/nginx.conf
upstream webserver {
server 192.168.10.103:8081 max_fails=3 fail_timeout=30s;
server 192.168.10.104:8082 max_fails=3 fail_timeout=30s;
keepalive 32; # 保持长连接数
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://webserver;
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 10s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
}
}
- 添加磁盘监控:避免因磁盘满导致服务异常
# 创建磁盘监控脚本
vim /usr/local/sbin/disk_monitor.sh
#!/bin/bash
LOG_FILE="/var/log/disk_monitor.log"
THRESHOLD=90 # 磁盘使用率阈值(%)
df -h | grep -v tmpfs | while read line; do
device=$(echo $line | awk '{print $1}')
if [ "$device" != "Filesystem" ]; then
usage=$(echo $line | awk '{print $5}' | tr -d '%')
if [ $usage -ge $THRESHOLD ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] WARNING: $device disk usage reaches $usage%, please check!" >> $LOG_FILE
# 发送邮件告警
echo "磁盘 $device 使用率达到 $usage%,请及时检查!" | mail -s "磁盘告警" admin@example.com
fi
fi
done
# 赋予执行权限
chmod +x /usr/local/sbin/disk_monitor.sh
# 添加定时任务,每10分钟检查一次
crontab -e
*/10 * * * * /usr/local/sbin/disk_monitor.sh
- 配置 Keepalived 优先级动态调整:根据服务器负载动态调整优先级
# 创建负载监控脚本
vim /etc/keepalived/load_monitor.sh
#!/bin/bash
LOG_FILE="/var/log/keepalived/load_monitor.log"
VIP1="192.168.10.100"
VIP2="192.168.10.200"
INTERFACE="ens33"
MAX_LOAD=4.0 # 最大负载阈值
# 获取1分钟系统负载
load=$(cat /proc/loadavg | awk '{print $1}')
echo "[$(date '+%Y-%m-%d %H:%M:%S')] System load: $load" >> $LOG_FILE
if [ $(echo "$load > $MAX_LOAD" | bc -l) -eq 1 ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] WARNING: System load too high, reducing keepalived priority." >> $LOG_FILE
# 降低Keepalived优先级(需根据实际角色调整)
if [ $(cat /etc/keepalived/keepalived.conf | grep "state MASTER" | wc -l) -ge 1 ]; then
# 如果是主节点,降低优先级使其成为从节点
sed -i 's/priority 100/priority 80/g' /etc/keepalived/keepalived.conf
systemctl restart keepalived
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Keepalived priority reduced to 80, service migrated." >> $LOG_FILE
fi
else
# 负载正常时恢复优先级
if [ $(cat /etc/keepalived/keepalived.conf | grep "priority 80" | wc -l) -ge 1 ]; then
sed -i 's/priority 80/priority 100/g' /etc/keepalived/keepalived.conf
systemctl restart keepalived
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Keepalived priority restored to 100." >> $LOG_FILE
fi
fi
# 赋予执行权限
chmod +x /etc/keepalived/load_monitor.sh
# 添加定时任务,每5分钟检查一次
crontab -e
*/5 * * * * /etc/keepalived/load_monitor.sh
7.4 常见故障排查
VIP 无法正常绑定
- 检查网络接口名称是否正确(
interface ens33
需与实际接口一致) - 确认两台服务器的
virtual_router_id
是否相同 - 检查防火墙是否允许 VRRP 协议通信(UDP 112 端口)
- 执行
ip addr show
查看 VIP 是否被正确绑定
- 检查网络接口名称是否正确(
Nginx 故障时 Keepalived 未切换
- 检查
check_nginx.sh
脚本是否有执行权限 - 通过
/var/log/messages
查看 Keepalived 日志,确认是否检测到 Nginx 故障 - 手动执行
check_nginx.sh
脚本,查看是否能正确停止 Keepalived - 确认
track_script
配置是否正确关联到检查脚本
- 检查
双主架构中 VIP 抢占异常
- 检查是否配置了
nopreempt
参数且state
为BACKUP
- 确认两台服务器的优先级配置是否正确(主节点优先级高于从节点)
- 检查网络延迟是否过高,导致心跳包丢失
- 检查是否配置了
Nginx 代理返回 502 错误
- 检查后端 Web 服务器是否正常运行
- 查看 Nginx 错误日志(
/usr/local/nginx/logs/error.log
) - 确认
upstream
配置中的服务器 IP 和端口是否正确 - 检查 Web 服务器防火墙是否允许 Nginx 服务器访问
7.5 生产环境最佳实践
硬件配置建议
- Nginx 服务器:4 核 CPU、8GB 内存、100GB SSD 硬盘
- Web 服务器:根据业务需求调整,建议至少 2 核 CPU、4GB 内存
- 网络:千兆网卡,交换机支持组播转发
监控体系搭建
- 使用 Prometheus+Grafana 监控 Nginx 和 Keepalived 状态
- 监控指标包括:CPU 使用率、内存占用、磁盘空间、网络流量、Nginx 请求数、Keepalived 状态
- 设置告警阈值,当指标异常时及时通知运维人员
定期维护计划
- 每周进行一次架构切换测试,确保故障切换正常
- 每月更新服务器系统补丁,修复安全漏洞
- 每季度检查硬件状态,更换老化部件
- 每年重新评估架构性能,根据业务增长调整配置
灾备方案扩展
- 跨机房部署 Nginx+Keepalived 架构,实现异地容灾
- 使用 DNS 轮询结合 Keepalived,实现多机房流量分发
- 对重要数据进行异地备份,确保数据可靠性
7.6 架构扩展方案
增加 Nginx 服务器节点
- 在双主架构基础上,添加更多 Nginx 节点,形成多主多备架构
- 使用 DNS 轮询或更高层的负载均衡设备分发流量到多个 VIP
- 调整 Keepalived 配置,实现多节点之间的故障切换
集成 Haproxy 实现四层负载均衡
- 在 Nginx 前端部署 Haproxy,实现 TCP 层负载均衡
- Haproxy 监控 Nginx 服务器状态,当某台 Nginx 故障时自动剔除
- 配置 Haproxy 的健康检查机制,确保流量只转发到正常工作的 Nginx 节点
容器化部署
- 将 Nginx 和 Keepalived 打包为 Docker 容器,便于部署和管理
- 使用 Kubernetes 管理容器集群,实现自动扩缩容和故障转移
- 通过 Service 和 Ingress 资源暴露服务,实现高可用架构