Skip to content

Keepalived 部署完全指南:VIP漂移、主备切换与健康检查脚本

Keepalived VIP 漂移示意图

前四章,我们完成了架构设计、原理学习、健康检查服务开发和 Nginx 配置。现在万事俱备,只欠最后一个组件——Keepalived

本章将正式部署 Keepalived,配置 VRRP 主备切换,让 VIP 真正"漂"起来。到本章结束时,你将拥有一个完整的高可用入口:VIP 自动漂移 + Nginx 反向代理 + 健康检查服务。

一、Keepalived 在这个架构中的角色

回顾一下完整架构:

Keepalived 在这个架构中承担了两个关键职责:

职责说明
VIP 管理通过 VRRP 协议,在三台机器之间维护 VIP 的归属
故障切换检测到 Master 节点故障时,自动将 VIP 漂移到备用节点

💡 第 4 篇我们配置了 Nginx 的被动检查(摘除故障 Master 服务),而 Keepalived 负责的是VIP 漂移(入口 IP 切换到备用机器)。两者配合,形成完整的故障防护链。

二、环境准备:安装 Keepalived

在开始配置之前,需要在三台机器(192.168.0.201192.168.0.202192.168.0.203)上分别完成 Keepalived 的安装。

2.1 安装 Keepalived

bash
# 更新软件包索引
sudo apt update

# 安装 Keepalived
sudo apt install -y keepalived

# 查看版本,确认安装成功
keepalived -v
# 输出:Keepalived v2.2.7 (03/15,2022)

2.2 验证 Keepalived 安装

bash
# 检查 Keepalived 是否安装成功
which keepalived
# /usr/sbin/keepalived

# 查看 Keepalived 版本详情
keepalived -v

2.3 确认配置文件位置

bash
# Keepalived 的默认配置文件路径
ls -la /etc/keepalived/
# 默认只有一个 keepalived.conf 示例文件(可能为空)

💡 本节目标:三台机器全部完成 Keepalived 安装,为后续的 VRRP 配置做好准备。

三、Keepalived 基础配置

3.1 三台机器的配置差异

和 Nginx 一样,三台机器的 Keepalived 配置大同小异,核心差异在于:

配置项node1(192.168.0.201)node2(192.168.0.202)node3(192.168.0.203)
stateMASTERBACKUPBACKUP
priority1009080
router_idKEEPALIVED_NODE1KEEPALIVED_NODE2KEEPALIVED_NODE3

在三台机器上分别创建配置文件:

bash
sudo vim /etc/keepalived/keepalived.conf
bash
# /etc/keepalived/keepalived.conf

global_defs {
    router_id KEEPALIVED_NODE1      # 节点标识,每台机器不同
    script_user root
    enable_script_security
}

vrrp_instance VI_1 {
    state MASTER                    # 初始角色:主
    interface eth0                  # 监听的网卡(根据实际情况调整)
    virtual_router_id 51            # VRID,同一集群必须一致
    priority 100                    # 优先级:主比备高
    advert_int 1                    # 心跳间隔:1秒

    authentication {
        auth_type PASS
        auth_pass 1234              # 简单认证,防止恶意加入
    }

    virtual_ipaddress {
        192.168.0.200/24 dev eth0 label eth0:vip
    }
}
bash
# /etc/keepalived/keepalived.conf

global_defs {
    router_id KEEPALIVED_NODE2
    script_user root
    enable_script_security
}

vrrp_instance VI_1 {
    state BACKUP                    # 初始角色:备
    interface eth0
    virtual_router_id 51
    priority 90                     # 优先级比主低
    advert_int 1

    authentication {
        auth_type PASS
        auth_pass 1234
    }

    virtual_ipaddress {
        192.168.0.200/24 dev eth0 label eth0:vip
    }
}
bash
# /etc/keepalived/keepalived.conf

global_defs {
    router_id KEEPALIVED_NODE3
    script_user root
    enable_script_security
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 80                     # 优先级最低
    advert_int 1

    authentication {
        auth_type PASS
        auth_pass 1234
    }

    virtual_ipaddress {
        192.168.0.200/24 dev eth0 label eth0:vip
    }
}

3.2 配置参数详解

参数说明本次配置值
router_id节点标识,集群内唯一KEEPALIVED_NODE1/2/3
state初始角色,MASTERBACKUP主:MASTER,备:BACKUP
interface监听的网卡,VRRP 心跳发送的接口eth0(根据实际网卡调整)
virtual_router_id虚拟路由器 ID(1-255),同一集群必须一致51
priority优先级(1-255),越高越容易成为 Master主:100,备:90/80
advert_int心跳通告间隔(秒)1
auth_pass认证密码,同一集群必须一致1234
virtual_ipaddress虚拟 IP 地址及网卡别名192.168.0.200/24 dev eth0 label eth0:vip

