Nginx 学习笔记:Keepalived 高可用实战,Docker 环境搭建与故障转移测试

0 阅读6分钟

一、什么是高可用?为什么需要 Keepalived?

高可用的含义

高可用(High Availability,HA) 指的是通过架构设计,消除单点故障,让服务在某个节点宕机后仍然可以正常对外提供服务。

单点故障问题

在生产环境中,如果只有一台 Nginx 服务器:

用户 ──→ Nginx(单点) ──→ 后端服务

如果这台 Nginx 挂了,整个服务就不可用了。这就是 单点故障(Single Point of Failure)

Keepalived 的解决方案

Keepalived 基于 VRRP(Virtual Router Redundancy Protocol,虚拟路由冗余协议),通过 主备模式 解决单点问题:

                        ┌─ 10.0.2.100 (VIP) ─┐
                        │                     │
用户 ──→ VIP ──────┬──→ Nginx-Master (主)    │
                    │                         │
                    └──→ Nginx-Backup (备)    │
                                              │
                    Master 挂了 → Backup 接管 VIP
  • Master(主节点):正常工作时持有 VIP,对外提供服务
  • Backup(备节点):监听 Master 的心跳,Master 挂了立即接管 VIP
  • VIP(Virtual IP):虚拟 IP,用户通过 VIP 访问服务,不关心背后哪个节点在服务

二、环境准备:WSL + Docker

本教程使用 WSL 上的 Docker 作为实验环境,用两个容器模拟两台服务器。

创建专用网络

为了让两个容器能互相通信并分配固定 IP,先创建一个 Docker 网络:

docker network create --driver bridge --subnet 10.0.2.0/24 ha-network

构建自定义镜像

基础 Nginx 镜像不包含 keepalived,需要自己构建:

