负载均衡 LVS 与高可用 Keepalived 全解析
本文是笔者学习 LVS(Linux Virtual Server)负载均衡与 Keepalived 高可用的一天笔记整理,从原理到实战,力求用最通俗的语言讲清楚这两个企业级架构的核心组件。
📖 目录
- [第一部分:LVS 负载均衡全解析](#第一部分:LVS 负载均衡全解析)
- [一、LVS 是什么](#一、LVS 是什么)
- 二、核心角色与术语
- [三、LVS 的工作原理 ------ netfilter 钩子](#三、LVS 的工作原理 —— netfilter 钩子)
- [四、LVS 的四种工作模式](#四、LVS 的四种工作模式)
- [4.1 NAT 模式](#4.1 NAT 模式)
- [4.2 DR 模式(⭐ 重点)](#4.2 DR 模式(⭐ 重点))
- [4.3 TUN 模式](#4.3 TUN 模式)
- [4.4 FullNAT 模式](#4.4 FullNAT 模式)
- 五、调度算法详解
- [六、ipvsadm 命令速查](#六、ipvsadm 命令速查)
- [七、实战:NAT 模式搭建](#七、实战:NAT 模式搭建)
- [八、实战:DR 模式搭建](#八、实战:DR 模式搭建)
- [第二部分:Keepalived 高可用全解析](#第二部分:Keepalived 高可用全解析)
- [九、Keepalived 与 DR 模式集成](#九、Keepalived 与 DR 模式集成)
- [十、VRRP 协议深度剖析](#十、VRRP 协议深度剖析)
- [十一、Keepalived 配置文件全解](#十一、Keepalived 配置文件全解)
- [十二、Keepalived 健康检查机制](#十二、Keepalived 健康检查机制)
- 十三、脑裂(Split-Brain)问题与防范
- [十四、实战:Keepalived + LVS-DR 高可用集群](#十四、实战:Keepalived + LVS-DR 高可用集群)
- 十五、非抢占模式与高级配置
第一部分:LVS 负载均衡全解析
一、LVS 是什么
LVS (Linux Virtual Server)是章文嵩博士于 1998 年 开发的一款开源负载均衡软件,现已合入 Linux 内核主线。
你可以把 LVS 想象成一个 超级快递分拣中心:
- 大量用户请求(快递包裹)涌来
- LVS(分拣中心)根据既定规则,把请求分发到后端的各个服务器(快递员)
- 用户最终收到响应,完全感知不到背后有多少台服务器在协作
LVS 工作在 OSI 第四层(传输层) ,基于 IP:Port 做流量分发,因此性能极高,可以轻松处理百万级并发连接。
二、核心角色与术语
搞懂 LVS,首先要记住这几个角色:
| 术语 | 全称 | 含义 | 类比 |
|---|---|---|---|
| Director / VS | Virtual Server | LVS 调度器本身,负责流量分发 | 快递分拣中心 |
| RS | Real Server | 后端真实服务器(Nginx/Apache/Tomcat) | 快递员 |
| VIP | Virtual IP | 对客户端暴露的虚拟 IP | 分拣中心的公开地址 |
| DIP | Director IP | Director 与 RS 通信使用的 IP | 分拣中心内部工号 |
| RIP | Real Server IP | Real Server 自身的 IP | 快递员的工号 |
| CIP | Client IP | 客户端的 IP | 寄件人地址 |
💡 记忆技巧:VIP 中的 V 是"虚"(Virtual),DIP 中的 D 是"调度器"(Director),RIP 中的 R 是"真实"(Real),CIP 中的 C 是"客户端"(Client)。
三、LVS 的工作原理 ------ netfilter 钩子
LVS 并非常规的用户态程序,而是 以内核模块(ipvs)的形式嵌入 Linux 内核的 netfilter 框架中。这意味着数据包的处理在内核态完成,不需要经过"用户态↔内核态"的来回拷贝,性能极高。
数据包进入 Director 后的流转路径:
网络 → PREROUTING → INPUT → [ IPVS 规则匹配 ] → POSTROUTING → 转发到 RS
↑ ↑
netfilter 钩子 netfilter 钩子
关键步骤:
- 数据包到达 Director,先过 PREROUTING 链
- 检查目标 IP 是否为 VIP,若是则路由到 INPUT 链
- 在 INPUT 链,IPVS 模块 介入:根据调度算法选择一个 RS,修改数据包的目标地址
- 数据包经 POSTROUTING 链发出,到达 RS
- RS 处理请求后,响应数据包返回给客户端
🔑 核心理解:IPVS 本质上是 netfilter 框架的一个"插件",在 INPUT 链上截获发往 VIP 的数据包,改写地址后从 POSTROUTING 发出。
四、LVS 的四种工作模式
LVS 支持四种工作模式,分别对应不同的数据包修改方式:
| 模式 | 英文 | 原理 | 使用占比 |
|---|---|---|---|
| NAT | Network Address Translation | 修改目标 IP(DNAT) | 较少 |
| DR | Direct Routing | 修改目标 MAC 地址 | ≈99% |
| TUN | IP Tunneling | IP 隧道封装 | 少 |
| FullNAT | Full Network Address Translation | 同时修改源和目标 IP | 较少 |
4.1 NAT 模式
NAT 模式是最容易理解的模式------就像 快递中转站代收代发:
客户端 Director Real Server
┌─────┐ ┌──────────┐ ┌──────────┐
│ CIP │ ──── 请求报文 ────→ │ VIP/DIP │ ──── DNAT ────→ │ RIP │
│ │ ←─── 响应报文 ──── │ │ ←─── 原路返回 ──── │ │
└─────┘ └──────────┘ └──────────┘
请求方向:CIP → VIP 变为 CIP → RIP (改目标 IP)
响应方向:RIP → CIP 变为 VIP → CIP (改源 IP)
工作流程:
- 客户端发送请求到 VIP
- Director 收到后,将 目标 IP 从 VIP 改为 RIP(DNAT)
- RS 收到请求并处理
- RS 将响应发给 Director(因为 RS 的默认网关必须是 Director)
- Director 将 源 IP 从 RIP 改回 VIP(SNAT),发给客户端
优点:
- 配置简单,易于理解
- 支持端口映射(VIP:80 → RIP:8080)
缺点:
- Director 需处理所有进出流量,容易成为瓶颈
- RS 的网关必须指向 Director
- 请求和响应都经过 Director,吞吐量受限于 Director 带宽
⚠️ NAT 模式下,Director 就像独木桥------所有人的进出都要经过它,当流量增大时,Director 首先扛不住。
4.2 DR 模式(⭐ 重点)
DR(Direct Routing)是 生产环境使用最多的模式 ,约 99% 的 LVS 集群采用此模式。它的核心思路非常巧妙------只改 MAC 地址,不改 IP 地址:
客户端 Director Real Server
┌─────┐ ┌──────────┐ ┌──────────┐
│ CIP │ ──── 请求报文 ────→ │ VIP/DIP │ ──── 改MAC ────→ │ VIP(RIP) │
│ │ ←─── 响应报文 ──────────────────────────────────── │ │
└─────┘ └──────────┘ └──────────┘
↑ ↑
只修改MAC 响应直接回客户端!
数据包变化(精华):
进入 Director 前: 离开 Director 后:
┌──────────────────────┐ ┌──────────────────────┐
│ 源 IP: CIP │ │ 源 IP: CIP │ ← 不变!
│ 目标 IP: VIP │ │ 目标 IP: VIP │ ← 不变!
│ 源 MAC: Client MAC │ │ 源 MAC: DIP 的 MAC │
│ 目标 MAC: VIP 的 MAC │ │ 目标 MAC: RS 的 MAC │ ← 只改这个!
└──────────────────────┘ └──────────────────────┘
工作流程:
- 客户端发请求到 VIP
- Director 收到后,不修改 IP 包,只把目标 MAC 地址改为某台 RS 的 MAC
- RS 收到后发现目标 IP(VIP)匹配自己的 lo 接口,正常处理
- RS 直接将响应发给客户端,不再经过 Director!
💡 这就是 DR 模式的核心优势------"来时有我,走时随意"。Director 只处理入站请求(通常请求数据量小),出站响应(通常数据量大)由 RS 直接返回客户端。这种非对称架构极大提高了吞吐量。
DR 模式的关键约束:
| 约束 | 说明 |
|---|---|
| ① RS 必须配置 VIP | RS 的 lo(回环接口)上需绑定 VIP(/32 掩码) |
| ② 必须抑制 ARP | RS 不能响应 VIP 的 ARP 请求,否则 Director 的 VIP 会被"抢走" |
| ③ RS 和 Director 同网段 | 需要通过 MAC 地址直接通信,不能跨越路由器 |
| ④ Director 的 VIP 对外可见 | RS 的 VIP 隐藏(通过 ARP 抑制实现) |
ARP 抑制详解(DR 模式最关键的技术细节):
为什么需要抑制 ARP?考虑这个场景:
- Director 上有 VIP(对外提供服务)
- RS 的 lo 上也绑了 VIP
- 当路由器问"谁是 VIP?请告诉 MAC 地址"时,如果 RS 抢先回答了,客户端的流量就会绕过 Director 直连 RS,负载均衡就失效了!
解决方案:配置两个内核参数:
bash
# arp_ignore = 1:只回应从该接口进来的 ARP 请求
# 如果 ARP 请求从 eth0 进来,而 VIP 配在 lo 上 → 不回应
net.ipv4.conf.all.arp_ignore = 1
# arp_announce = 2:通告 IP 时使用最佳本地地址
# 对外通告时,不宣告 lo 上的 VIP
net.ipv4.conf.all.arp_announce = 2
🎯 一句话总结 DR 模式:Director 和 RS 共享同一个 VIP,但只有 Director 的 VIP 对外"出声";RS 的 VIP 是"沉默"的,只用来接收 Director 转发过来的请求。
4.3 TUN 模式
TUN(IP Tunneling)模式在 DR 模式基础上增加了 IP 隧道封装,解决了 跨网段 的问题:
原始报文:[CIP → VIP] + 数据
封装后: [DIP → RIP] + [CIP → VIP] + 数据
↑ 新增的外层 IP 头 ↑ 原始报文
适用场景:RS 和 Director 不在同一物理网络,需要跨机房、跨地域部署时使用。
约束:
- RS 操作系统必须支持 IP 隧道(
ipip模块) - 额外的 IP 头带来少量性能开销
4.4 FullNAT 模式
FullNAT 是淘宝对 LVS 的扩展,同时修改源 IP 和目标 IP:
- NAT 只改目标 IP
- FullNAT 连源 IP 也改(SNAT + DNAT 同时做)
- 优点:RS 可以跨网段,Director 和 RS 不必在同一子网
- 缺点:RS 看不到真实客户端 IP(CIP 被替换成 DIP)
五、调度算法详解
LVS 提供了丰富的调度算法,分为 静态 和 动态 两大类:
静态调度算法(不关心 RS 当前状态)
| 算法 | 全称 | 含义 | 类比 |
|---|---|---|---|
| RR | Round Robin | 轮询,依次分发 | 发扑克牌,一人一张 |
| WRR | Weighted RR | 加权轮询,按权重比例分发 | 性能好的服务器多拿几张牌 |
| DH | Destination Hash | 按目标 IP 哈希 | 同一目标 IP 的请求固定发到同一 RS |
| SH | Source Hash | 按源 IP 哈希 | 同一客户端的请求固定发到同一 RS |
动态调度算法(根据 RS 当前连接数和负载)
| 算法 | 全称 | 含义 |
|---|---|---|
| LC | Least Connections | 最少连接数优先 |
| WLC | Weighted LC | 加权最少连接数(默认算法) |
| SED | Shortest Expected Delay | 最短预期延迟 |
| NQ | Never Queue | 永不排队(SED 改进版) |
| LBLC | Locality-Based LC | 基于局部性的最少连接 |
| LBLCR | LBLC with Replication | 带复制的 LBLC |
WLC 算法公式(最常用):
Overhead = (Active_Connections × 256 + Inactive_Connections) ÷ Weight
选择 Overhead 最小的 RS。+1 和 ×256 的设计是为了让活跃连接的影响远大于非活跃连接。
📌 生产建议:一般场景用 WRR ,长连接场景(如数据库代理)用 WLC。
六、ipvsadm 命令速查
ipvsadm 是管理 LVS 规则的用户态工具,对应的内核模块是 ipvs。
添加/修改虚拟服务
bash
# 添加 TCP 虚拟服务(VIP:Port),调度算法为 rr
ipvsadm -A -t 10.1.8.100:80 -s rr
# 修改调度算法为 wrr
ipvsadm -E -t 10.1.8.100:80 -s wrr
# 删除虚拟服务
ipvsadm -D -t 10.1.8.100:80
参数说明:
-A:添加虚拟服务-E:修改虚拟服务-D:删除虚拟服务-t:TCP 协议-u:UDP 协议-s:指定调度算法-p:持久连接超时时间
添加/修改 Real Server
bash
# 添加 RS(-g=DR模式, -i=TUN模式, -m=NAT模式)
ipvsadm -a -t 10.1.8.100:80 -r 10.1.8.11:80 -g -w 1
ipvsadm -a -t 10.1.8.100:80 -r 10.1.8.12:80 -g -w 2
ipvsadm -a -t 10.1.8.100:80 -r 10.1.8.13:80 -g -w 3
# 修改 RS 权重
ipvsadm -e -t 10.1.8.100:80 -r 10.1.8.12:80 -g -w 5
# 删除 RS
ipvsadm -d -t 10.1.8.100:80 -r 10.1.8.12:80
参数说明:
-a:添加 RS-e:修改 RS-d:删除 RS-r:RS 的地址-g:DR 模式(Gateway)-i:TUN 模式(IPIP)-m:NAT 模式(Masquerade)-w:权重
查看与保存
bash
# 查看规则(-n 不做 DNS 解析)
ipvsadm -Ln
# 查看连接状态
ipvsadm -Lnc
# 计数器清零
ipvsadm -Z
# 保存规则
ipvsadm-save -n > /etc/sysconfig/ipvsadm
# 清空所有规则
ipvsadm -C
七、实战:NAT 模式搭建
🖥️ 实验拓扑:7 台 CentOS 7 虚拟机
| 角色 | 主机名 | VMnet1 IP | VMnet8 IP | 网关 |
|---|---|---|---|---|
| 外网客户端 | client2 | 10.1.1.21 | - | 10.1.1.10 |
| 内网客户端 | client1 | - | 10.1.8.21 | 10.1.8.10 |
| LVS Director | lvs | 10.1.1.10 | 10.1.8.10 | 10.1.8.2 |
| Web 服务器 1 | web1 | - | 10.1.8.11 | 10.1.8.10 |
| Web 服务器 2 | web2 | - | 10.1.8.12 | 10.1.8.10 |
| Web 服务器 3 | web3 | - | 10.1.8.13 | 10.1.8.10 |
步骤 1:网络配置
bash
# === 各节点设置主机名和 IP ===
# client2(外网客户端)
hostnamectl set-hostname client2.laogao.cloud
nmcli connection modify ens33 ipv4.method manual \
ipv4.addresses 10.1.1.21/24 \
ipv4.gateway 10.1.1.10 \
ipv4.dns 223.5.5.5 autoconnect yes
nmcli connection up ens33
# lvs(Director,双网卡)
hostnamectl set-hostname lvs.laogao.cloud
nmcli connection modify ens33 ipv4.method manual \
ipv4.addresses 10.1.8.10/24 \
ipv4.gateway 10.1.8.2 \
ipv4.dns 223.5.5.5 autoconnect yes
nmcli connection up ens33
# 添加第二块网卡(连接外网)
nmcli connection add type ethernet con-name ens36 ifname ens36 \
ipv4.method manual ipv4.addresses 10.1.1.10/24 autoconnect yes
nmcli connection up ens36
# web1-3(Real Server,网关指向 Director)
# 以 web1 为例
hostnamectl set-hostname web1.laogao.cloud
nmcli connection modify ens33 ipv4.method manual \
ipv4.addresses 10.1.8.11/24 \
ipv4.gateway 10.1.8.10 \
ipv4.dns 223.5.5.5 autoconnect yes
nmcli connection up ens33
步骤 2:Director 开启转发和 NAT
bash
# 开启 IP 转发
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p
# 配置防火墙 NAT(MASQUERADE)
systemctl enable firewalld.service --now
firewall-cmd --set-default-zone=trusted
firewall-cmd --add-masquerade --permanent
firewall-cmd --add-masquerade
步骤 3:RS 部署 Web 服务
bash
# 在每个 Web 节点上
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum install -y nginx
echo "Welcome to $(hostname)" > /usr/share/nginx/html/index.html
systemctl enable nginx.service --now
# 验证
curl 10.1.8.11 # → Welcome to web1.laogao.cloud
curl 10.1.8.12 # → Welcome to web2.laogao.cloud
curl 10.1.8.13 # → Welcome to web3.laogao.cloud
步骤 4:Director 配置 LVS 规则
bash
yum install -y ipvsadm
touch /etc/sysconfig/ipvsadm
systemctl enable ipvsadm --now
# 添加虚拟服务(VIP: 10.1.1.10:80,调度算法 rr)
ipvsadm -A -t 10.1.1.10:80 -s rr
# 添加 Real Server(-m 表示 NAT 模式)
ipvsadm -a -t 10.1.1.10:80 -r 10.1.8.11 -m
ipvsadm -a -t 10.1.1.10:80 -r 10.1.8.12 -m
ipvsadm -a -t 10.1.1.10:80 -r 10.1.8.13 -m
# 查看规则
ipvsadm -Ln
输出示例:
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.1.1.10:80 rr
-> 10.1.8.11:80 Masq 1 0 0
-> 10.1.8.12:80 Masq 1 0 0
-> 10.1.8.13:80 Masq 1 0 0
🔍 注意
Forward列显示Masq,这是 NAT 模式的标志。
步骤 5:测试负载均衡
bash
# 从外网客户端发起 90 次请求
for i in {1..90}; do curl -s 10.1.1.10; done | sort | uniq -c
# 输出(RR 算法,均匀分配):
# 30 Welcome to web1.laogao.cloud
# 30 Welcome to web2.laogao.cloud
# 30 Welcome to web3.laogao.cloud
步骤 6:切换到 WRR 算法
bash
# 修改调度算法为加权轮询
ipvsadm -E -t 10.1.1.10:80 -s wrr
# 设置权重(web1=1, web2=2, web3=3)
ipvsadm -e -t 10.1.1.10:80 -r 10.1.8.11 -m -w 1
ipvsadm -e -t 10.1.1.10:80 -r 10.1.8.12 -m -w 2
ipvsadm -e -t 10.1.1.10:80 -r 10.1.8.13 -m -w 3
# 再次测试(90 次请求,按 1:2:3 分配)
for i in {1..90}; do curl -s 10.1.1.10; done | sort | uniq -c
# 15 Welcome to web1.laogao.cloud ← 1/6
# 30 Welcome to web2.laogao.cloud ← 2/6
# 45 Welcome to web3.laogao.cloud ← 3/6
八、实战:DR 模式搭建
DR 模式是企业级部署的标配,下面详细演示完整搭建过程。
实验拓扑
| 角色 | 主机名 | VMnet8 IP | 网关 |
|---|---|---|---|
| 路由器 | router | 10.1.8.20 (内网) / 10.1.1.20 (外网) | 10.1.8.2 |
| LVS Director | lvs | 10.1.8.10 | 10.1.8.20 |
| Web 服务器 1 | web1 | 10.1.8.11 | 10.1.8.20 |
| Web 服务器 2 | web2 | 10.1.8.12 | 10.1.8.20 |
| Web 服务器 3 | web3 | 10.1.8.13 | 10.1.8.20 |
| 内网客户端 | client1 | 10.1.8.21 | 10.1.8.20 |
| VIP | - | 10.1.8.100 | - |
步骤 1:路由器配置
bash
hostnamectl set-hostname router.laogao.cloud
# 配置双网卡 + 开启转发
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p
systemctl enable firewalld.service --now
firewall-cmd --set-default-zone=trusted
firewall-cmd --add-masquerade --permanent
firewall-cmd --add-masquerade
步骤 2:Real Server 配置 ------ 关键步骤!
每个 RS 上要做两件事:① 绑 VIP 到 lo ② 抑制 ARP
bash
# ===== 在每个 Web 节点上执行 =====
# ① 创建 dummy 接口,绑定 VIP(/32 掩码,不对外广播)
nmcli connection add type dummy ifname dummy con-name dummy \
ipv4.method manual ipv4.addresses 10.1.8.100/32
nmcli connection up dummy
# ② 配置 ARP 抑制(核心!)
cat >> /etc/sysctl.conf << EOF
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.dummy.arp_ignore = 1
net.ipv4.conf.dummy.arp_announce = 2
EOF
sysctl -p
💡 arp_ignore = 1:只有 ARP 请求从目标接口进入时才回应。VIP 绑定在 dummy 上,ARP 请求从 eth0 进入 → 不回应!
💡 arp_announce = 2:对外通告时,始终使用最佳本地地址(eth0 的 RIP),不宣告 dummy 上的 VIP。
步骤 3:Director 配置
bash
# Director 也绑定 VIP(对外提供服务)
nmcli connection add type dummy ifname dummy con-name dummy \
ipv4.method manual ipv4.addresses 10.1.8.100/32
nmcli connection up dummy
# 安装并配置 LVS(注意:-g 表示 DR 模式)
yum install -y ipvsadm
touch /etc/sysconfig/ipvsadm
systemctl enable ipvsadm --now
ipvsadm -A -t 10.1.8.100:80 -s rr
ipvsadm -a -t 10.1.8.100:80 -r 10.1.8.11:80 -g
ipvsadm -a -t 10.1.8.100:80 -r 10.1.8.12:80 -g
ipvsadm -a -t 10.1.8.100:80 -r 10.1.8.13:80 -g
ipvsadm-save -n > /etc/sysconfig/ipvsadm
# 查看规则(注意 Forward 列为 Route,表示 DR 模式)
ipvsadm -Ln
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.1.8.100:80 rr
-> 10.1.8.11:80 Route 1 0 0
-> 10.1.8.12:80 Route 1 0 0
-> 10.1.8.13:80 Route 1 0 0
🔍
Forward列显示Route表示 DR 模式(对比 NAT 模式显示Masq)。
步骤 4:测试
bash
# 从客户端测试
for i in {1..90}; do curl -s 10.1.8.100; done | sort | uniq -c
# 30 Welcome to web1.laogao.cloud
# 30 Welcome to web2.laogao.cloud
# 30 Welcome to web3.laogao.cloud
步骤 5:生产级启动脚本
Real Server 脚本 (/usr/local/sbin/lvs-rs.sh):
bash
#!/bin/bash
# description : LVS Real Server 启动/停止脚本
VIP=10.1.8.100
case "$1" in
start)
echo -n "Start LVS Real Server ... "
# 绑定 VIP
if nmcli connection | grep -q dummy; then
nmcli connection modify dummy ipv4.method manual ipv4.addresses $VIP/32
else
nmcli connection add type dummy ifname dummy con-name dummy \
ipv4.method manual ipv4.addresses $VIP/32
fi
nmcli connection up dummy
# 抑制 ARP
echo "1" > /proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce
echo "1" > /proc/sys/net/ipv4/conf/dummy/arp_ignore
echo "2" > /proc/sys/net/ipv4/conf/dummy/arp_announce
echo OK
;;
stop)
echo -n "Stop LVS Real Server ... "
nmcli connection delete dummy
# 恢复 ARP 默认值
echo "0" > /proc/sys/net/ipv4/conf/all/arp_ignore
echo "0" > /proc/sys/net/ipv4/conf/all/arp_announce
echo "0" > /proc/sys/net/ipv4/conf/dummy/arp_ignore
echo "0" > /proc/sys/net/ipv4/conf/dummy/arp_announce
echo OK
;;
*)
echo "Usage: $0 start|stop"
exit 1
esac
Director Server 脚本 (/usr/local/sbin/lvs-ds.sh):
bash
#!/bin/bash
# description : LVS Director Server 启动/停止脚本
VIP=10.1.8.100
PORT=80
rs1=10.1.8.11
rs2=10.1.8.12
rs3=10.1.8.13
interface=ens33
ipv=/sbin/ipvsadm
# 确保 ipvsadm 已安装
if ! rpm -q ipvsadm &>/dev/null; then
yum install -y ipvsadm &>/dev/null
fi
case "$1" in
start)
echo -n "Start LVS Director Server ... "
# 绑定 VIP 到物理网卡
if ! ip -br addr | grep -q $VIP; then
nmcli connection modify ${interface} +ipv4.addresses $VIP/32
nmcli connection up ${interface}
fi
# 配置 LB 规则
$ipv -C
$ipv -A -t $VIP:$PORT -s wrr
$ipv -a -t $VIP:$PORT -r $rs1:$PORT -g -w 1
$ipv -a -t $VIP:$PORT -r $rs2:$PORT -g -w 1
$ipv -a -t $VIP:$PORT -r $rs3:$PORT -g -w 1
echo OK
;;
stop)
echo -n "Stop LVS Director Server ... "
# 移除 VIP
if ip -br addr | grep -q $VIP; then
nmcli connection modify ${interface} -ipv4.addresses $VIP/32
nmcli connection up ${interface}
fi
# 清空 LB 规则
$ipv -C
echo OK
;;
*)
echo "Usage: $0 start|stop"
exit 1
esac
第二部分:Keepalived 高可用全解析
前面我们搭建了 LVS-DR 集群,但有一个致命问题------Director 是单点! 如果 Director 宕机,整个集群就瘫痪了。接下来用 Keepalived 解决这个难题。
九、Keepalived 与 DR 模式集成
问题分析
回顾 LVS-DR 架构:
┌──────────────┐
│ 客户端 │
└──────┬───────┘
│ VIP
┌──────▼───────┐
│ Director │ ← 单点故障!这台挂了全完了
└──┬───┬───┬───┘
│ │ │
┌─────▼ ▼ ▼─────┐
│ RS1 RS2 RS3 │ ← 后端好好的,可惜没人分发流量了
└───────────────────┘
解决思路:用两台(或多台)Director,一台做主(Master),一台做备(Backup),主备之间通过 VRRP 协议协商 VIP 的归属。
┌──────────────┐
│ 客户端 │
└──────┬───────┘
│ VIP(飘来飘去)
┌───────┴───────┐
│ │
┌────▼────┐ ┌─────▼────┐
│ Master │ │ Backup │ ← Keepalived 管理的主备
│ (LVS) │◄──►│ (LVS) │ VRRP 心跳
└──┬───┬──┘ └──┬──┬───┘
│ │ │ │
▼ ▼ ▼ ▼
┌──────────────────────┐
│ RS1 RS2 RS3 │
└──────────────────────┘
Keepalived 是什么
Keepalived 是一个用 C 语言编写的 Linux 守护进程,主要实现两大功能:
| 功能 | 说明 |
|---|---|
| VRRP 高可用 | 实现主备节点的故障切换(Failover),VIP 在主备之间漂移 |
| LVS 健康检查 | 自动检测后端 RS 的健康状态,自动剔除故障节点、恢复后自动加入 |
Keepalived 本质上是对 VRRP 协议 的完整实现,同时深度集成了 LVS 的管理能力。你可以把它理解为 "LVS 的自动驾驶系统"------不仅会开车(负载均衡),还能自动换备胎(故障切换)和检测发动机(健康检查)。
十、VRRP 协议深度剖析
10.1 什么是 VRRP
VRRP (Virtual Router Redundancy Protocol,虚拟路由冗余协议)是 IETF 标准协议(RFC 3768),用于解决局域网中默认网关单点故障的问题。
不严谨但好理解的类比:
想象公司前台只有一个人接电话。如果他请假了,所有电话就没人接了。VRRP 的做法是------安排两个人(一个主、一个备),共享同一个"前台分机号"(VIP),主前台正常接电话,备前台在旁边待命。主前台每隔一会儿喊一声"我还在!",如果备前台连续几次没听到,就自动接管分机号,开始接电话。
10.2 VRRP 核心概念
| 概念 | 说明 |
|---|---|
| 虚拟路由器 | 由 Master + Backup 组成的逻辑实体,对外表现为一台"永不宕机"的路由器 |
| VRID | Virtual Router Identifier(1-255),同一组 VRRP 实例共享 |
| Master | 主节点,持有 VIP 并处理流量 |
| Backup | 备节点,监听 Master 心跳,随时准备接管 |
| Priority | 优先级(0-255),值高者成为 Master。注意:IP 地址最大的节点在优先级相同时胜出 |
| VIP | 虚拟 IP,始终在 Master 上 |
10.3 VRRP 报文格式
VRRP 通过组播地址 224.0.0.18 发送通告报文:
┌──────────────────────────────────────────┐
│ Ver (v2=IPv4, v3=IPv4+IPv6) │
│ Virtual Rtr ID (VRID, 1-255) │
│ Priority (0-255,0 表示 Master 主动放弃) │
│ Count IP Addrs (VIP 个数) │
│ Auth Type (无/PASS/MD5) │
│ Adver Int (通告间隔,默认 1 秒) │
│ IP Address(es) (VIP 地址列表) │
│ Authentication Data │
└──────────────────────────────────────────┘
10.4 VRRP 状态机
VRRP 协议定义了三态状态机:
┌──────────┐
启动 ────►│Initialize│
└────┬─────┘
│ Priority=255 → 直接成为 Master
┌────▼─────┐
┌────►│ Master │◄────────────┐
│ └──┬───┬───┘ │
│ │ │ 收到更高优先级通告 │
│ │ └──────────────────┘
│ │ 主动关闭(priority=0)
│ ┌────▼─────┐
└───┤ Backup │
Master_Down │ │ 收到低优先级 Master 通告
超时后抢占 └──────────┘ ──────────────────┘
Master_Down 计时器计算公式:
MASTER_DOWN = 3 × ADVER_INTERVAL + Skew_Time
Skew_Time = (256 - Priority) / 256
💡 这意味着:优先级越高的 Backup,Skew_Time 越小,越快感知到 Master 宕机并抢占。这是一个精妙的"优先级越高,反应越快"的设计。
10.5 VIP 漂移过程(完整流程)
以 web1(Master,Priority=110)和 web2(Backup,Priority=100)为例:
时间线 ─────────────────────────────────────────────────────►
① 初始状态
web1 [MASTER, VIP=10.1.8.100] ←→ 发送心跳(每秒1次) ←→ web2 [BACKUP]
② web1 宕机(或 Keepalived 停止)
web1 [DOWN] web2 [等待...]
MASTER_DOWN 超时(约3秒)
③ web2 接管
web1 [DOWN] web2 [MASTER, VIP=10.1.8.100]
↑ 发送 Gratuitous ARP 通告
④ web1 恢复
web1 [启动,发现比自己优先级高 → 成为 MASTER] web2 [收到更高优先级通告 → 降为 BACKUP]
↑ 再次发送 Gratuitous ARP
📡 Gratuitous ARP(免费 ARP):当 VIP 发生漂移时,新的 Master 会主动广播"我是 10.1.8.100,我的 MAC 是 xx:xx",让交换机和路由器立即更新 MAC 地址表,实现流量的无缝切换。
十一、Keepalived 配置文件全解
Keepalived 的配置文件位于 /etc/keepalived/keepalived.conf,分为三大块:
配置结构
keepalived.conf
├── GLOBAL CONFIGURATION(全局配置)
│ ├── global_defs:router_id、邮件通知等
│ └── VRRP 全局参数
├── VRRPD CONFIGURATION(VRRP 实例配置)
│ └── vrrp_instance:state、priority、VIP、认证等
└── LVS CONFIGURATION(LVS 规则配置)
└── virtual_server:调度算法、转发模式、RS 列表等
完整配置示例(带注释)
nginx
! Configuration File for keepalived
# ============ 全局配置 ============
global_defs {
# 路由器标识(在 LAN 中唯一)
router_id LVS_DEVEL
# 邮件通知(可选)
# notification_email {
# admin@example.com
# }
# notification_email_from keepalived@example.com
# smtp_server 192.168.200.1
# smtp_connect_timeout 30
# VRRP 全局参数
vrrp_skip_check_adv_addr # 不检查通告中的源地址
# vrrp_strict # 严格模式(会配置防火墙规则)
vrrp_garp_interval 0 # Gratuitous ARP 发送间隔
vrrp_gna_interval 0 # 无请求邻居通告间隔
}
# ============ VRRP 实例配置 ============
vrrp_instance VI_1 {
state MASTER # MASTER 或 BACKUP
interface eth0 # VIP 绑定的网卡
virtual_router_id 51 # VRID,主备必须一致(1-255)
priority 100 # 优先级,高者成为 Master
advert_int 1 # 心跳通告间隔(秒)
# 认证(主备必须一致)
authentication {
auth_type PASS # PASS 或 AH
auth_pass 1111 # 密码(最多 8 位)
}
# 虚拟 IP 地址
virtual_ipaddress {
192.168.200.16
192.168.200.17
192.168.200.18
}
# 追踪网卡状态(任一下降则降级)
track_interface {
eth0
eth1
}
}
# ============ LVS 虚拟服务配置 ============
virtual_server 192.168.200.100 443 {
delay_loop 6 # 健康检查间隔(秒)
lb_algo rr # 调度算法:rr|wrr|lc|wlc|lblc|sh|dh
lb_kind DR # 转发模式:NAT|DR|TUN
persistence_timeout 50 # 持久连接超时(秒)
protocol TCP # 协议:TCP|UDP|SCTP
# 后端 Real Server
real_server 192.168.201.100 443 {
weight 1 # 权重
# TCP_CHECK / HTTP_GET / SSL_GET 等健康检查方式
TCP_CHECK {
connect_timeout 3
retry 3
delay_before_retry 3
}
}
}
十二、Keepalived 健康检查机制
Keepalived 不仅仅做 VRRP 高可用,它还能自动检测后端 RS 的健康状态,这是生产环境中不可或缺的能力。
支持的检查方式
| 检查类型 | 说明 | 适用场景 |
|---|---|---|
| TCP_CHECK | TCP 三次握手探测端口 | 通用 TCP 服务 |
| HTTP_GET | HTTP GET 请求 + 状态码/内容校验 | Web 服务 |
| SSL_GET | HTTPS 握手 + GET 请求 | HTTPS 服务 |
| MISC_CHECK | 执行自定义脚本 | 复杂业务逻辑 |
| SMTP_CHECK | SMTP 协议探测 | 邮件服务 |
| DNS_CHECK | DNS 查询探测 | DNS 服务 |
配置示例:HTTP 健康检查
nginx
virtual_server 10.1.8.100 80 {
delay_loop 6
lb_algo wrr
lb_kind DR
protocol TCP
real_server 10.1.8.11 80 {
weight 1
HTTP_GET {
url {
path /health # 检查的 URL 路径
status_code 200 # 期望的状态码
digest abc123def # 可选:页面内容的 MD5
}
connect_timeout 3 # 连接超时
nb_get_retry 3 # 重试次数
delay_before_retry 3 # 重试间隔
}
}
}
当 RS 健康检查失败时,Keepalived 会自动将其从 LVS 转发列表中移除;恢复后自动加回。整个过程对客户端透明。
十三、脑裂(Split-Brain)问题与防范
什么是脑裂
脑裂 是指 VRRP 集群中,Master 和 Backup 同时认为自己持有 VIP,导致 IP 冲突、流量混乱。
打个比方:一个公司不能有两个 CEO 同时发号施令。脑裂就是两个 CEO 都认为自己是老大,结果公司乱成一团。
脑裂的常见原因
- 心跳线中断:主备之间的网络断了,双方都认为对方挂了
- 防火墙阻断 VRRP 组播:VRRP 使用 UDP 112 端口通信
- CPU 负载过高:Master 来不及发送心跳,Backup 误判其宕机
- 配置不一致:VRID 或认证密码不匹配
防范脑裂的五大措施
① 配置 VPN 专用心跳线
主备之间用独立网线直连或专用 VLAN,不依赖业务网络。
② 放行 VRRP 协议(防火墙)
bash
# 必须放行 VRRP 协议号 112
firewall-cmd --add-protocol=vrrp --permanent
firewall-cmd --reload
③ 配置认证
nginx
vrrp_instance VI_1 {
authentication {
auth_type PASS
auth_pass 123456 # 主备密码必须一致
}
}
④ 编写脑裂检测脚本 + 通知回调
nginx
vrrp_instance VI_1 {
notify_master "/etc/keepalived/check_split_brain.sh master"
notify_backup "/etc/keepalived/check_split_brain.sh backup"
notify_fault "/etc/keepalived/check_split_brain.sh fault"
}
检测思路:
- 成为 Master 后,ping 网关或对端 IP
- 如果也能 ping 通 VIP(说明对端也持有 VIP)→ 脑裂发生 → 自动降级或告警
⑤ 监控告警
通过 Zabbix / Prometheus 监控 Keepalived 状态变化,第一时间发现异常。
十四、实战:Keepalived + LVS-DR 高可用集群
🎯 目标:搭建两台 Director(一主一备)+ 两台 Web RS 的高可用负载均衡集群。
实验拓扑
| 角色 | 主机名 | IP |
|---|---|---|
| 客户端 | client1 | 10.1.8.21 |
| Director 1(Master) | web1 | 10.1.8.11 |
| Director 2(Backup) | web2 | 10.1.8.12 |
| VIP | - | 10.1.8.100 |
为了简化,这里将 Keepalived 直接安装在 Web 服务器上(也作为 Director)。
步骤 1:基础环境
bash
# 所有节点设置主机名和网络(略,参考前面 NAT/DR 配置)
# web1 和 web2 安装 Web 服务
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum install -y nginx
echo "Welcome to $(hostname)" > /usr/share/nginx/html/index.html
systemctl enable nginx.service --now
步骤 2:web2(Backup)配置 Keepalived
bash
yum install -y keepalived
cp /etc/keepalived/keepalived.conf{,.ori}
nginx
! Configuration File for keepalived
global_defs {
router_id web2 # 唯一标识
}
vrrp_instance nginx {
state BACKUP # 备节点
interface ens33 # 绑定网卡
virtual_router_id 51 # VRID,主备必须一致
priority 100 # 优先级(比 Master 低)
advert_int 1 # 心跳间隔 1 秒
authentication {
auth_type PASS
auth_pass laogao@123
}
virtual_ipaddress {
10.1.8.100/24 # VIP
}
}
bash
systemctl enable keepalived.service --now
# 验证:web2 上有 VIP(因为目前只有它一个,自动成为 Master)
ip -br a show ens33
# ens33 UP 10.1.8.12/24 10.1.8.100/24 ...
步骤 3:web1(Master)配置 Keepalived
nginx
! Configuration File for keepalived
global_defs {
router_id web1
}
vrrp_instance nginx {
state MASTER # 主节点
interface ens33
virtual_router_id 51
priority 110 # 优先级 110 > 100,成为 Master
advert_int 1
authentication {
auth_type PASS
auth_pass laogao@123
}
virtual_ipaddress {
10.1.8.100/24
}
}
bash
systemctl enable keepalived.service --now
# 验证:web1 已抢占 VIP
ip -br a show ens33
# ens33 UP 10.1.8.11/24 10.1.8.100/24 ... ← VIP 在这里!
此时再看 web2:
bash
ip -br a show ens33
# ens33 UP 10.1.8.12/24 ... ← VIP 消失了!(被 web1 抢占)
步骤 4:故障切换测试
bash
# 访问 VIP------请求落在 Master(web1)上
curl 10.1.8.100
# Welcome to web1.laogao.cloud
# ===== 模拟故障:停止 web1 的 Keepalived =====
systemctl stop keepalived.service
# 再次访问------VIP 已漂移到 web2
curl 10.1.8.100
# Welcome to web2.laogao.cloud ← 自动切换成功!
# ===== 恢复 web1 =====
systemctl start keepalived.service
# 访问------VIP 又回到 web1(优先级高,自动抢占)
curl 10.1.8.100
# Welcome to web1.laogao.cloud ← 自动抢回!
✅ 整个切换过程对客户端完全透明,客户端始终访问
10.1.8.100,感知不到后端发生了故障切换。
十五、非抢占模式与高级配置
15.1 非抢占模式(nopreempt)
默认情况下,高优先级的节点恢复后会自动抢回 Master 角色。这在某些场景下可能不合适------比如你正在维护原来的 Master,不希望它刚恢复就又承担流量。
nginx
vrrp_instance nginx {
state BACKUP # 注意:nopreempt 模式下,state 都配 BACKUP
nopreempt # 非抢占模式
priority 110 # 优先级依然影响首次选举
# ...
}
配置要点:
- 所有节点
state都设为BACKUP - 只有优先级更高的那个节点会通过首次选举成为 Master
- 主节点宕机恢复后,不会自动抢占,避免流量震荡
15.2 实战:非抢占模式
nginx
# web1(优先级 110,但 state 也是 BACKUP)
vrrp_instance nginx {
state BACKUP
nopreempt
interface ens33
virtual_router_id 51
priority 110
# ...
}
nginx
# web2(优先级 100)
vrrp_instance nginx {
state BACKUP
interface ens33
virtual_router_id 51
priority 100
# ...
}
测试:
bash
# 初始:web1 优先级高 → 成为 Master,持有 VIP
# 停止 web1 Keepalived → web2 接替,成为 Master
# 启动 web1 Keepalived → web1 因为有 nopreempt,不会抢回!
# web2 继续做 Master,web1 成为 Backup 等待
15.3 配置调试技巧
bash
# 开启调试日志
vim /etc/sysconfig/keepalived
# 修改:
KEEPALIVED_OPTIONS="-D -d -S 0"
# -D:以守护进程运行
# -d:开启详细日志
# -S 0:syslog facility 设为 local0
# 配置独立日志文件
cat > /etc/rsyslog.d/keepalived.conf << EOF
local0.* /var/log/keepalived.log
EOF
systemctl restart rsyslog
systemctl restart keepalived.service
# 实时查看
tail -f /var/log/keepalived.log
15.4 多网卡指定源 IP
当服务器有多块网卡时,需要明确指定 VRRP 通告的源 IP:
nginx
vrrp_instance Nginx {
state MASTER
interface ens36
mcast_src_ip 20.0.0.11 # 明确指定 VRRP 通告的源 IP
virtual_router_id 51
priority 110
# ...
}
📊 总结与架构全景图
LVS + Keepalived 高可用负载均衡完整架构
Internet
│
┌────────▼────────┐
│ 防火墙/路由器 │
└────────┬────────┘
│
┌────────▼────────┐
│ VIP (虚拟IP) │ ← Keepalived 管理 VIP 漂移
└───┬────────┬───┘
│ │
┌─────────▼──┐ ┌──▼─────────┐
│ Director 1 │ │ Director 2 │ ← Keepalived VRRP 主备
│ (Master) │ │ (Backup) │
│ ipvsadm │ │ ipvsadm │ ← LVS 负载均衡
└──────┬─────┘ └──────┬──────┘
│ │
┌─────┼──────────────┼──────┐
│ │ │ │
┌────▼──┐ ┌▼─────┐ ┌────▼──┐ │
│ RS1 │ │ RS2 │ │ RS3 │ │ ← Nginx/Apache/Tomcat
└───────┘ └──────┘ └───────┘ │
└──────────────────────────┘
Real Server Pool
关键要点速记
| 维度 | 要点 |
|---|---|
| LVS 模式选择 | DR 模式 ≈99% 场景首选(高性能、Director 不处理回包) |
| DR 模式关键 | RS 绑定 VIP + ARP 抑制(arp_ignore=1, arp_announce=2) |
| 调度算法 | 无状态→WRR,长连接→WLC |
| Keepalived | VRRP 实现主备 + 健康检查自动踢除/恢复 RS |
| VIP 漂移 | Gratuitous ARP 通知交换机更新 MAC 表 |
| 脑裂防范 | 独立心跳线 + 防火墙放行 + 认证 + 检测脚本 + 监控告警 |
| 非抢占 | 生产建议开启 nopreempt,避免 VIP 频繁漂移 |
📝 学习感悟:LVS 和 Keepalived 是 Linux 运维的"双子星"------LVS 解决"怎么分发",Keepalived 解决"分发者挂了怎么办"。两者结合,构成了互联网公司最经典的四层负载均衡高可用方案。掌握它们,你就拥有了处理百万级并发流量的基础能力。
🔗 本文基于笔者 2026 年 8 月 12 日的学习笔记整理,如有疏漏欢迎指正交流。