3.3 检查网卡名称

在配置 interface 之前,先确认机器网卡的实际名称:

bash
# 查看网卡名称
ip addr show

# 或
ip link show

# 常见的网卡名称:
# - eth0(传统命名)
# - ens3、ens4(虚拟化环境)
# - enp0s3、enp0s8(VirtualBox)
# - eno1、eno2(物理机)

如果网卡名称不是 eth0,需要将配置中的 interface eth0dev eth0 替换为实际的网卡名称。

四、启动 Keepalived

4.1 启动服务

在三台机器上分别执行:

bash
# 启动 Keepalived
sudo systemctl start keepalived

# 查看服务状态
sudo systemctl status keepalived

# 设置开机自启
sudo systemctl enable keepalived

4.2 验证 VIP 是否已分配

Master 节点(192.168.0.201) 上查看:

bash
# 查看 VIP 是否已绑定
ip addr show eth0 | grep 192.168.0.200

# 预期输出:
# inet 192.168.0.200/24 scope global eth0:vip

Backup 节点(192.168.0.202) 上查看:

bash
ip addr show eth0 | grep 192.168.0.200

# 预期输出:空(VIP 不在备节点上)

4.3 验证 VIP 可访问性

bash
# 从任意机器 ping VIP
ping -c 3 192.168.0.200

# 预期:能 ping 通

# 通过 VIP 访问健康检查服务
curl http://192.168.0.200/health | jq .

# 预期:返回 node1 的服务信息

此时,VIP 已经可以正常访问了。 客户端访问 192.168.0.200 即可到达 node1。

五、整合健康检查脚本

在生产环境中,我们不仅希望 Keepalived 检测机器是否存活,还要检测 NginxMaster 服务是否正常工作。如果 Nginx 或 Master 服务挂了,Keepalived 应该主动降低当前节点的优先级,让 VIP 漂移到其他健康的节点。

5.1 创建健康检查脚本

在三台机器上创建同样的脚本:

bash
# 1. 检查 Master 服务
cat > /usr/local/bin/check_master.sh << 'EOF'
#!/bin/bash
# 检查 Master 服务是否健康

MASTER_HEALTH_URL="http://127.0.0.1:8080/health"

if curl -f -s -o /dev/null -w "%{http_code}" "$MASTER_HEALTH_URL" | grep -q "200"; then
    exit 0
else
    exit 1
fi
EOF

# 2. 检查 Nginx 是否存活
cat > /usr/local/bin/check_nginx.sh << 'EOF'
#!/bin/bash
# 检查 Nginx 进程是否运行

if pgrep -x "nginx" > /dev/null; then
    exit 0
else
    exit 1
fi
EOF

# 3. 添加执行权限
chmod +x /usr/local/bin/check_master.sh
chmod +x /usr/local/bin/check_nginx.sh

5.2 更新 Keepalived 配置

在三台机器上更新 /etc/keepalived/keepalived.conf,加入健康检查脚本:

bash
sudo vim /etc/keepalived/keepalived.conf

完整的配置如下(三台机器的差异只在 statepriorityrouter_id):

nginx
# /etc/keepalived/keepalived.conf(以 node1 为例)

global_defs {
    router_id KEEPALIVED_NODE1
    script_user root
    enable_script_security
}

# 健康检查脚本定义
vrrp_script check_master { 
    script "/usr/local/bin/check_master.sh"
    interval 3          # 每3秒检查一次 
    weight -30          # 检查失败时,优先级减20 
    fall 2              # 连续失败2次判定为失败 
    rise 2              # 连续成功2次判定为恢复 
} 
vrrp_script check_nginx { 
    script "/usr/local/bin/check_nginx.sh"
    interval 2
    weight -30 
    fall 2
    rise 2
} 

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 {
        192.168.0.200/24 dev eth0 label eth0:vip
    }

    # 关联健康检查脚本
    track_script { 
        check_master 
        check_nginx 
    } 
}

5.3 脚本参数详解

参数作用本次配置值
interval检查间隔(秒)23
weight检查失败时,优先级减少的值-30
fall连续失败多少次后判定为失败2
rise连续成功多少次后判定为恢复2

