Nginx 如何实现高可用?(Keepalived + VIP)
简化版
单台 Nginx 是单点,一挂整个入口就瘫了。要高可用,经典方案是 Keepalived + VIP(虚拟 IP):部署两台 Nginx(主 + 备),用 Keepalived 通过 VRRP 协议维护一个虚拟 IP(VIP),正常时 VIP 绑在主 Nginx 上、对外提供服务;Keepalived 之间互发心跳,一旦主 Nginx 宕机,备机检测到后自动把 VIP 抢过来(漂移),接管流量。对客户端来说始终访问同一个 VIP,故障切换无感知,从而消除单点。
详细版
架构:
VIP: 192.168.1.100(对外唯一入口)
│
┌─────────────┴─────────────┐
Nginx 主(MASTER) Nginx 备(BACKUP)
Keepalived Keepalived
持有 VIP,提供服务 监听主的心跳,随时待命
│ │
└──────── 后端服务集群 ───────┘
工作原理:
- VRRP 协议:Keepalived 用 VRRP 在主备之间选举、维护 VIP 归属。
- 心跳检测:主备之间定期发心跳。主机正常时持有 VIP。
- 故障转移:主机宕机(心跳消失)→ 备机升为主、接管 VIP(VIP 漂移到备机)→ 继续服务。
- VIP 对外不变:客户端/DNS 始终指向 VIP,切换对外透明。
进阶:Keepalived 可配合脚本检测 Nginx 进程本身是否存活(不只是机器存活),Nginx 挂了也触发切换。
完整版教学
一、为什么需要 Nginx 高可用
Nginx 通常是整个系统的流量入口——所有外部请求都先经过它。如果只部署一台 Nginx,那么这台机器一旦宕机(硬件故障、网络断、进程崩溃),整个网站/服务就完全不可访问,即使后端服务器都好好的也没用。这就是单点故障(SPOF)。
要消除这个单点,就得部署多台 Nginx,并保证「一台挂了,另一台能立刻顶上,且对客户端透明」。难点在于:客户端/DNS 配置的是一个固定地址,怎么让这个地址在多台 Nginx 之间「灵活切换」?答案是 Keepalived + VIP。
二、核心概念:VIP(虚拟 IP)
VIP(Virtual IP,虚拟 IP) 是一个不固定绑在某台物理机上的、可以在多台机器间「漂移」的 IP 地址。
- 对外,客户端/DNS 只认这一个 VIP(如
192.168.1.100),把它当作 Nginx 的地址来访问。 - 内部,这个 VIP 实际绑定在当前的主 Nginx 机器上。主机提供服务。
- 当主机挂了,VIP 会漂移到备机上——备机接过这个 IP,开始响应发往 VIP 的请求。
关键在于:VIP 对外始终不变,但它背后对应的物理机可以切换。客户端完全感知不到背后换了机器,它只知道「访问 192.168.1.100 一直有响应」。
三、Keepalived 与 VRRP 协议
Keepalived 是实现 VIP 漂移和故障检测的软件,它基于 VRRP(Virtual Router Redundancy Protocol,虚拟路由冗余协议) 工作:
- 每台 Nginx 上都装 Keepalived,配置成 MASTER(主) 或 BACKUP(备),并设置优先级。
- Keepalived 之间通过 VRRP 协议定期互发心跳(组播),宣告「我还活着,我的优先级是多少」。
- 优先级最高的存活节点持有 VIP,成为 MASTER 对外服务。
- BACKUP 节点静静监听 MASTER 的心跳,随时待命。
四、故障转移的完整过程
- 正常状态:主 Nginx(MASTER)持有 VIP,对外提供服务;备 Nginx(BACKUP)监听主的 VRRP 心跳。
- 主机故障:主 Nginx 宕机(机器挂了/网络断),它的 VRRP 心跳消失。
- 备机检测到:BACKUP 在一定时间内收不到 MASTER 的心跳,判定主机已故障。
- VIP 漂移:BACKUP 把自己升级为 MASTER,通过发送 ARP 广播告知网络「VIP 现在对应我的 MAC 地址了」,于是发往 VIP 的流量转到备机。
- 备机接管服务:客户端对 VIP 的请求现在由原备机处理,服务继续,用户无感知。
- 主机恢复:如果原主机修好重新上线,根据配置(是否抢占 preempt),可能重新抢回 VIP成为 MASTER,或让当前 MASTER 继续。
整个过程自动完成,通常几秒内切换,实现了 Nginx 的高可用。
五、进阶:检测 Nginx 进程,而非只看机器
一个常见的坑:Keepalived 默认只检测机器/网络是否存活(心跳还在),但如果机器活着、Nginx 进程却崩了,Keepalived 以为主机正常、不切换,结果 VIP 还在主机上但 Nginx 已经不工作了——服务照样不可用。
解决:给 Keepalived 配置一个健康检查脚本(vrrp_script),定期检测 Nginx 进程本身是否存活(如 pidof nginx 或探测端口)。如果检测到 Nginx 进程挂了,就主动降低本机优先级或触发切换,让 VIP 漂移到备机。这样才能覆盖「机器活、进程死」的情况。
更完整的高可用还包括:主备之上再用 LVS/DNS 轮询/云负载均衡(SLB) 做多层负载和容灾;后端服务本身也集群化。Keepalived+VIP 解决的是入口 Nginx 这一层的单点问题。
六、常见误区与追问
| 考点 | 正确口径 |
|---|---|
| 高可用目标 | 避免单台 Nginx 故障导致入口不可用 |
| Keepalived | 基于 VRRP 漂移 VIP |
| 切换逻辑 | 主节点故障,备节点接管 VIP |
client -> VIP
VIP on nginx-A(master)
nginx-A health check fails
keepalived moves VIP to nginx-B(backup)
client -> same VIP -> nginx-B
Keepalived 解决入口 IP 漂移,不解决后端应用是否健康,二者都要检查。
- 误区:Nginx 配 upstream 就高可用了。 upstream 解决后端负载,Nginx 自身入口仍可能单点。
- 误区:Keepalived 能自动修复所有服务问题。 它只负责 VIP 漂移和健康脚本触发,服务异常原因仍要处理。
- 误区:主备切换对所有连接完全无感。 VIP 漂移后新连接可恢复,已有 TCP 连接可能中断。
- 追问:VRRP 做了什么? 多台机器竞选虚拟路由器,Master 持有 VIP,故障后 Backup 接管。
- 追问:健康检查脚本要查什么? 至少检查 Nginx 进程、端口、关键 upstream 或本机转发能力。
- 追问:脑裂怎么防? 依赖可靠心跳、合理优先级、抢占策略、单播配置和外部监控告警。
七、加强记忆
Nginx 单点故障用 Keepalived + VIP(虚拟 IP) 解决:部署主 + 备两台 Nginx,Keepalived 基于 VRRP 协议维护一个对外不变的 VIP——正常时 VIP 绑在主机、主机服务,主备间互发心跳;主机宕机(心跳消失)→ 备机升主、把 VIP 漂移过来(发 ARP 广播)接管流量,对客户端透明。进阶要配健康检查脚本检测 Nginx 进程本身(防「机器活但进程死」不切换)。核心:VIP 对外不变、背后物理机可切换、心跳触发故障转移。口诀:双机主备、VIP 漂移、心跳切换、脚本查进程。