Appearance
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.201、192.168.0.202、192.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 -v2.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) |
|---|---|---|---|
state | MASTER | BACKUP | BACKUP |
priority | 100 | 90 | 80 |
router_id | KEEPALIVED_NODE1 | KEEPALIVED_NODE2 | KEEPALIVED_NODE3 |
在三台机器上分别创建配置文件:
bash
sudo vim /etc/keepalived/keepalived.confbash
# /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 | 初始角色,MASTER 或 BACKUP | 主: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 eth0 和 dev eth0 替换为实际的网卡名称。
四、启动 Keepalived
4.1 启动服务
在三台机器上分别执行:
bash
# 启动 Keepalived
sudo systemctl start keepalived
# 查看服务状态
sudo systemctl status keepalived
# 设置开机自启
sudo systemctl enable keepalived4.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 检测机器是否存活,还要检测 Nginx 和 Master 服务是否正常工作。如果 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.sh5.2 更新 Keepalived 配置
在三台机器上更新 /etc/keepalived/keepalived.conf,加入健康检查脚本:
bash
sudo vim /etc/keepalived/keepalived.conf完整的配置如下(三台机器的差异只在 state、priority、router_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 | 检查间隔(秒) | 2 或 3 |
weight | 检查失败时,优先级减少的值 | -30 |
fall | 连续失败多少次后判定为失败 | 2 |
rise | 连续成功多少次后判定为恢复 | 2 |
工作原理:
- 正常情况下,Master 节点优先级为
100 - 如果 Master 服务挂了(
check_master失败),优先级降至70(100 - 30) - 如果 Nginx 也挂了(
check_nginx失败),优先级降至70(100 - 30) - 如果两个脚本同时失败,优先级降至
40(100 - 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:vipbash
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:47 | Script check_master now returning 1 | 健康检查脚本检测到 gateway 服务异常 |
| 15:01:50 | VRRP_Script(check_master) failed | 连续失败 2 次,确认脚本失败 |
| 15:01:50 | Changing effective priority from 100 to 70 | node1 优先级从 100 降到 70 |
| 15:01:53 | received advert from 192.168.0.202 with higher priority 90 | node1 收到 node2 优先级 90 的通告,比自己高 |
| 15:01:53 | Entering BACKUP STATE | node1 主动让出 Master 角色 |
验证漂移结果:
bash
# 在 node2 上检查
ip addr show eth0 | grep 192.168.0.200
# 预期:inet 192.168.0.200/24 scope global eth0:vipbash
# 通过 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:52 | Script check_nginx now returning 1 | 健康检查脚本检测到 Nginx 异常 |
| 14:54:54 | VRRP_Script(check_nginx) failed | 连续失败 2 次,确认脚本失败 |
| 14:54:54 | Changing effective priority from 100 to 70 | node1 优先级从 100 降到 70 |
| 14:54:57 | received advert from 192.168.0.202 with higher priority 90 | node2 优先级 90 高于当前 70,触发切换 |
| 14:54:57 | Entering BACKUP STATE | node1 让出 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 STATE6.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:vip6.5 验证结论汇总
| 故障场景 | 触发命令 | 日志关键词 | VIP 漂移目标 | 恢复时间 |
|---|---|---|---|---|
| Master 服务故障 | systemctl stop gateway | check_master failed → Changing priority 100→70 → Entering BACKUP | node2 | ~3-6 秒 |
| Nginx 故障 | systemctl stop nginx | check_nginx failed → Changing priority 100→70 → Entering BACKUP | node2 | ~3-6 秒 |
| 整机宕机 | shutdown -h now | (心跳中断) | node2 | ~3-6 秒 |
| 服务恢复 | systemctl start gateway | check_master succeeded → Changing priority 70→100 → Entering MASTER | node1 | ~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.2007.2 查看 VIP 归属
bash
# 查看 VIP 当前在哪台机器
ip addr show eth0 | grep 192.168.0.200
# 或使用更详细的命令
ip addr show label eth0:vip7.3 查看 Keepalived 进程状态
bash
# 查看 Keepalived 进程
ps aux | grep keepalived
# 查看 Keepalived 主进程 PID
sudo cat /var/run/keepalived.pid7.4 手动触发 VIP 切换
bash
# 将当前 Master 降级为 Backup(用于测试)
sudo systemctl stop keepalived
# 查看其他节点是否接管 VIP
# 重新启动 Keepalived 后,会重新抢占(如果优先级更高)
sudo systemctl start keepalived八、常见问题与解决方案
Q1:启动 Keepalived 后,VIP 没有出现?
可能原因:
- 网卡名称不对
- 配置文件语法错误
- 三台机器的
virtual_router_id或auth_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.18Q2:VIP 频繁漂移(抖动)?
可能原因:
- 网络不稳定,心跳丢包
- 健康检查脚本执行太频繁或太重
- 三台机器的
advert_int不一致
解决方案:
- 确保三台机器的
advert_int一致 - 适当增加
fall和rise的值(如fall 3、rise 3) - 检查网络是否稳定
Q3:健康检查脚本没有生效?
可能原因:
track_script块缺失或放错位置- 脚本没有执行权限
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.shQ4:weight 设置多少合适?
weight 的核心原则是:任何单一故障都足以让 Master 的优先级明确低于所有 Backup 节点。
| 节点 | priority | 需要的 weight | 说明 |
|---|---|---|---|
| node1 | 100 | > 10 | 100 - weight < 90 → weight > 10 |
| node2 | 90 | - | - |
| node3 | 80 | - | - |
推荐配置: 使用 -30,留出足够余量,即使两个脚本同时失败也能正常切换。
Q5:三台机器的网卡名称不一样怎么办?
通常在同一批服务器上,网卡名称是相同的。如果不一致,需要为每台机器单独调整 interface 和 dev 参数。
bash
# 在每台机器上单独确认网卡名称
ip addr show
# 然后分别修改配置文件中的 interface 和 dev
interface eth0
virtual_ipaddress {
192.168.0.200/24 dev eth0 label eth0:vip
}九、小结
本章完成了 Keepalived 的部署和 VIP 漂移配置,核心要点:
- 环境准备:三台机器安装 Keepalived
- 基础配置:
state+priority+virtual_ipaddress - 健康检查脚本:检查 Master 服务和 Nginx 是否存活
- 脚本整合:通过
track_script关联健康检查 - 故障验证:三种场景验证 VIP 自动漂移
到现在为止,我们完整搭建了一个生产级的高可用入口:
产品 A → VIP (192.168.0.200) → Keepalived 管理漂移 → Nginx 反向代理 → Master 集群下一章,我们将进行四大故障场景的完整演练,并提供一个自动化的验证脚本。
💡 本文是《分布式高可用入口架构实战系列》第 5 篇
- 点击查看全部文章
- 上一篇:Nginx upstream 健康检查与被动熔断配置
- 下一篇:四大故障场景完整演练(撰写中...)