工作原理:

  • 正常情况下,Master 节点优先级为 100
  • 如果 Master 服务挂了(check_master 失败),优先级降至 70100 - 30
  • 如果 Nginx 也挂了(check_nginx 失败),优先级降至 70100 - 30
  • 如果两个脚本同时失败,优先级降至 40100 - 30 - 30
  • 当优先级低于 Backup 节点(90)时,VIP 自动漂移

⚠️ 为什么 weight-30 而不是 -20-10

因为 node1 的优先级是 100,node2 是 90。要让 node1 的优先级明确低于 node2,至少需要降到 89 以下:

  • weight -10:降到 90,和 node2 平级,不会触发切换
  • weight -20:降到 80,明确低于 90可以触发切换
  • weight -30:降到 70更保险,即使两个脚本同时失败也足够低

我们在实际验证中发现 -10 不会触发切换,所以统一使用 -30 确保可靠性。

5.4 重新加载配置

bash
# 测试配置语法
sudo keepalived -t -f /etc/keepalived/keepalived.conf

# 重新加载配置
sudo systemctl reload keepalived

# 查看服务状态
sudo systemctl status keepalived

六、验证 VIP 漂移

这是最激动人心的环节——模拟故障,让 VIP 真正漂起来。

在开始之前,先打开一个终端窗口,实时监控 Keepalived 日志:

bash
sudo journalctl -u keepalived -f

然后另开一个终端,用于执行故障模拟命令。

6.1 确认当前 Master

在开始故障模拟之前,先确认 VIP 当前在哪个节点上:

bash
ip addr show eth0 | grep 192.168.0.200
# 预期:inet 192.168.0.200/24 scope global eth0:vip
bash
ip addr show eth0 | grep 192.168.0.200
# 预期:(空)

可以看到,VIP 当前在 node1 上。

6.2 场景一:Master 服务故障

操作步骤:

node1 上停止 gateway 服务,模拟业务服务故障:

bash
# 在 node1 上执行
sudo systemctl stop gateway

日志输出:

在日志终端中,你会看到以下输出:

Jun 21 15:01:47 node1 Keepalived_vrrp[937]: Script `check_master` now returning 1
Jun 21 15:01:50 node1 Keepalived_vrrp[937]: VRRP_Script(check_master) failed (exited with status 1)
Jun 21 15:01:50 node1 Keepalived_vrrp[937]: (VI_1) Changing effective priority from 100 to 70
Jun 21 15:01:53 node1 Keepalived_vrrp[937]: (VI_1) Master received advert from 192.168.0.202 with higher priority 90, ours 70
Jun 21 15:01:53 node1 Keepalived_vrrp[937]: (VI_1) Entering BACKUP STATE

日志解读:

时间日志内容含义
15:01:47Script check_master now returning 1健康检查脚本检测到 gateway 服务异常
15:01:50VRRP_Script(check_master) failed连续失败 2 次,确认脚本失败
15:01:50Changing effective priority from 100 to 70node1 优先级从 100 降到 70
15:01:53received advert from 192.168.0.202 with higher priority 90node1 收到 node2 优先级 90 的通告,比自己高
15:01:53Entering BACKUP STATEnode1 主动让出 Master 角色

验证漂移结果:

bash
# 在 node2 上检查
ip addr show eth0 | grep 192.168.0.200
# 预期:inet 192.168.0.200/24 scope global eth0:vip
bash
# 通过 VIP 验证服务可达
curl -s http://192.168.0.200/health | jq .hostname
# 预期:"node2"

恢复与回切:

bash
# 在 node1 上恢复服务
sudo systemctl start gateway

日志中会看到:

Jun 21 15:04:44 node1 Keepalived_vrrp[937]: Script `check_master` now returning 0
Jun 21 15:04:47 node1 Keepalived_vrrp[937]: VRRP_Script(check_master) succeeded
Jun 21 15:04:47 node1 Keepalived_vrrp[937]: (VI_1) Changing effective priority from 70 to 100
Jun 21 15:04:47 node1 Keepalived_vrrp[937]: (VI_1) received lower priority (90) advert from 192.168.0.202 - discarding
Jun 21 15:04:48 node1 Keepalived_vrrp[937]: (VI_1) received lower priority (90) advert from 192.168.0.202 - discarding
Jun 21 15:04:49 node1 Keepalived_vrrp[937]: (VI_1) received lower priority (90) advert from 192.168.0.202 - discarding
Jun 21 15:04:50 node1 Keepalived_vrrp[937]: (VI_1) Entering MASTER STATE

恢复后约 3-6 秒,VIP 回到 node1。

6.3 场景二:Nginx 故障

操作步骤:

node1 上停止 Nginx 服务,模拟代理层故障:

bash
# 在 node1 上执行
sudo systemctl stop nginx

日志输出:

Jun 21 14:54:52 node1 Keepalived_vrrp[1022]: Script `check_nginx` now returning 1
Jun 21 14:54:54 node1 Keepalived_vrrp[1022]: VRRP_Script(check_nginx) failed (exited with status 1)
Jun 21 14:54:54 node1 Keepalived_vrrp[1022]: (VI_1) Changing effective priority from 100 to 70
Jun 21 14:54:57 node1 Keepalived_vrrp[1022]: (VI_1) Master received advert from 192.168.0.202 with higher priority 90, ours 70
Jun 21 14:54:57 node1 Keepalived_vrrp[1022]: (VI_1) Entering BACKUP STATE

日志解读:

时间日志内容含义
14:54:52Script check_nginx now returning 1健康检查脚本检测到 Nginx 异常
14:54:54VRRP_Script(check_nginx) failed连续失败 2 次,确认脚本失败
14:54:54Changing effective priority from 100 to 70node1 优先级从 100 降到 70
14:54:57received advert from 192.168.0.202 with higher priority 90node2 优先级 90 高于当前 70,触发切换
14:54:57Entering BACKUP STATEnode1 让出 Master 角色

验证漂移结果:

bash
# 在 node2 上检查
ip addr show eth0 | grep 192.168.0.200
# 预期:inet 192.168.0.200/24 scope global eth0:vip

恢复与回切:

bash
# 在 node1 上恢复 Nginx
sudo systemctl start nginx
# VIP 会自动回到 node1

日志中会看到:

Jun 21 14:55:46 node1 Keepalived_vrrp[1022]: Script `check_nginx` now returning 0
Jun 21 14:55:48 node1 Keepalived_vrrp[1022]: VRRP_Script(check_nginx) succeeded
Jun 21 14:55:48 node1 Keepalived_vrrp[1022]: (VI_1) Changing effective priority from 70 to 100
Jun 21 14:55:48 node1 Keepalived_vrrp[1022]: (VI_1) received lower priority (90) advert from 192.168.0.202 - discarding
Jun 21 14:55:49 node1 Keepalived_vrrp[1022]: (VI_1) received lower priority (90) advert from 192.168.0.202 - discarding
Jun 21 14:55:50 node1 Keepalived_vrrp[1022]: (VI_1) received lower priority (90) advert from 192.168.0.202 - discarding
Jun 21 14:55:51 node1 Keepalived_vrrp[1022]: (VI_1) Entering MASTER STATE

6.4 场景三:整机宕机

操作步骤:

node1 上执行关机,模拟整机故障:

bash
# 在 node1 上执行(仅限测试!)
sudo shutdown -h now

⚠️ 注意:关机前请确保 node1 上没有其他重要服务在运行。

预期结果:

node1 关机后,Keepalived 心跳中断,node2 在大约 3-6 秒后接管 VIP。

验证漂移结果:

bash
# 在 node2 上检查
ip addr show eth0 | grep 192.168.0.200
# 预期:inet 192.168.0.200/24 scope global eth0:vip

6.5 验证结论汇总

故障场景触发命令日志关键词VIP 漂移目标恢复时间
Master 服务故障systemctl stop gatewaycheck_master failedChanging priority 100→70Entering BACKUPnode2~3-6 秒
Nginx 故障systemctl stop nginxcheck_nginx failedChanging priority 100→70Entering BACKUPnode2~3-6 秒
整机宕机shutdown -h now(心跳中断)node2~3-6 秒
服务恢复systemctl start gatewaycheck_master succeededChanging priority 70→100Entering MASTERnode1~10-15 秒

至此,我们拥有了一个完整的高可用入口:

  • 入口高可用:VIP 192.168.0.200 自动漂移
  • 代理高可用:Nginx 多节点 + 被动检查
  • 业务高可用:Master 服务多节点 + 健康检查

七、常用运维命令

7.1 查看 Keepalived 日志

bash
# 实时查看 Keepalived 日志
sudo journalctl -u keepalived -f

# 查看最近 50 行日志
sudo journalctl -u keepalived -n 50

# 查看系统日志中的 Keepalived 记录
sudo tail -f /var/log/syslog | grep keepalived

在故障切换时,日志中会看到类似信息:

# Master 节点日志:
Keepalived_vrrp[12345]: VRRP_Instance(VI_1) Received lower prio advert, forcing new election