FROM nginx:latest
RUN apt update && apt install -y keepalived \
    && apt clean \
    && rm -rf /var/lib/apt/lists/*
docker build -t nginx-keepalived:latest .

三、Keepalived 配置详解

核心配置参数

参数说明
state角色:MASTER(主)或 BACKUP(备)
interface网络接口名,Docker 容器默认为 eth0
virtual_router_id虚拟路由 ID(0-255),主备必须相同
priority优先级(0-255),值越大越优先
advert_int心跳间隔(秒),Master 每隔多久发一次广播
authentication认证方式,防止无关节点加入
virtual_ipaddress虚拟 IP 列表,即 VIP

Master 配置

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1234
    }
    virtual_ipaddress {
        10.0.2.100
    }
}

Backup 配置

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 50
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1234
    }
    virtual_ipaddress {
        10.0.2.100
    }
}

Master 和 Backup 的区别:只有两处不同——state(MASTER / BACKUP)和 priority(100 / 50)。Master 优先级高,正常时持有 VIP;Master 挂了,Backup 自动接管。

关键设计原则

原则说明
主备 priority 必须不同Master 优先级 > Backup,否则谁持有 VIP 不确定
virtual_router_id 必须相同同一个 VRRP 组的节点必须用同一 ID
VIP 配置必须一致主备声明同一个 VIP,切换后对用户透明
authentication 要一致认证不匹配的节点会被忽略

四、实战:启动两台 Nginx 容器

创建容器

# Master 节点
docker run -d \
  --name nginx-master \
  --network ha-network \
  --ip 10.0.2.10 \
  --cap-add=NET_ADMIN \
  --cap-add=NET_BROADCAST \
  --cap-add=NET_RAW \
  nginx-keepalived:latest

# Backup 节点
docker run -d \
  --name nginx-backup \
  --network ha-network \
  --ip 10.0.2.11 \
  --cap-add=NET_ADMIN \
  --cap-add=NET_BROADCAST \
  --cap-add=NET_RAW \
  nginx-keepalived:latest

参数解析

参数含义
-d后台运行(detach),容器启动后在后台运行,不占用终端
--name nginx-master容器名字,方便后续用名字操作(docker exec nginx-master ...
--network ha-network加入指定网络,把容器放到 ha-network 里,和另一个容器互通
--ip 10.0.2.10固定 IP,不给的话 Docker 会自动分配,固定 IP 方便配置 keepalived
--cap-add=NET_ADMIN网络管理权限,keepalived 需要它来添加/删除 VIP
--cap-add=NET_BROADCAST广播权限,VRRP 通过广播发心跳包,通知对端自己还活着
--cap-add=NET_RAW原始套接字权限,keepalived 需要它发送 VRRP 协议数据包
nginx-keepalived:latest使用的镜像,我们刚构建的自定义镜像(nginx + keepalived)

--cap-add 是什么意思?

--cap-add添加 Linux 能力(capability) 的意思。Linux 把 root 的权限拆分成很多小单元,每个叫一个 capability。Docker 容器默认不拥有这些能力——即使容器内是 root,也不能操作网络接口,这是安全设计。

但 keepalived 需要操作网络,所以必须显式授权:

--cap-add=NET_ADMIN     # 授权:管理网络接口(添加/删除 VIP)
--cap-add=NET_BROADCAST # 授权:发送广播包(VRRP 心跳需要)
--cap-add=NET_RAW       # 授权:构造原始网络包(VRRP 协议包需要)

打个比方:默认容器像"住酒店的客人",只能在房间里活动。--cap-add 相当于给了一张"工程部权限卡",允许他去配电房操作网络设备。

配置 Keepalived

将上面的配置文件写入容器:

# Master
docker exec nginx-master sh -c 'cat > /etc/keepalived/keepalived.conf << '\''EOF'\''
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1234
    }
    virtual_ipaddress {
        10.0.2.100
    }
}
EOF'

# Backup
docker exec nginx-backup sh -c 'cat > /etc/keepalived/keepalived.conf << '\''EOF'\''
vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 50
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1234
    }
    virtual_ipaddress {
        10.0.2.100
    }
}
EOF'

验证配置语法

docker exec nginx-master keepalived -t -f /etc/keepalived/keepalived.conf
docker exec nginx-backup keepalived -t -f /etc/keepalived/keepalived.conf

没有报错即表示配置正确。


五、启动 Keepalived

# 启动 Master 的 keepalived
docker exec -d nginx-master keepalived \
  --dont-fork --log-console \
  -f /etc/keepalived/keepalived.conf

# 启动 Backup 的 keepalived
docker exec -d nginx-backup keepalived \
  --dont-fork --log-console \
  -f /etc/keepalived/keepalived.conf

验证 VIP 分配

docker exec nginx-master ip addr show eth0 | grep "inet "
# 输出: 10.0.2.10/24  AND  10.0.2.100/32  ← VIP 在 Master 上

docker exec nginx-backup ip addr show eth0 | grep "inet "
# 输出: 10.0.2.11/24  ← Backup 没有 VIP

预期结果:VIP 10.0.2.100 绑定在 Master 上,Backup 没有。


六、测试故障转移

模拟 Master 宕机

# 杀掉 Master 的 keepalived 进程
docker exec nginx-master kill $(cat /var/run/keepalived.pid)

验证 VIP 漂移

# 查看 Backup 的 IP
docker exec nginx-backup ip addr show eth0 | grep "inet "
# 输出: 10.0.2.11/24  AND  10.0.2.100/32  ← VIP 漂移到 Backup 了!

故障转移流程图解

正常时:
         ┌─ 10.0.2.100 (VIP) ──┐
         │                       │
 用户 ──→│    nginx-master       │  ← priority 100,持有 VIP
         │    nginx-backup       │  ← priority 50,监听中
         └───────────────────────┘

Master 宕机后:
         ┌───────────────────────┐
         │    nginx-master (宕)  │  ← 停止发送心跳
         │                       │
 用户 ──→│    nginx-backup       │  ← 检测到 Master 失联,接管 VIP
         └─ 10.0.2.100 (VIP) ──┘

七、进阶:Nginx 进程级监控

当前配置下,如果 keepalived 还在运行但 nginx 挂了,VIP 不会漂移——因为 keepalived 本身没死,还在发心跳。这时用户通过 VIP 访问会得到错误响应。

解决办法是添加 健康检测脚本,让 keepalived 定期检查 nginx 状态:

检测脚本 /etc/keepalived/scripts/check_nginx.sh

#!/bin/bash
if ! pidof nginx > /dev/null; then
    killall keepalived
    exit 1
fi
exit 0

配置中引入脚本检测

global_defs {
    enable_script_security
    script_user root
}

vrrp_script chk_nginx {
    script "/etc/keepalived/scripts/check_nginx.sh"
    interval 2
    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 1234
    }
    virtual_ipaddress {
        10.0.2.100
    }
    track_script {
        chk_nginx
    }
}

interval 2 表示每 2 秒执行一次脚本。如果 nginx 挂了,脚本杀掉 keepalived 进程,触发 VIP 漂移。

同样的思路,你可以监控任何服务——Redis、MySQL、Tomcat 等——只要在脚本中检测对应进程即可。


八、总结

知识点要点
高可用核心主备模式 + VIP 漂移,消除单点故障
协议VRRP(虚拟路由冗余协议),通过心跳检测存活
核心参数state(角色)、priority(优先级)、virtual_ipaddress(VIP)
故障转移Master 停止心跳 → Backup 检测超时 → Backup 接管 VIP
进程级监控使用 vrrp_script + 检测脚本,nginx 挂了主动触发漂移
适用范围不仅限于 Nginx,任何 TCP 服务都可以用 Keepalived 做高可用

Keepalived 是实现服务高可用的经典方案,配置简单,效果可靠。结合健康检测脚本,可以实现服务级别的自动故障转移,是后端架构入门必须掌握的核心技能之一。