从零构建高可用Nginx集群:负载均衡、健康检查与动态上游配置详解

大家好,我是33blog的技术博主。在今天的教程里,我将和大家一起,从零开始搭建一个具备高可用特性的Nginx集群。这不仅仅是简单地把几个Nginx实例堆起来,而是要真正实现负载均衡、自动健康检查,甚至能动态更新后端服务器列表。过程中我会分享一些我踩过的坑和实战心得,希望能帮你少走弯路。
一、 环境准备与基础架构规划
在动手之前,我们先明确目标架构。我们将构建一个经典的两层结构:
- 负载均衡层:由至少两台Nginx服务器组成,使用Keepalived实现虚拟IP(VIP)漂移,确保入口高可用。
- 应用服务器层:由多台后端Web服务器(这里用Nginx模拟应用)组成,由负载均衡器进行流量分发。
我准备了三台CentOS 7虚拟机,IP分别为 192.168.1.10 (nginx-lb-01), 192.168.1.11 (nginx-lb-02), 192.168.1.100 (web-01), 192.168.1.101 (web-02)。虚拟VIP计划使用 192.168.1.200。
踩坑提示:生产环境请务必确保服务器间时钟同步(使用NTP),否则健康检查等基于时间的逻辑可能会出问题。
二、 部署与配置后端Web服务器
我们先快速搭建两个简单的后端服务,以便后续测试负载均衡效果。
在 web-01 和 web-02 上执行:
# 安装Nginx
yum install -y nginx
# 创建用于区分的首页(分别修改两台机器)
# 在 web-01 上:
echo "<h1>Hello from Backend Server 01</h1>" > /usr/share/nginx/html/index.html
# 在 web-02 上:
echo "<h1>Hello from Backend Server 02</h1>" > /usr/share/nginx/html/index.html
# 启动并设置开机自启
systemctl start nginx
systemctl enable nginx
# 暂时关闭防火墙或开放80端口(根据你的安全策略调整)
systemctl stop firewalld # 仅为实验方便,生产环境请配置规则
访问两台机器的IP,确认页面能正常显示不同内容。我们的“应用”就准备好了。
三、 配置负载均衡器Nginx(主/备)
现在在 nginx-lb-01 和 nginx-lb-02 上安装并配置Nginx作为负载均衡器。
# 在两台负载均衡器上都执行
yum install -y nginx
接下来是核心配置。编辑 /etc/nginx/nginx.conf 或在 /etc/nginx/conf.d/ 下创建新文件,如 upstream.conf:
# 定义上游服务器组,名称为 backend_servers
upstream backend_servers {
# 默认使用轮询(round-robin)算法
# weight 参数可以设置权重,权重越高分配的请求越多
server 192.168.1.100:80 weight=1 max_fails=3 fail_timeout=30s;
server 192.168.1.101:80 weight=1 max_fails=3 fail_timeout=30s;
# 可选的负载均衡算法:
# least_conn; # 最少连接数
# ip_hash; # 基于客户端IP的哈希,实现会话保持
}
server {
listen 80;
server_name _; # 监听所有域名,生产环境请替换为具体域名
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_connect_timeout 5s;
proxy_read_timeout 60s;
}
# 可选:添加一个状态检查页面(需要安装nginx-module-http-stub-status)
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
allow 192.168.1.0/24; # 允许内网访问
deny all;
}
}
配置完成后,检查语法并重启Nginx:
nginx -t
systemctl restart nginx
systemctl enable nginx
现在,分别访问 nginx-lb-01 和 nginx-lb-02 的IP,刷新页面,你应该能看到请求被轮询分发到了 web-01 和 web-02 上,页面内容交替出现。基础的负载均衡已经生效!
实战经验:max_fails 和 fail_timeout 参数构成了被动的健康检查。当Nginx在 fail_timeout 时间内连续遇到 max_fails 次连接失败,就会将该服务器标记为不可用,并在 fail_timeout 时间内不再向其分发请求。
四、 实现高可用:使用Keepalived配置VIP
目前我们有两个负载均衡器,但用户需要记住两个IP。我们需要一个统一的入口(VIP),并在主节点故障时自动切换到备用节点。
在两台负载均衡器上安装Keepalived:
yum install -y keepalived
配置Keepalived。主节点 (nginx-lb-01) 的配置文件 /etc/keepalived/keepalived.conf:
vrrp_instance VI_1 {
state MASTER # 初始状态,主节点设为MASTER,备节点设为BACKUP
interface ens33 # 注意!这里替换成你服务器的实际网卡名(使用 ip a 命令查看)
virtual_router_id 51 # 虚拟路由ID,同一组集群必须相同,范围0-255
priority 100 # 优先级,主节点(如100)应高于备节点(如90)
advert_int 1 # 心跳检查间隔,单位秒
authentication {
auth_type PASS
auth_pass 1111 # 认证密码,同一组集群必须相同
}
virtual_ipaddress {
192.168.1.200/24 # 定义的虚拟IP(VIP)
}
}
备节点 (nginx-lb-02) 的配置文件,主要修改 state 和 priority:
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.1.200/24
}
}
踩大坑预警:interface 配置错误是Keepalived无法飘移VIP的最常见原因!务必使用 ip a 或 ifconfig 确认你的网卡名称,可能是 eth0, ens160, enp0s3 等。
启动Keepalived并设置开机自启:
systemctl start keepalived
systemctl enable keepalived
检查VIP是否在主节点(nginx-lb-01)上生效:
ip a show ens33
你应该能看到类似 inet 192.168.1.200/24 scope global secondary ens33 的行。现在,访问 http://192.168.1.200,负载均衡应该正常工作。
高可用测试:模拟主负载均衡器故障。
# 在 nginx-lb-01 (主) 上执行
systemctl stop keepalived
# 或者直接关闭机器
等待几秒后,在备节点 nginx-lb-02 上执行 ip a show ens33,你会发现VIP已经飘移过来了!此时访问 http://192.168.1.200,服务依然可用。恢复 nginx-lb-01 后,VIP通常会因为优先级更高而飘回(取决于 nopreempt 等参数配置)。
五、 进阶:集成主动健康检查与动态上游
基础的被动检查在服务器完全宕机时有效,但对于应用内部错误(如返回500)则无能为力。我们可以使用Nginx商业版带的 health_check 指令,或者更灵活地,使用开源模块 nginx-upsync-module 结合Consul/Etcd实现动态配置。
这里我演示一个更通用的思路:使用Nginx的 match 块和 health_check(如果你使用的是Nginx Plus或编译了相应模块)。对于开源版,一个常见的替代方案是使用 proxy_next_upstream 指令对特定错误码进行重试。
http {
# 定义一个健康检查的匹配条件
match server_ok {
status 200-399;
header Content-Type = text/html; # 可选,检查响应头
body !~ "maintenance"; # 可选,检查响应体不包含特定字符串
}
upstream backend_servers {
zone upstream_backend 64k; # 为共享内存区域,用于健康状态共享
server 192.168.1.100:80;
server 192.168.1.101:80;
# 主动健康检查(Nginx Plus 或 已编译 health_check 模块)
# health_check interval=5s fails=3 passes=2 uri=/health_check match=server_ok;
}
server {
# ... 其他配置同上 ...
location / {
proxy_pass http://backend_servers;
# 当遇到502、503、504、500等错误时,尝试转发到下一个上游服务器
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
proxy_next_upstream_tries 3;
proxy_next_upstream_timeout 30s;
# ... 其他proxy_set_header等配置
}
}
}
对于真正的动态上游(无需重启Nginx即可增删服务器),我强烈推荐研究 nginx-upsync-module 或 lua-nginx-module 结合外部存储(如Consul、Redis)。这允许你通过API或配置中心来管理上游列表,是实现现代微服务架构下弹性伸缩的关键。
六、 总结与监控建议
至此,一个具备基础高可用和负载均衡能力的Nginx集群就搭建完成了。我们实现了:
- 通过Upstream模块进行请求分发。
- 通过Keepalived实现负载均衡器自身的高可用(VIP飘移)。
- 通过被动参数和主动重试机制提升后端容错能力。
要投入生产,你还需要:
- 监控:监控每台Nginx的
stub_status或ngx_http_status_module指标(如活跃连接数、请求速率)。监控Keepalived的VIP状态。 - 日志:妥善分析Nginx的访问日志和错误日志,特别是上游错误(
upstream timed out,no live upstreams)。 - 安全:配置防火墙规则,限制对VIP和管理端口的访问。
- 测试:定期进行故障转移演练,确保高可用流程真正有效。
希望这篇详细的教程能帮助你顺利构建自己的Nginx高可用集群。过程中遇到问题,多查日志,多验证网络和配置,这些都是宝贵的排错经验。Happy scaling!


这个配置在CentOS8上能直接套用吗?网卡名老是搞错 😅