# Backup 节点日志:
Keepalived_vrrp[12345]: VRRP_Instance(VI_1) Transition to MASTER STATE
Keepalived_vrrp[12345]: VRRP_Instance(VI_1) Entering MASTER STATE
Keepalived_vrrp[12345]: VRRP_Instance(VI_1) setting VIP 192.168.0.200

7.2 查看 VIP 归属

bash
# 查看 VIP 当前在哪台机器
ip addr show eth0 | grep 192.168.0.200

# 或使用更详细的命令
ip addr show label eth0:vip

7.3 查看 Keepalived 进程状态

bash
# 查看 Keepalived 进程
ps aux | grep keepalived

# 查看 Keepalived 主进程 PID
sudo cat /var/run/keepalived.pid

7.4 手动触发 VIP 切换

bash
# 将当前 Master 降级为 Backup(用于测试)
sudo systemctl stop keepalived

# 查看其他节点是否接管 VIP
# 重新启动 Keepalived 后,会重新抢占(如果优先级更高)
sudo systemctl start keepalived

八、常见问题与解决方案

Q1:启动 Keepalived 后,VIP 没有出现?

可能原因:

  1. 网卡名称不对
  2. 配置文件语法错误
  3. 三台机器的 virtual_router_idauth_pass 不一致

解决方案:

bash
# 1. 查看 Keepalived 日志
sudo journalctl -u keepalived -f

# 2. 检查网卡名称
ip addr show

# 3. 测试配置文件语法
sudo keepalived -t -f /etc/keepalived/keepalived.conf

# 4. 检查防火墙是否放行 VRRP 组播
sudo iptables -L -n | grep 224.0.0.18

Q2:VIP 频繁漂移(抖动)?

可能原因:

  1. 网络不稳定,心跳丢包
  2. 健康检查脚本执行太频繁或太重
  3. 三台机器的 advert_int 不一致

解决方案:

  • 确保三台机器的 advert_int 一致
  • 适当增加 fallrise 的值(如 fall 3rise 3
  • 检查网络是否稳定

Q3:健康检查脚本没有生效?

可能原因:

  1. track_script 块缺失或放错位置
  2. 脚本没有执行权限
  3. script_user 未配置

解决方案:

首先确认日志中是否有警告:

bash
sudo journalctl -u keepalived | grep "not used"

如果看到 Warning - script check_master is not used,说明 track_script 没有正确配置。

确保配置结构正确:

bash
# ✅ 正确:track_script 在 vrrp_instance 块内部
vrrp_instance VI_1 {
    state MASTER
    # ... 其他配置 ...

    track_script {
        check_master
        check_nginx
    }
}

# ❌ 错误:track_script 在 vrrp_instance 块外面
track_script {
    check_master
}

检查脚本权限:

bash
sudo chmod +x /usr/local/bin/check_master.sh
sudo chmod +x /usr/local/bin/check_nginx.sh

Q4:weight 设置多少合适?

weight 的核心原则是:任何单一故障都足以让 Master 的优先级明确低于所有 Backup 节点。

节点priority需要的 weight说明
node1100> 10100 - weight < 90 → weight > 10
node290--
node380--

推荐配置: 使用 -30,留出足够余量,即使两个脚本同时失败也能正常切换。

Q5:三台机器的网卡名称不一样怎么办?

通常在同一批服务器上,网卡名称是相同的。如果不一致,需要为每台机器单独调整 interfacedev 参数。

bash
# 在每台机器上单独确认网卡名称
ip addr show

# 然后分别修改配置文件中的 interface 和 dev
interface eth0
virtual_ipaddress {
    192.168.0.200/24 dev eth0 label eth0:vip
}

九、小结

本章完成了 Keepalived 的部署和 VIP 漂移配置,核心要点:

  1. 环境准备:三台机器安装 Keepalived
  2. 基础配置state + priority + virtual_ipaddress
  3. 健康检查脚本:检查 Master 服务和 Nginx 是否存活
  4. 脚本整合:通过 track_script 关联健康检查
  5. 故障验证:三种场景验证 VIP 自动漂移

到现在为止,我们完整搭建了一个生产级的高可用入口:

产品 A → VIP (192.168.0.200) → Keepalived 管理漂移 → Nginx 反向代理 → Master 集群

下一章,我们将进行四大故障场景的完整演练,并提供一个自动化的验证脚本。


💡 本文是《分布式高可用入口架构实战系列》第 5 篇

最后更新2026/06/21 16:32
如果你觉得这篇文章有帮助,或者想聊聊技术、工作,欢迎通过下面方式联系我:
contact fishfinal