前言
前两篇文章中,我们已经完成了 LVS-DR 的基本实验,并理解了它的数据链路:
客户端
↓
访问 VIP
↓
LVS Director 选择 Real Server
↓
只修改当前数据帧的目标 MAC
↓
Real Server 接收目标为 VIP 的数据包
↓
Real Server 使用 VIP 直接响应客户端
从数据转发角度看,这套架构已经可以工作。
但如果把它放到真实生产环境中,很快会遇到两个问题。
第一个问题是 Director 故障:
┌── RS1
客户端 → VIP → LVS ┤
└── RS2
即使 RS1 和 RS2 都正常,只要中间的 LVS Director 挂掉,客户端的数据包就无法进入后端。
此时会出现一种看起来很矛盾的现象:
后端服务器都活着
Web 服务也活着
数据也没有丢失
但是整个网站无法访问
第二个问题是 Real Server 故障。
假设 IPVS 中仍然存在两条调度记录:
VIP:8080
├── RS1:8080
└── RS2:8080
如果 RS2 的 Web 服务已经停止,但 IPVS 并不知道,新的连接仍有可能被调度到 RS2:
客户端 A → RS1 → 正常
客户端 B → RS2 → 连接失败
客户端 C → RS1 → 正常
客户端 D → RS2 → 连接失败
所以,多台 Real Server 只能解决部分容量和后端单机问题,并不能自动得到一套完整的高可用架构。
真正需要解决的是两个层面:
入口高可用
Director 挂掉后,VIP 应自动转移
后端健康检查
Real Server 挂掉后,应自动移出调度池
Keepalived 就是用来自动完成这两件事的。
一、负载均衡不等于高可用
负载均衡解决的核心问题是:
当后端存在多台服务器时,怎样把连接分配给不同服务器?
高可用解决的核心问题则是:
当某个关键节点故障时,怎样让其他节点自动接管服务?
二者并不是同一个概念。
假设我们已经部署两台 Real Server:
RS1:192.168.150.12
RS2:192.168.150.13
Director 的地址为:
DIP:192.168.150.11
VIP:192.168.150.100
IPVS 可以把新连接轮询到 RS1 和 RS2:
192.168.150.100:8080
├── 192.168.150.12:8080
└── 192.168.150.13:8080
这说明后端已经具备横向扩展能力。
但是入口仍然只有一台:
客户端
↓
192.168.150.100
↓
Director:192.168.150.11
只要 .11 故障,VIP 就没有主机接收,整个负载均衡集群仍然不可用。
所以:
多台 Real Server
≠
整个架构已经高可用
完整的故障点至少包括:
Director 主机
Director 网卡
Keepalived 进程
VIP
IPVS 规则
Real Server
Real Server 上的应用
Director 与 RS 之间的网络
高可用不是简单地“多准备几台机器”,而是需要明确:
谁在检测故障
谁来决定接管
接管什么资源
如何通知网络
故障节点恢复后怎么办
二、为什么不能让两台 Director 永久拥有同一个 VIP?
解决 Director 单点问题最直接的想法是再增加一台:
Director 1:192.168.150.11
Director 2:192.168.150.14
然后给两台机器都配置:
VIP:192.168.150.100
但是如果它们同时在同一个网络中宣告自己拥有 VIP,就可能出现地址冲突。
客户端发送 ARP 请求:
谁拥有 192.168.150.100?
两台 Director 同时回答:
Director 1:
192.168.150.100 在我的 MAC 上
Director 2:
192.168.150.100 在我的 MAC 上
客户端和交换机学习到的结果可能不断变化:
VIP
↓
一会儿指向 Director 1
一会儿指向 Director 2
同一条 TCP 连接的数据包也可能被分散到不同机器:
SYN → Director 1
ACK → Director 2
业务数据 → Director 1
后续确认包 → Director 2
而两台 Director 的 IPVS 连接状态未必一致。
最终可能出现:
握手失败
连接重置
数据包被丢弃
访问间歇性超时
因此,主备高可用的基本原则是:
同一个时刻只能由一台 Director 对外承担 VIP。
正常状态:
Director 1
角色:MASTER
VIP:192.168.150.100
对外提供服务
Director 2
角色:BACKUP
没有 VIP
等待接管
主节点故障后:
Director 1
故障
Director 2
BACKUP → MASTER
添加 VIP
接管流量
VIP 并不是同时在两台机器上工作,而是在主备节点之间移动:
正常:
VIP → Director 1
故障后:
VIP → Director 2
Director 1 恢复后:
根据抢占策略决定是否移回 Director 1
这种机制通常被称为:
VIP 漂移
三、主节点和备节点怎样发现对方是否存活?
最容易想到的方式是让备机不断询问主机:
BACKUP:
你还活着吗?
MASTER:
活着
过一段时间再问:
BACKUP:
你还活着吗?
MASTER:
活着
这种方式虽然可以实现,但如果备机很多,所有备机都不断询问主机,会增加主机和网络的额外压力。
VRRP 采用的思路更接近:
MASTER 周期性发送通告
BACKUP 被动监听
正常情况下:
MASTER:
我还活着,优先级是 150
MASTER:
我还活着,优先级是 150
MASTER:
我还活着,优先级是 150
BACKUP 只需要持续接收这些 Advertisement。
当一段时间没有收到有效通告时,BACKUP 才认为当前 MASTER 可能已经不可用,并进入重新选主流程。
当前 VRRPv3 规范中,通告报文包含 VRID、优先级和通告间隔等信息;同一个虚拟路由中,优先级越高的节点越优先承担 Active/Master 角色。
1. 不是简单地“丢三次包就切换”
课堂中经常把这一过程简化为:
连续三次收不到心跳
↓
认为主节点故障
这种说法便于理解,但不够精确。
Backup 判断主节点故障所使用的时间,通常由两部分组成:
若干个通告周期
+
根据优先级计算的偏移时间
可以抽象为:
Master Down Interval
=
3 × Advertisement Interval
+
Skew Time
所以它不是简单地对某一个网络包做一次判断,而是通过定时器避免因为短暂抖动就频繁切换。Keepalived 默认也按照三个通告周期加偏移时间计算主节点失效时间。
假设:
advert_int = 1 秒
那么从主节点完全停止发送通告,到备机完成接管,通常需要几秒,而不是瞬间完成。
2. 为什么需要优先级?
假设存在一个主节点和两个备节点:
Director 1:priority 150
Director 2:priority 100
Director 3:priority 80
Director 1 故障后,另外两台机器都可能发现心跳消失。
如果没有明确规则,它们可能同时试图成为 MASTER。
优先级解决了这个问题:
150 > 100 > 80
正常情况下:
Director 1 成为 MASTER
Director 1 故障后:
Director 2 成为 MASTER
Director 3 继续作为 BACKUP
Director 1 和 Director 2 都故障后:
Director 3 成为 MASTER
这不是让多台机器进行复杂的长时间讨论,而是提前把优先顺序写进配置中。
3. virtual_router_id 是什么?
virtual_router_id,简称 VRID,用于标识一个虚拟路由实例。
例如:
virtual_router_id 51
同一组主备节点必须配置相同的 VRID:
Director 1:VRID 51
Director 2:VRID 51
这样它们才能知道:
我们保护的是同一个 VIP
我们属于同一个高可用组
同一个二层网络中的其他 VRRP 组则应使用不同的 VRID。
Keepalived 的配置参考将 VRID 定义为用于区分 VRRP 实例的 1~255 整数,并明确说明选主时优先级最高的节点获胜。
四、Keepalived、VRRP、LVS 和 IPVS 是什么关系?
这几个名称很容易混在一起。
先看 LVS:
LVS
Linux Virtual Server
一套四层负载均衡技术
LVS 在 Linux 内核中的主要实现是:
IPVS
管理 IPVS 规则的命令行工具是:
ipvsadm
前面的实验中,我们手工执行:
ipvsadm -A ...
ipvsadm -a ...
本质上是在告诉内核:
创建哪个虚拟服务
使用什么调度算法
后端有哪些 Real Server
使用 NAT、DR 还是 TUN
Keepalived 则是运行在用户空间中的守护程序。
它主要把两个机制组合起来:
VRRP
管理主备状态和 VIP
健康检查器
检查 Real Server
动态维护 IPVS 后端条目
因此,可以把整套关系理解为:
Keepalived
├── 使用 VRRP 管理 VIP 高可用
└── 使用健康检查维护 IPVS 规则
IPVS
└── 在 Linux 内核中执行四层调度
Keepalived 官方文档也将其负载均衡框架描述为建立在 Linux IPVS 内核模块之上,同时通过 VRRP 状态机管理故障转移。
Keepalived 不只是 LVS 的专用工具
虽然 Keepalived 最经典的应用是:
Keepalived + LVS
但它管理 VIP 的能力并不依赖 LVS。
例如两台 Nginx:
┌── Nginx 1
客户端 → VIP ────┤
└── Nginx 2
同样可以使用 Keepalived:
Nginx 1 正常
↓
VIP 在 Nginx 1
Nginx 1 故障
↓
VIP 漂移到 Nginx 2
区别只是:
LVS 场景
VIP 后面连接 IPVS 调度规则
Nginx 场景
VIP 直接交给本机 Nginx 监听
所以更准确的描述是:
Keepalived 是一个通用的高可用和健康检查工具,LVS 是它最典型的应用场景之一。
五、本次实验拓扑
为了与前两篇文章保持一致,继续使用下面的地址。
客户端:
192.168.150.1
Director 1:
192.168.150.11
Director 2:
192.168.150.14
Real Server 1:
192.168.150.12
Real Server 2:
192.168.150.13
VIP:
192.168.150.100
服务端口:
8080
完整拓扑:
┌─────────────────────┐
│ Director 1 │
│ 192.168.150.11 │
│ priority 150 │
│ MASTER │
└─────────┬───────────┘
│
客户端 │ VIP 漂移
192.168.150.1 │
│ │
│ 访问 │
│ 192.168.150.100:8080 │
▼ │
VIP ────────────────────────────┤
│
┌─────────┴───────────┐
│ Director 2 │
│ 192.168.150.14 │
│ priority 100 │
│ BACKUP │
└─────────┬───────────┘
│
IPVS 选择 Real Server
│
┌──────────────┴──────────────┐
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ RS1 │ │ RS2 │
│ 192.168.150.12 │ │ 192.168.150.13 │
│ VIP 配置在 lo │ │ VIP 配置在 lo │
│ Web:8080 │ │ Web:8080 │
└──────────────────┘ └──────────────────┘
四台服务器位于同一个二层网络:
192.168.150.0/24
由于使用 LVS-DR,RS1 和 RS2 上仍需要保留前一篇文章中的配置:
VIP 配置在 lo
掩码使用 /32
限制 Real Server 对 VIP 的 ARP 响应和宣告
例如:
sudo ip addr add \
192.168.150.100/32 \
dev lo
Keepalived 安装在两台 Director 上,并不意味着它会自动替远端 Real Server 配置隐藏 VIP。
因此,本次实验中:
Director 1、Director 2
安装 Keepalived
RS1、RS2
继续保留 LVS-DR 的隐藏 VIP 配置
六、先清理手工配置
前一篇实验中,我们在 Director 1 上手工配置了 VIP 和 IPVS 规则。
现在要改为由 Keepalived 自动管理,所以应先清理旧配置,避免出现:
手工规则
+
Keepalived 自动规则
两套配置相互影响。
在原 Director 上执行:
sudo ipvsadm -C
该命令会清空当前 IPVS 虚拟服务和 Real Server 规则。
检查:
sudo ipvsadm -Ln
应不再看到原来的虚拟服务。
然后删除手工添加的 VIP:
sudo ip addr del \
192.168.150.100/32 \
dev eth0
检查:
ip addr show dev eth0
确认物理接口上已经没有:
192.168.150.100
此时 Director 1 恢复为:
只有 DIP
没有 VIP
没有手工 IPVS 规则
Director 2 如果从未进行过配置,本身就是裸机状态。
RS1 和 RS2 不要清理。
它们仍需保留:
lo 上的 VIP
ARP 隐藏参数
8080 端口上的 Web 服务
先分别验证两台 Real Server:
curl http://192.168.150.12:8080/
curl http://192.168.150.13:8080/
预期:
response from rs1
response from rs2
七、安装 Keepalived 和 ipvsadm
以下操作在两台 Director 上执行。
基于 RHEL、Rocky Linux、AlmaLinux 等系统:
sudo dnf install -y \
keepalived \
ipvsadm
旧版本 CentOS 也可能使用:
sudo yum install -y \
keepalived \
ipvsadm
安装完成后,先确认程序存在:
keepalived --version
ipvsadm --version
Keepalived 的主配置文件通常位于:
/etc/keepalived/keepalived.conf
修改前先备份:
sudo cp \
/etc/keepalived/keepalived.conf \
/etc/keepalived/keepalived.conf.bak
备份不是多余操作。
配置文件写错时,可以立即恢复:
sudo cp \
/etc/keepalived/keepalived.conf.bak \
/etc/keepalived/keepalived.conf
八、配置主 Director
在 Director 1 上编辑:
sudo vi /etc/keepalived/keepalived.conf
写入:
global_defs {
router_id LVS_DIRECTOR_1
}
vrrp_instance VI_LVS {
state MASTER
interface eth0
virtual_router_id 51
priority 150
advert_int 1
virtual_ipaddress {
192.168.150.100/32 dev eth0 label eth0:1
}
}
virtual_server 192.168.150.100 8080 {
delay_loop 3
lvs_sched rr
lvs_method DR
protocol TCP
real_server 192.168.150.12 8080 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 3
retry 3
delay_before_retry 2
}
}
real_server 192.168.150.13 8080 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 3
retry 3
delay_before_retry 2
}
}
}
实际环境中的网卡不一定叫:
eth0
也可能是:
ens33
ens160
enp0s3
可以执行:
ip link show
根据真实接口名称修改配置。
Keepalived 官方配置参考支持在 virtual_server 中设置 NAT、DR 或 TUN,并支持为每个 real_server 配置 HTTP、TCP 等类型的健康检查。
九、VRRP 配置逐项解释
1. router_id
router_id LVS_DIRECTOR_1
它主要用于标识当前 Keepalived 节点。
备机应使用不同名称:
router_id LVS_DIRECTOR_2
这个名称不是 VIP,也不是 VRID。
可以理解为:
当前 Keepalived 实例的主机标识
2. vrrp_instance
vrrp_instance VI_LVS {
}
表示定义一个 VRRP 实例。
VI_LVS 是本地配置名称,便于阅读和日志识别。
真正参与同一 VRRP 组识别的关键参数是:
virtual_router_id 51
3. state
主节点:
state MASTER
备节点:
state BACKUP
这里需要注意:
state更接近初始角色声明,实际运行角色仍会受到优先级、收到的通告和接口状态等因素影响。
不能认为写了:
state MASTER
这台机器就永远一定是 MASTER。
如果另一台节点优先级更高,它仍可能在选举中获胜。
4. interface
interface eth0
指定 VRRP 通告从哪块网卡发送和接收。
VIP 默认也会配置到相关接口上。
在生产环境中,服务器可能存在多块网卡:
业务网卡
管理网卡
存储网卡
心跳网卡
应根据网络拓扑选择正确接口。
5. virtual_router_id
virtual_router_id 51
同一组主备节点必须一致:
Director 1:51
Director 2:51
不同高可用组应避免在同一个网络中使用相同组合。
6. priority
priority 150
数值越高,通常越优先成为 MASTER。
例如:
Director 1:150
Director 2:100
正常情况下 Director 1 成为 MASTER。
不要把两台机器设置成完全相同的优先级,否则会增加角色结果的不确定性。
7. advert_int
advert_int 1
表示 MASTER 发送 VRRP 通告的间隔。
这里为:
1 秒
BACKUP 根据收到的通告和失效定时器判断 MASTER 是否仍然可用。
8. virtual_ipaddress
virtual_ipaddress {
192.168.150.100/32 dev eth0 label eth0:1
}
表示由 Keepalived 管理 VIP。
MASTER 状态下:
添加 VIP
BACKUP 状态下:
不持有 VIP
状态切换时,Keepalived会对地址执行添加或删除操作;其配置语法也允许指定掩码、设备和接口标签。
label eth0:1 主要提供传统接口别名形式的显示标签。
在现代 Linux 中,真正关键的是:
同一个物理接口可以持有多个 IP 地址
而不是系统真的创建了一块新的物理网卡。
十、IPVS 配置逐项解释
1. virtual_server
virtual_server 192.168.150.100 8080 {
}
相当于创建一个 IPVS 虚拟服务:
TCP
192.168.150.100:8080
只有目标地址和端口匹配的数据包,才会进入这条调度规则。
它对应手工命令中的:
ipvsadm -A \
-t 192.168.150.100:8080 \
-s rr
2. delay_loop
delay_loop 3
表示健康检查的循环间隔。
这里可以理解为:
每隔约 3 秒执行一轮检查
它和连接超时不是同一个参数。
delay_loop
多久检查一次
connect_timeout
单次连接最多等待多久
3. lvs_sched
lvs_sched rr
表示使用轮询调度:
Round Robin
对于每一条新的连接,IPVS 按顺序选择后端:
新连接 1 → RS1
新连接 2 → RS2
新连接 3 → RS1
新连接 4 → RS2
需要注意:
IPVS 通常按连接调度
不是按每个 HTTP 请求调度
如果浏览器复用了原来的 TCP 连接,不断刷新页面也不一定产生新的轮询结果。
实验时可以使用:
curl \
-H 'Connection: close' \
http://192.168.150.100:8080/
强制每次请求结束后关闭连接,更容易观察轮询。
4. lvs_method
lvs_method DR
表示使用 Direct Routing。
它对应手工命令中的:
-g
请求方向:
客户端
↓
Director
↓
Real Server
响应方向:
Real Server
↓
客户端
响应不再经过 Director。
5. protocol
protocol TCP
表示虚拟服务处理 TCP 流量。
本文的服务是 HTTP over TCP:
VIP:8080
6. real_server
real_server 192.168.150.12 8080 {
}
表示添加一台后端服务器。
对应手工命令:
ipvsadm -a \
-t 192.168.150.100:8080 \
-r 192.168.150.12:8080 \
-g \
-w 1
7. weight
weight 1
表示后端权重。
两台都为 1:
RS1:1
RS2:1
轮询比例大致相同。
如果配置为:
RS1:2
RS2:1
在加权算法下,RS1 会承担更高比例的连接。
十一、持久化超时到底有什么用?
配置文件中经常会看到:
persistence_timeout 50
它表示在指定时间内,将满足条件的同一客户端继续定向到原来的 Real Server。
例如第一次调度结果是:
客户端 A → RS1
在持久化时间内,客户端 A 重新建立连接时,仍可能被分配到 RS1:
客户端 A → RS1
客户端 A → RS1
客户端 A → RS1
它适用于某些需要会话亲和性的场景:
本地 Session
本地缓存
购物车状态
长流程业务
但持久化也会让轮询实验看起来“不工作”。
你可能期望:
刷新一次 → RS1
再刷新一次 → RS2
再刷新一次 → RS1
实际却一直看到:
RS1
RS1
RS1
这不一定是调度算法失效,也可能是:
持久化规则仍然生效
浏览器复用了 TCP 连接
客户端源地址始终相同
Keepalived 配置参考中,persistence_timeout 的单位为秒。
为了清楚观察轮询,本次实验最简单的做法是:
暂时不配置 persistence_timeout
而不是先加入持久化,再怀疑轮询没有生效。
生产环境是否需要持久化,应由业务状态管理方式决定,不能照抄实验参数。
十二、为什么健康检查不能只使用 ping?
最简单的健康检查方式是:
ping 192.168.150.12
如果能够 ping 通,说明:
主机可能在线
网络层可能可达
但不能证明:
8080 端口正在监听
Web 服务正常
应用没有死锁
数据库连接正常
核心接口能够返回数据
可能出现:
操作系统正常
网卡正常
ping 正常
但是:
Tomcat 已停止
Nginx 已崩溃
Java 进程仍在但线程池耗尽
数据库连接全部失败
所以:
ping 成功
≠
应用服务正常
本次配置使用:
HTTP_GET {
url {
path /
status_code 200
}
}
Keepalived 会向 Real Server 发起 HTTP 请求。
只有返回:
HTTP 200
才认为服务正常。
更合理的生产检查页面
生产项目中可以专门提供:
/health
或者:
/actuator/health
该接口内部可以检查:
应用进程状态
数据库连接
缓存连接
必要的磁盘状态
关键下游服务
全部正常时返回:
200 OK
出现关键故障时返回非 200 状态。
例如:
数据库不可用
↓
/health 返回 503
↓
Keepalived 判定 RS 故障
↓
从 IPVS 调度池移除
不过检查逻辑也不能无限扩大。
如果健康接口依赖十几个外部系统,任意一个短暂波动都让整个节点下线,可能反而引发连锁故障。
合理原则是:
健康检查应该验证当前节点是否还能正确处理核心请求,而不是把所有非关键依赖都变成下线条件。
十三、连接超时与重试怎样配合?
配置:
connect_timeout 3
retry 3
delay_before_retry 2
可以抽象为:
第一次检查失败
↓
等待 2 秒
↓
再次检查
↓
仍然失败则继续重试
↓
达到失败条件
↓
将 Real Server 标记为不可用
各参数含义:
connect_timeout 3
单次连接最多等待 3 秒
retry 3
失败后进行额外重试
delay_before_retry 2
两次重试之间等待 2 秒
Keepalived 官方配置说明中,HTTP 检查支持连接超时、重试次数和重试间隔等参数。
这样做是为了避免一次短暂丢包就立即把服务器踢出调度池。
但是参数也不能设置得过大。
过于敏感:
一次失败立即下线
可能造成频繁抖动。
过于迟钝:
失败几十秒后才下线
又会让大量用户继续访问故障节点。
最终需要在两者之间平衡:
故障发现速度
误判概率
业务允许的中断时间
后端恢复速度
十四、配置备 Director
可以先将主节点配置复制到备节点。
在 Director 1 上执行:
sudo scp \
/etc/keepalived/keepalived.conf \
root@192.168.150.14:/etc/keepalived/keepalived.conf
然后登录 Director 2,修改差异项。
主节点:
global_defs {
router_id LVS_DIRECTOR_1
}
vrrp_instance VI_LVS {
state MASTER
interface eth0
virtual_router_id 51
priority 150
advert_int 1
}
备节点改为:
global_defs {
router_id LVS_DIRECTOR_2
}
vrrp_instance VI_LVS {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
advert_int 1
}
其他部分保持一致:
VIP 必须一致
VRID 必须一致
服务端口必须一致
调度算法必须一致
Real Server 列表必须一致
健康检查规则必须一致
只有节点自身相关的内容不同:
router_id
state
priority
这里最容易犯的错误是把备节点 VIP 改成另一个地址。
错误:
主节点 VIP:192.168.150.100
备节点 VIP:192.168.150.101
这样保护的已经不是同一个服务入口。
正确:
主节点 VIP:192.168.150.100
备节点 VIP:192.168.150.100
区别只是:
正常状态下只有 MASTER 真正配置该地址
十五、启动并验证 Keepalived
先在两台机器上设置开机启动:
sudo systemctl enable keepalived
启动主节点:
sudo systemctl start keepalived
查看状态:
sudo systemctl status keepalived
检查 VIP:
ip addr show dev eth0
主节点应出现:
192.168.150.100/32
再检查 IPVS:
sudo ipvsadm -Ln
预期类似:
IP Virtual Server version ...
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight
TCP 192.168.150.100:8080 rr
-> 192.168.150.12:8080 Route 1
-> 192.168.150.13:8080 Route 1
然后启动备节点:
sudo systemctl start keepalived
在备节点查看:
ip addr show dev eth0
正常情况下,不应看到 VIP。
也就是说:
Director 1:
有 VIP
Director 2:
无 VIP
但是在备节点执行:
sudo ipvsadm -Ln
仍可能看到 IPVS 虚拟服务和健康检查维护的 Real Server。
这是正常现象。
可以理解为:
BACKUP 已经提前准备好调度规则
但因为没有 VIP
所以正常流量不会进入它
当它切换为 MASTER 后,就可以更快接管。
Keepalived 官方快速入门同样建议使用 ipvsadm -Ln 检查 Keepalived 是否已将虚拟服务和后端服务器写入内核。
查看日志:
sudo journalctl \
-u keepalived \
-n 100 \
--no-pager
可以观察:
进入 MASTER
进入 BACKUP
添加 VIP
删除 VIP
Real Server 健康检查成功
Real Server 健康检查失败
十六、验证正常负载均衡
客户端执行:
for i in $(seq 1 6); do
curl \
-s \
-H 'Connection: close' \
http://192.168.150.100:8080/
echo
done
预期可能看到:
response from rs1
response from rs2
response from rs1
response from rs2
response from rs1
response from rs2
查看 IPVS 统计:
sudo ipvsadm \
-L \
-n \
--stats
查看连接:
sudo ipvsadm \
-L \
-n \
-c
此时完整链路为:
客户端查询 VIP 的 MAC
↓
当前 MASTER 响应
↓
请求进入 MASTER
↓
IPVS 选择 RS1 或 RS2
↓
DR 修改目标 MAC
↓
Real Server 接收目标为 VIP 的数据包
↓
Real Server 直接响应客户端
Keepalived 没有替代 IPVS 的数据转发。
它只是自动完成了:
配置 VIP
维护 IPVS 规则
检测后端健康
处理主备状态
真正对业务数据包进行四层调度的仍然是内核中的 IPVS。
十七、模拟主 Director 故障
方法一:停止 Keepalived
可以先使用相对温和的方式:
sudo systemctl stop keepalived
正常停止时,Keepalived有机会:
释放 VIP
清理相关状态
通知备节点
然后在备节点查看:
ip addr show dev eth0
应看到 VIP 已经转移:
192.168.150.100/32
查看日志:
sudo journalctl \
-u keepalived \
-n 50 \
--no-pager
可以观察到类似:
BACKUP → MASTER
方法二:关闭主节点网卡
为了模拟更接近网络故障的场景,可以在虚拟机控制台执行:
sudo ip link set eth0 down
或者旧系统中:
sudo ifconfig eth0 down
注意:
通过 SSH 操作时关闭 SSH 所使用的网卡,会立即断开当前远程连接。
因此这类实验最好通过:
虚拟机控制台
云平台控制台
带外管理接口
执行。
主节点网卡关闭后:
MASTER 无法发送 VRRP Advertisement
↓
BACKUP 的失效定时器到期
↓
BACKUP 转为 MASTER
↓
配置 VIP
↓
发送免费 ARP
↓
更新周围主机和交换机对 VIP 的邻居信息
新的访问流量随后进入 Director 2。
十八、客户端真的完全无感知吗?
课堂中常把主备切换描述为:
客户端完全无感知
这句话需要分情况理解。
对于切换后的新连接:
客户端仍访问同一个 VIP
DNS 不需要修改
客户端配置不需要修改
后端地址不需要暴露
从这个角度看,故障转移对客户端是透明的。
但是,对于故障发生前已经建立的 TCP 连接:
不保证一定无损恢复
原主节点中可能存在 IPVS 连接映射:
CIP:ClientPort
→
RS1
备节点虽然拥有相同的调度规则,但未必拥有完全相同的已有连接状态。
切换后,旧连接的后续数据包可能:
被重新调度
无法匹配原有状态
发生超时
被客户端重新建立
因此更准确的说法是:
VIP 切换可以保证客户端继续使用同一个服务入口,但若没有额外的连接状态同步,切换瞬间的已有连接不保证全部无损延续。
前一篇文章中也提到,Keepalived 切换 VIP 后,已有连接是否继续需要结合 IPVS 连接状态同步和转发模式判断。
对于普通短连接 HTTP 请求,用户可能只感觉到一次刷新或重试。
对于:
WebSocket
长轮询
数据库长连接
文件上传
实时音视频
影响可能更加明显。
十九、主节点恢复后为什么会抢回 VIP?
重新启用 Director 1 的网卡:
sudo ip link set eth0 up
然后启动或确认 Keepalived 正常:
sudo systemctl restart keepalived
此时:
Director 1:priority 150
Director 2:priority 100
默认抢占模式下,Director 1 发现自己的优先级更高,可能重新成为 MASTER:
VIP
从 Director 2
漂移回 Director 1
这就是:
抢占
Preemption
当前 VRRP 规范中,高优先级 Backup 默认可以抢占低优先级 Active/Master;Keepalived 也提供 nopreempt 禁止高优先级节点恢复后立即夺回主角色。
什么场景适合抢占?
LVS Director 通常不保存业务数据。
两台机器的核心内容是:
VIP
IPVS 规则
健康检查状态
原主节点修复后重新接管,通常不需要同步大量磁盘数据。
因此可以使用:
高优先级主节点恢复后抢回 VIP
什么场景可能不适合抢占?
对于有状态系统:
数据库
分布式存储
大数据主节点
需要长时间数据同步的服务
刚恢复的原主节点可能数据落后。
如果立即抢回主角色,可能带来:
数据不一致
重复切换
缓存未预热
同步压力
此时更合理的策略可能是:
谁已经稳定承担服务
谁继续保持主角色
在 Keepalived 中可以使用:
nopreempt
不过官方配置说明明确指出,nopreempt 生效时,初始状态不能配置为 MASTER,通常应让节点从 BACKUP 状态开始,再通过优先级完成选举。
二十、验证 Real Server 健康检查
现在停止 RS2 的 Web 服务。
假设使用的是 Python 简易服务器,可以终止对应进程。
如果使用 systemd 管理的服务,例如 Nginx:
sudo systemctl stop nginx
或者 Apache:
sudo systemctl stop httpd
然后在 Director 上持续观察:
watch -n 1 \
'sudo ipvsadm -Ln'
健康检查失败并达到重试条件后,RS2 会从可用调度列表中消失:
TCP 192.168.150.100:8080 rr
-> 192.168.150.12:8080 Route 1
此时新连接只会被发送到 RS1:
客户端 1 → RS1
客户端 2 → RS1
客户端 3 → RS1
恢复 RS2:
sudo systemctl start nginx
或者重新启动实验服务器:
cd ~/lvs-web
python3 -m http.server \
8080 \
--bind 0.0.0.0
健康检查重新成功后,Keepalived 会将 RS2 加回调度池:
TCP 192.168.150.100:8080 rr
-> 192.168.150.12:8080 Route 1
-> 192.168.150.13:8080 Route 1
整个过程不需要人工执行:
ipvsadm -d
ipvsadm -a
这就是自动化运维的价值:
检测
↓
判断
↓
移除
↓
持续复查
↓
恢复后重新加入
二十一、Keepalived 到底有几个进程?
实验中执行:
ps -ef | grep keepalived
经常会看到一个父进程和若干子进程。
可以抽象为:
Keepalived 父进程
├── VRRP 子进程
├── Health Checker 子进程
└── 可选的 BFD 子进程
其中:
VRRP 子进程
管理 VRRP 通告、状态切换和 VIP
Health Checker 子进程
执行 Real Server 检查
维护 IPVS 配置
父进程
监控子进程状态
这里需要修正一种常见理解:
一台 Real Server
=
一个独立 Keepalived 子进程
这并不准确。
健康检查子进程可以同时调度和管理多个 Real Server 的检查任务,并不是配置几台 RS 就必然产生几个检查子进程。
Keepalived 官方架构说明中,守护程序最多拆分为父进程、VRRP 子进程、健康检查子进程和可选 BFD 子进程;父进程还会监控并在必要时重启子进程。
因此,不能仅通过:
看到三个进程
就推断:
一个父进程
+
两台 RS 各一个进程
更合理的理解是按功能隔离:
高精度 VRRP 调度
健康检查
可选 BFD
父进程监督
二十二、kill -9 为什么可能留下问题?
正常停止:
systemctl stop keepalived
程序有机会执行退出流程:
发送退出通告
删除 VIP
清理部分规则
关闭文件和 Socket
写入日志
而:
kill -9 <PID>
由内核直接终止进程,程序没有机会执行自己的清理逻辑。
如果把 Keepalived 相关进程强制终止,可能出现:
用户空间进程已经消失
但内核中的 VIP 或部分规则仍然存在
与此同时,备节点收不到 MASTER 通告:
BACKUP 判断 MASTER 故障
↓
BACKUP 添加同一个 VIP
结果可能变成:
Director 1:
残留 VIP
Director 2:
接管 VIP
两台机器同时存在同一个 VIP。
这就引出了脑裂问题。
需要注意,父进程本身会监控部分子进程;如果只杀死某个子进程,父进程可能重新拉起它。因此测试异常退出时,应先明确自己模拟的是:
VRRP 子进程故障
Keepalived 整体故障
主机故障
网卡故障
网络分区
不同故障的结果并不完全相同。
二十三、什么是脑裂?
正常主备结构中,只有一个 MASTER:
Director 1:MASTER
Director 2:BACKUP
脑裂状态则是:
Director 1:认为自己是 MASTER
Director 2:也认为自己是 MASTER
两台机器可能同时配置:
192.168.150.100
常见原因包括:
VRRP 通告被防火墙拦截
交换机或网络出现分区
心跳接口故障
两边配置的通信方式不一致
进程异常退出后资源没有清理
CPU 长时间过载导致通告处理延迟
虚拟化平台调度停顿
人为同时配置静态 VIP
脑裂最危险的地方不是简单地“多了一个 IP”,而是:
双方都认为自己拥有服务控制权
在 LVS 场景中,可能造成:
VIP 对应的 MAC 不稳定
新连接进入不同 Director
连接状态不一致
流量分配结果不可预测
间歇性连接失败
同一局域网能不能出现脑裂?
能。
ARP 缓存可能让现象暂时不明显,但不能从根本上阻止两台机器同时拥有 VIP。
根据:
谁最后发送免费 ARP
客户端缓存状态
交换机 MAC 学习
网络设备实现
不同客户端可能在一段时间内将 VIP 指向不同节点。
所以更准确的说法是:
同一局域网中的 ARP 缓存可能掩盖或延迟脑裂现象,但并不代表局域网无法出现脑裂。
VRRP 的正常状态机明确要求 Backup 不响应受保护 IPv4 地址的 ARP,而 Active/Master 负责响应并承担转发;一旦两台机器都错误进入 Active 状态,这一互斥关系就被破坏。
二十四、怎样降低脑裂风险?
1. 确认 VRRP 报文没有被拦截
VRRP 使用独立的 IP 协议号:
112
它不是:
TCP 112
UDP 112
防火墙和安全组必须允许主备节点之间正常交换 VRRP 通告。当前 VRRPv3 规范规定其 IP 协议号为 112。
2. 确保主备配置一致
重点检查:
virtual_router_id
VIP
网卡名称
地址族
组播或单播模式
通告间隔
其中某些参数不一致时,两台机器可能根本没有加入同一个有效 VRRP 组。
3. 监控角色和 VIP,而不只监控进程
只检查:
pgrep keepalived
是不够的。
还应监控:
当前节点是 MASTER 还是 BACKUP
VIP 实际在哪台主机
是否出现两台机器同时持有 VIP
VRRP 通告是否正常
IPVS 后端数量是否符合预期
健康检查是否频繁抖动
4. 避免手工静态配置同一个 VIP
如果 VIP 已由 Keepalived 管理,就不要再通过其他网络配置文件永久添加相同地址。
否则可能出现:
Keepalived 删除了 VIP
网络服务又自动加回来
5. 关键系统考虑隔离故障节点
对于数据库、共享存储等状态型服务,仅靠“双方互相发心跳”可能还不够。
更严格的高可用架构通常还会考虑:
Fencing
STONITH
带外电源控制
仲裁节点
多数派机制
其目标是:
无法确认对方是否死亡时
至少保证只有一方有资格继续提供写服务
这也是后续理解 ZooKeeper、Raft、Paxos 和分布式仲裁机制的重要基础。
二十五、常见误区
1. 有两台 Real Server 就已经高可用
错误。
Real Server 变多只解决后端容量和部分后端故障。
Director 和 VIP 仍可能是单点。
2. 两台 Director 可以一直配置同一个 VIP
错误。
主备模式下只能由当前 MASTER 对外承担 VIP。
两台同时持有 VIP 可能造成脑裂和邻居解析混乱。
3. Keepalived 就是 LVS
错误。
LVS/IPVS
负责四层负载均衡
Keepalived
负责 VRRP、VIP 管理和健康检查
4. Keepalived 是内核模块
错误。
Keepalived 是用户空间守护程序。
IPVS 才位于 Linux 内核中。
5. BACKUP 会不断 ping MASTER
不准确。
VRRP 的基本工作方式是 MASTER 周期性发送 Advertisement,BACKUP 监听通告并维护失效定时器。
6. 连续丢三个心跳就一定切换
过度简化。
切换时间还与:
advert_int
节点优先级
Skew Time
Keepalived 配置
系统调度延迟
有关。
7. state MASTER 决定谁永远是主
错误。
state 是初始状态配置,运行中的角色还由优先级和 VRRP 通告决定。
8. ping 通就说明后端服务正常
错误。
ping 只能说明部分网络层状态。
应用可能已经停止或无法处理请求。
9. 健康检查应该只检查端口
不一定。
端口能够连接,只说明存在程序监听。
更合理的方式是请求能够代表核心服务状态的健康接口。
10. 配置 persistence_timeout 后仍应每次刷新轮询
错误。
持久化会让同一客户端在一段时间内继续访问原来的 Real Server。
浏览器还可能复用 TCP 连接。
11. 主备切换后所有旧连接都会继续
不一定。
VIP 入口可以继续使用,但旧 TCP 连接是否延续取决于连接状态同步和具体转发模式。
12. 原主机恢复后一定应该抢回 VIP
不一定。
无状态入口通常可以抢占。
有状态服务则要考虑数据同步、缓存预热和二次切换成本。
13. 一台 Real Server 对应一个 Keepalived 子进程
错误。
Keepalived 通常按 VRRP、健康检查、BFD 等功能拆分进程,而不是按 Real Server 数量一一创建进程。
14. 同一局域网不会出现脑裂
错误。
ARP 缓存可能暂时掩盖问题,但两台机器同时持有 VIP 仍会造成风险。
15. 用守护进程再守护 Keepalived 就能无限提高可靠性
错误。
如果不断增加:
守护 Keepalived 的程序
守护守护程序的程序
再守护上一层的程序
只会形成无穷依赖。
更合理的方向是:
进程监督
主备或集群
故障隔离
仲裁机制
监控告警
自动恢复
总结
单台 LVS Director 的结构是:
客户端
↓
VIP
↓
Director
↓
Real Server
它可以完成负载均衡,但 Director 仍是单点。
加入第二台 Director 后:
┌── Director 1
客户端 → VIP ────┤
└── Director 2
VIP 不能同时由两台机器对外承担。
因此使用 VRRP 建立主备关系:
正常:
Director 1 = MASTER
Director 2 = BACKUP
VIP 在 Director 1
故障:
Director 1 不可用
Director 2 = MASTER
VIP 漂移到 Director 2
Keepalived 在 Director 层完成:
发送和监听 VRRP 通告
根据优先级完成选主
在 MASTER 上添加 VIP
在 BACKUP 上移除 VIP
状态切换后发送免费 ARP
在后端层完成:
检查 Real Server
请求健康检查页面
验证 HTTP 状态码
失败后从 IPVS 调度池移除
恢复后重新加入
因此整套自动化链路为:
MASTER 正常发送 VRRP 通告
↓
BACKUP 持续监听
↓
MASTER 故障
↓
BACKUP 失效定时器到期
↓
BACKUP 转为 MASTER
↓
添加 VIP
↓
发送免费 ARP
↓
新的客户端请求进入新 MASTER
↓
IPVS 选择健康的 Real Server
Real Server 故障时:
HTTP 健康检查失败
↓
达到重试条件
↓
Keepalived 将 RS 从 IPVS 中移除
↓
新连接不再进入故障节点
Real Server 恢复时:
HTTP 健康检查重新成功
↓
Keepalived 将 RS 加回 IPVS
↓
节点重新参与负载均衡
最后,可以用一句话概括 Keepalived 在 LVS 架构中的作用:
IPVS 负责把连接分配给后端服务器,Keepalived 则通过 VRRP 保证 VIP 始终由一台可用的 Director 承担,并通过应用层健康检查动态维护真正能够提供服务的 Real Server。
评论区