「架构积木」LVS速解析:从基本原理到实战配置!

第一部分:原理与核心概念
一、LVS的概念
LVS 全称 Linux Virtual Server,是 Linux 内核层实现的高性能、高可用的负载均衡集群技术,由章文嵩博士开发,目前是 Linux 内核的标准模块之一。它的核心作用是将前端的请求流量分发到后端多台真实服务器(Real Server)上,从而提升服务的并发处理能力和可用性。
官网:http://www.linuxvirtualserver.org/
相关术语:
-
VS:Virtual Server,负责调度
-
RS:Real Server,负责真正提供服务
二、集群和分布式简介
2.1 系统性能扩展方式
| 方式 | 说明 |
|---|---|
| Scale UP(向上扩展) | 增强单台服务器的硬件能力 |
| Scale Out(向外扩展) | 增加设备数量,通过调度分配解决问题,即集群(Cluster) |
2.2 集群(Cluster)
集群是为了解决某个特定问题,将多台计算机组合起来形成的单个系统。
Cluster 常见的三种类型:
| 类型 | 全称 | 说明 |
|---|---|---|
| LB | Load Balancing(负载均衡) | 由多个主机组成,每个主机只承担一部分访问 |
| HA | High Availability(高可用) | 解决单点故障(SPOF) |
| HPC | High-performance Computing(高性能计算) | 聚合算力,解决超大问题 |
值得注意的是,技术与技术之间可以是相辅相成的。
2.3 分布式
| 类型 | 常见技术 |
|---|---|
| 分布式存储 | Ceph、GlusterFS、FastDFS、MogileFS |
| 分布式计算 | Hadoop、Spark |
| 分布式应用 | 服务按照功能拆分,使用微服务 |
| 分布式静态资源 | 静态资源放在不同的存储集群上 |
| 分布式数据和存储 | 使用 Key-Value 缓存系统 |
2.4 集群和分布式的区别
实际场景:对于大型网站,访问用户很多,实现一个集群,在前面部署一个负载均衡服务器,后面几台服务器完成同一业务。负载均衡器根据后端各服务器的负载情况,决定由哪一台去完成响应,并且一台服务器垮了,其它的服务器可以顶上来。分布式的每一个节点,都完成不同的业务,如果一个节点垮了,那这个业务可能就会失败。
三、LVS运行原理

VS 根据请求报文的目标 IP、目标协议及端口,依据调度算法将其转发至某 RS。
3.1LVS地址类型
| 地址类型 | 全称 | 网络定位 | 承载接口 |
|---|---|---|---|
| CIP | Client IP | 请求发起端 | 客户端网卡 |
| VIP | Virtual IP | 集群对外服务的逻辑地址 | Director 物理网卡(或别名),RS 端根据模式决定是否绑定于 lo 或 dummy 接口 |
| DIP | Director IP | Director 与 RS 通信的源地址 | Director 内网接口 |
| RIP | Real Server IP | RS 业务通信地址 | RS 业务网卡 |
访问流程k:CIP <--> VIP == DIP <--> RIP
在讲清楚LVS 的四种工作模式之前,需要对网络基础技术和OSI七层模型有一定掌握,对于前者,由于涉及不多,在此不再赘述。接下来将会设计到一部分流量封装的内容。
OSI七层模型及各层职能与LVS
| 层级 | 名称 | 核心职能 | 典型协议/标准 | 封装单元(PDU) |
|---|---|---|---|---|
| 7 | 应用层 | 提供用户服务接口,定义应用程序间通信的语义和语法 | HTTP、HTTPS、FTP、SMTP、DNS、SSH | 数据(Data) |
| 6 | 表示层 | 数据格式转换、加密/解密、压缩/解压缩 | TLS/SSL(部分归类)、JPEG、ASCII、MIME | 数据(Data) |
| 5 | 会话层 | 建立、管理和终止会话连接,控制对话的同步与恢复 | NetBIOS、RPC、PPTP、SMB(部分归类) | 数据(Data) |
| 4 | 传输层 | 端到端可靠/不可靠传输,分段/重组,端口寻址,拥塞控制 | TCP、UDP、SCTP | 段(Segment) / 数据报(Datagram) |
| 3 | 网络层 | 跨网络逻辑寻址(IP地址),路由转发,路径选择 | IPv4、IPv6、ICMP、IGMP、IPSec | 包(Packet) / 数据报(Datagram) |
| 2 | 数据链路层 | 相邻节点间物理寻址(MAC地址),封装成帧,差错检测(FCS),介质访问控制 | Ethernet、PPP、Wi-Fi(802.11)、VLAN(802.1Q) | 帧(Frame) |
| 1 | 物理层 | 比特流传输,定义电气、机械、时序和接口特性,信号编码与转换 | 以太网(RJ45)、光纤、USB、蓝牙射频、DSL | 比特(Bit) |
注: TCP/IP模型中,第5、6、7层通常合并为应用层,第3层对应Internet层,第4层对应传输层,第2层对应网络接入层。但在LVS封包拆包分析中,L3(IP)和L4(TCP/UDP)是地址/端口改写的核心操作层,必须显式区分。
封包与拆包顺序
发送端封包(从第7层到第1层)
数据从应用层产生,逐层向下封装,每层在数据前面加上自己的头部(部分层加尾部):
| 步骤 | 层级 | 操作 | 封装后名称 |
|---|---|---|---|
| 1 | 7→5 | 用户产生业务数据,会话/表示层可能做格式转换或加密 | 数据(Data) |
| 2 | 4 | 加上TCP/UDP头(含源端口、目标端口、校验和) | 段(Segment) |
| 3 | 3 | 加上IP头(含源IP地址、目标IP地址、TTL) | 包(Packet) |
| 4 | 2 | 加上帧头(含源MAC地址、目标MAC地址)+ 帧尾校验 | 帧(Frame) |
| 5 | 1 | 转成电/光信号发出去 | 比特流 |
完整结构:[L2帧头][L3 IP头][L4 TCP/UDP头][应用层数据][L2帧尾]
接收端拆包(从第1层到第7层)
接收端从网卡收到信号后,逐层向上剥离头部:
| 步骤 | 层级 | 操作 | 得到内容 |
|---|---|---|---|
| 1 | 1 | 信号转回比特流 | 帧 |
| 2 | 2 | 校验帧尾是否正确 → 剥离帧头和帧尾 → 根据EtherType(0x0800=IP)送给网络层 | IP包 |
| 3 | 3 | 检查目标IP是否为本机 → 剥离IP头 → 根据协议号(6=TCP,17=UDP)送给传输层 | TCP/UDP段 |
| 4 | 4 | 校验校验和 → 剥离TCP/UDP头 → 根据目标端口号送给对应进程 | 应用层数据 |
| 5 | 5→7 | 解密/解压/格式转换 → 交给应用程序 | 原始业务数据 |
LVS与各层的关系
| LVS模式 | 在OSI哪层操作 | 改什么 | 影响转发行为的原理 |
|---|---|---|---|
| NAT | L3 + L4 | 改IP头(目标地址VIP→RIP,响应时源地址RIP→VIP),可能改端口 | 目标IP变了 → 路由表把包送往RS;源IP变了 → 客户端认不出 |
| DR | L2 | 改帧头(目标MAC由VIP_MAC改为RS_MAC),IP层不动 | MAC变了 → 交换机把帧从对应端口转发到RS |
| TUN | L3 | 外层新增一个IP头(SIP=DIP,DIP=RIP),内层IP头不变 | 外层目标IP=RIP → 路由系统跨网段送达RS;到达后解封装还原内层包 |
| FULLNAT | L3 + L4 | 同时改IP头源地址(CIP→DIP)和目标地址(VIP→RIP),端口可改 | 目标RIP → 发往RS;源DIP → RS响应目标为DIP,强制回Director |
针对LVS流量流向的关键结论
| 层级 | 设备依据什么转发 | LVS利用这个做什么 |
|---|---|---|
| L2(MAC地址) | 交换机根据MAC地址把帧从特定端口转发 | DR模式改写DMAC,让交换机把流量定向送到RS |
| L3(IP地址) | 路由器根据目标IP查路由表,决定下一跳 | NAT/TUN/FULLNAT改写或封装IP,让包被路由到RS |
| L4(端口号) | 接收端内核根据目标端口把数据交给对应进程 | 端口映射让VS监听的端口和RS实际监听的端口可以不同 |
四、LVS 的四种工作模式
4.1 NAT 模式
编辑
原理:本质是多目标 IP 的 DNAT,通过将请求报文中的目标地址和目标端口修改为某 RS 的 RIP 和 PORT 实现转发。
本质:NAT模式下,请求流量到达Director后,IPVS在L3层将目标IP从VIP改为RIP,同步更新IP头校验和并重算L4(TCP/UDP)校验和,随后在L2层根据新目标IP(RIP)查询ARP表重新封装帧头(DMAC=RS_MAC),交换机依据DMAC将帧精准转发至RS;RS处理完生成响应包时,因其默认网关指向DIP,L2层封装的目标MAC强制为Director_MAC,从而将响应帧引导回Director,IPVS在L3层将源IP从RIP改回VIP并重算校验和后,经外网网关发往客户端,确保客户端收到的响应源IP与请求目标IP(VIP)一致。
特点:
-
RIP 和 DIP 应在同一个 IP 网络,且应使用私网地址
-
RS 的网关要指向 DIP
-
请求报文和响应报文都必须经由 Director 转发,Director 易于成为系统瓶颈
-
支持端口映射,可修改请求报文的目标 PORT
-
VS 必须是 Linux 系统,RS 可以是任意 OS 系统
4.2 NAT 模式数据逻辑
-
客户端发送访问请求,请求数据包中含有请求来源(CIP)、访问目标地址(VIP)、访问目标端口
-
VS 服务器接收到访问请求做 DNAT,把请求数据包中的目的地由 VIP 换成 RS 的 RIP 和相应端口
-
RS 响应请求,发送响应数据包,包中的响应报文为数据来源(RIP)、响应目标(CIP)
-
VS 服务器接收到响应数据包,改变包中的数据来源(RIP → VIP)
-
VS 服务器把修改过报文的响应数据包回传给客户端
-
LVS 的 NAT 模式接收和返回客户端数据包时都要经过 LVS 的调度机,所以 LVS 的调度机容易阻塞
4.3 DR 模式
DR:Direct Routing,直接路由,LVS 默认模式,应用最广泛。
编辑
原理:通过为请求报文重新封装一个 MAC 首部进行转发,源 MAC 是 DIP 所在的接口的 MAC,目标 MAC 是某 RS 的 RIP 所在接口的 MAC 地址;源 IP/PORT 以及目标 IP/PORT 均保持不变。
本质:DR模式请求方向:Director仅修改L2帧头的目标MAC地址(从Director_MAC改为RS_MAC),L3的IP头(SIP=CIP,DIP=VIP)及L4校验和完全不变,交换机根据DMAC将帧二层转发至RS;RS处理完生成响应包时,因其VIP配置在lo接口且默认网关指向外部路由器而非Director,响应帧以VIP为源地址、CIP为目标地址,L2层直接封装网关MAC经上行链路发出,完全不经过Director。
4.4 DR 模式数据逻辑
在 DR 模式中,RS 接收到访问请求后不需要回传给 VS 调度器,直接把回传数据发送给 client,所以 RS 和 VS 上都要有 VIP。
4.5 DR 模式数据传输过程
-
客户端发送数据帧给 VS 调度主机,帧中内容为:客户端 IP + 客户端的 MAC + VIP + VIP 的 MAC
-
VS 调度主机接收到数据帧后,把帧中的 VIP 的 MAC 改为 RS1 的 MAC,此时帧中的数据为:客户端 IP + 客户端的 MAC + VIP + RS1 的 MAC
-
RS1 得到数据包后做出响应,回传数据包中的数据为:VIP + RS1 的 MAC + 客户端 IP + 客户端 IP 的 MAC
4.6 DR 模式的特点
-
Director 和各 RS 都配置有 VIP
-
确保前端路由器将目标 IP 为 VIP 的请求报文发往 Director
-
解决 VIP 冲突的三种方式:
-
在前端网关做静态绑定 VIP 和 Director 的 MAC 地址
-
在 RS 上使用 arptables 工具
arptables -A IN -d $VIP -j DROP arptables -A OUT -s $VIP -j mangle --mangle-ip-s $RIP
-
在 RS 上修改内核参数以限制 arp 通告及应答级别
-
/proc/sys/net/ipv4/conf/all/arp_ignore -
/proc/sys/net/ipv4/conf/all/arp_announce
-
-
-
RS 的 RIP 可以使用私网地址,也可以是公网地址;RIP 与 DIP 在同一 IP 网络
-
RIP 的网关不能指向 DIP,以确保响应报文不会经由 Director
-
RS 和 Director 要在同一个物理网络
-
请求报文要经由 Director,但响应报文不经由 Director,由 RS 直接发往 Client
-
不支持端口映射(端口不能修改)
-
RS 可使用大多数 OS 系统
DR模式请求方向:Director仅修改L2帧头的目标MAC地址(从Director_MAC改为RS_MAC),L3的IP头(SIP=CIP,DIP=VIP)及L4校验和完全不变,交换机根据DMAC将帧二层转发至RS;RS处理完生成响应包时,因其VIP配置在lo接口且默认网关指向外部路由器而非Director,响应帧以VIP为源地址、CIP为目标地址,L2层直接封装网关MAC经上行链路发出,完全不经过Director。
4.7 TUN 模式
编辑
转发方式:不修改请求报文的 IP 首部(源 IP 为 CIP,目标 IP 为 VIP),而在原 IP 报文之外再封装一个 IP 首部(源 IP 是 DIP,目标 IP 是 RIP),将报文发往挑选出的目标 RS;RS 直接响应给客户端(源 IP 是 VIP,目标 IP 是 CIP)。
TUN 模式数据传输过程:
-
客户端发送请求数据包:源 IP + VIP + dport
-
VS 调度器对数据包重新封装,添加 IP 报文头,新添加的 IP 报文头中包含 TUNSRCIP(DIP)+ TUNDESTIP(RSIP1),发送到 RS1
-
RS 收到 VS 调度器发送的数据包后做出响应,生成的响应报文中包含 SRCIP(VIP)+ DSTIP(CIP)+ port,响应数据包通过网络直接回传给 client
TUN 模式特点:
-
DIP、VIP、RIP 都应该是公网地址
-
RS 的网关一般不能指向 DIP
-
请求报文要经由 Director,但响应不能经由 Director
-
不支持端口映射
-
RS 的 OS 须支持隧道功能
4.8 FULLNAT 模式
编辑
原理:通过同时修改请求报文的源 IP 地址和目标 IP 地址进行转发:
-
CIP → DIP
-
VIP → RIP
特点:
-
VIP 是公网地址,RIP 和 DIP 是私网地址,且通常不在同一 IP 网络;因此,RIP 的网关一般不会指向 DIP
-
RS 收到的请求报文源地址是 DIP,因此只需响应给 DIP;但 Director 还要将其发往 Client
-
请求和响应报文都经由 Director
-
支持端口映射
Warning:此类型 kernel 默认不支持。
4.9 LVS 工作模式总结
| 特性 | NAT 模式 | DR 模式 | TUN 模式 |
|---|---|---|---|
| RS 操作系统 | 不限 | 支持隧道,禁用 ARP | 支持隧道 |
| 调度器和服务器网络 | 同一网络 | 不可跨网络(同一物理网络) | 可跨网络 |
| 调度服务器数量 | 少 | 多 | 多 |
| 服务器数量 | 多 | 多 | 多 |
| RS 服务器网关 | 指向调度器 DIP | 指向路由 | 指向路由 |
总结:
-
LVS-NAT 与 LVS-FULLNAT:请求和响应报文都经由 Director
-
LVS-NAT:RIP 的网关要指向 DIP
-
LVS-FULLNAT:RIP 和 DIP 未必在同一 IP 网络,但要能通信
-
-
LVS-DR 与 LVS-TUN:请求报文要经由 Director,但响应报文由 RS 直接发往 Client
-
LVS-DR:通过封装新的 MAC 首部实现,通过 MAC 网络转发
-
LVS-TUN:通过在原 IP 报文外封装新 IP 头实现转发,支持远距离通信
-
五、LVS 的调度算法
5.1 调度算法类型
ipvs scheduler 根据调度时是否考虑各 RS 当前的负载状态,分为两种:
| 类型 | 说明 |
|---|---|
| 静态方法 | 仅根据算法本身进行调度,不考虑 RS 的负载情况 |
| 动态方法 | 主要根据每 RS 当前的负载状态及调度算法进行调度,Overhead 值较小的 RS 将被调度 |
LVS 内核以独立模块(如 ip_vs_rr.ko、ip_vs_wrr.ko)分别实现每种算法,运行时动态加载。目前 LVS 共支持 13 种调度算法:静态算法 4 种,动态算法 9 种。
5.2 静态调度算法
静态调度算法不评估 RS 的实时负载,仅依据预设规则或请求中的特定字段进行分配决策。
| 算法 | 全称 | 说明 |
|---|---|---|
| RR | Round Robin(轮询) | RS 分别被调度,当 RS 配置有差别时不推荐 |
| WRR | Weighted RR(加权轮询) | 根据 RS 的配置进行加权调度,性能差的 RS 被调度的次数少 |
| SH | Source Hashing(源地址哈希) | 实现 session sticky,将同一源 IP 的请求始终发往第一次挑中的 RS,实现会话绑定 |
| DH | Destination Hashing(目标地址哈希) | 第一次轮询调度至 RS,后续发往同一目标地址的请求始终转发至第一次挑中的 RS,典型使用场景是正向代理缓存场景的负载均衡(如宽带运营商) |
1. RR(Round Robin,轮询)
调度逻辑:按顺序将请求依次轮流分配给各 RS,循环往复。假设服务器集合为 S={S₁,S₂,…,Sₙ},第 i 个请求分配至服务器 S_((i mod n)+1)。
特点:所有 RS 被同等对待,不考虑其容量或实际负载差异。
适用约束:适用于各 RS 硬件配置、处理能力相近的场景。若 RS 配置存在明显差异,性能较差的 RS 会因调度次数与其他 RS 相同而过载,故不推荐使用。
2. WRR(Weighted RR,加权轮询)
调度逻辑:为每台 RS 分配一个整数值权重(weight),权重越高的 RS 在每轮调度中获得越多的请求分配机会。服务器 Sᵢ 的权重为 wᵢ,总权重 W=Σwᵢ,第 i 个请求分配至服务器 Sⱼ,其中 j 满足 Σ{k=1}^{j-1}wₖ < (i mod W) ≤ Σ{k=1}^j wₖ。
特点:权重充当服务器间的比例因子。例如,RS-A 权重为 1、RS-B 权重为 5,则 RS-B 每承接 5 个连接时,RS-A 承接 1 个连接,总分配比例严格为 5:1。权重不参考 RS 的实时负载,仅由管理员根据机器配置预先设定。
适用场景:解决 RR 算法在异构集群中的短板,使高性能 RS 获得更多请求,低性能 RS 获得较少请求,实现资源利用率的合理化。
补充说明:管理员可基于性能监控数据定期调整权重值。但需注意,权重为静态配置,调度过程不会因 RS 瞬时负载变化而动态调整分配比例。
3. SH(Source Hashing,源地址哈希)
调度逻辑:以请求报文的源 IP 地址(CIP)作为哈希函数的输入,计算哈希值后对 RS 总数取模,根据取模结果决定转发至哪台 RS,即服务器索引 = hash(源 IP) mod n。
特点:同一源 IP 地址的请求始终被转发至同一 RS,实现 Session Sticky(会话绑定)。该算法在静态哈希表中查找源 IP 对应的 RS,若服务器可用且未超载则转发,否则返回空。
适用场景:适用于需要保持用户会话状态的场景(如本地存储登录信息、购物车数据),确保同一用户的所有请求均由同一 RS 处理,避免跨服务器导致的会话丢失。
不足:若某 RS 故障,其承载的所有会话需全部迁移至其他 RS,可能引发瞬时负载冲击。在大 NAT 网络下,同一出口 IP 的数万用户全部落入同一台 RS,造成严重负载倾斜。
4. DH(Destination Hashing,目标地址哈希)
调度逻辑:以请求报文的目标 IP 地址(DIP)作为哈希函数的输入,计算哈希值后对 RS 总数取模,根据取模结果决定转发至哪台 RS,即服务器索引 = hash(目标 IP) mod n。
特点:同一目标 IP 的请求始终被转发至同一 RS。首次请求按轮询逻辑选定 RS 后,后续映射关系固定。
适用场景:将发往同一目标地址的请求集中到同一台 RS,提高缓存命中率,避免多台缓存服务器重复缓存相同内容。典型应用于正向代理缓存集群(如宽带运营商缓存加速),当大量用户请求同一目标地址(如同一热门视频的 CDN 节点 IP)时,所有请求均被定向到同一台缓存 RS,大幅减少回源流量。
不足:与 SH 类似,目标服务器故障时会导致其承载的所有请求迁移,可能引发雪崩效应。
5.3 动态调度算法
动态调度算法综合考虑各 RS 当前的实时负载状况,通过计算 Overhead 值选出负载最轻的 RS 承接新请求。
| 算法 | 全称 | 特点 |
|---|---|---|
| LC | Least Connections(最少连接) | 仅比较活跃连接数,不考虑服务器权重差异 |
| WLC | Weighted LC(加权最少连接) | LC 基础上引入权重,LVS 默认算法 |
| SED | Shortest Expection Delay(最短期望延迟) | 高权重服务器优先承接新连接,初始阶段倾向明显 |
| NQ | Never Queue(永不排队) | 首轮强制所有 RS 各分一连接,后续同 SED |
| LBLC | Locality-Based LC(基于局部性的最少连接) | 目标 IP 哈希 + LC 动态调整,缓存场景专用 |
| LBLCR | LBLC with Replication(带复制的 LBLC) | LBLC 基础上增加缓存复制机制,避免迁移丢缓存 |
| FO | Weighted Fail Over(故障转移) | 权重最高的健康 RS 承接全部流量,灰度发布专用 |
| OVF | Overflow-Connection(溢出连接) | 基于权重配额的连接数上限调度,超出则溢出到次高权重 RS |
| MQ | Multiple Queue(多队列) | 按目的端口号将流量分类到不同队列,多队列独立调度 |
动态算法公式通用前置变量说明:
| 变量 | 含义 |
|---|---|
activeconns |
当前与 RS 保持活跃 TCP 连接的数量(ESTABLISHED 状态) |
inactiveconns |
当前与 RS 处于非活跃状态的连接数(如 TIME_WAIT) |
weight |
RS 的权重值,由管理员根据机器配置手动设定 |
1. LC(Least Connections,最少连接)
调度逻辑:选择 Overhead 值最小的 RS。
公式:Overhead = activeconns × 256 + inactiveconns
特点:activeconns 乘以 256 的目的是放大活跃连接数在 Overhead 中的权重,使其主导负载评估。inactiveconns 权重较低,仅在活跃连接数相同的情况下作为辅助比较项。
适用场景:长连接应用(如数据库连接池、WebSocket 服务)。此类场景中,每台 RS 维护的长连接数量直接反映其承载压力,活跃连接数越少代表该 RS 越空闲。
不足:未考虑 RS 间的硬件性能差异,在异构集群中无法实现按能力分配流量。
2. WLC(Weighted LC,加权最少连接)—— LVS 默认调度算法
调度逻辑:选择 Overhead 值最小的 RS。
公式:Overhead = (activeconns × 256 + inactiveconns) / weight
特点:在 LC 的基础上引入权重作为分母,实现单位权重下的负载评估。高性能 RS(权重高)即使绝对连接数多于低性能 RS(权重低),其单位权重负载仍可能更低,从而承接更多请求。由于每次调度都需计算各 RS 的 Overhead 并比较,调度开销随 RS 数量增加而线性增长。
适用场景:适用于绝大多数通用业务场景,兼顾了连接数和服务器硬件差异,是生产环境中最常用的调度算法。
不足:在 RS 数量较大(如超过 50 台)时,遍历所有 RS 计算 Overhead 会产生一定调度延迟。
3. SED(Shortest Expectation Delay,最短期望延迟)
调度逻辑:选择 Overhead 值最小的 RS。
公式:Overhead = (activeconns + 1 + inactiveconns) × 256 / weight
特点:分子中的 +1 代表假设新连接已经被分配进来后的预期负载,而非当前负载。这使得权重高的 RS 在初始阶段(所有 RS 连接数均为 0 时)因分母较大而获得更小的 Overhead 值,从而被优先调度。权重越高的 RS,前期的调度优先级越明显。当 node1 权重为 1、node2 权重为 10 时,初始阶段的绝大部分新连接将被调度至 node2,直至 node2 的连接数增长使其单位权重负载接近 node1 的水平。
适用场景:适合 RS 处理能力差异较大的集群,希望高权重 RS 快速承接流量、缩短新连接响应时间的场景。
不足:集群启动或扩容时,低权重 RS 可能长时间处于空闲状态,出现调度"饥饿"现象。
4. NQ(Never Queue,永不排队)
调度逻辑:第一轮所有 RS 按权重轮询分配,确保每台 RS 至少被分配到一个连接(按权重比例),不出现空闲 RS;从第二轮起完全按照 SED 算法进行调度。
特点:解决 SED 算法在集群刚启动时可能出现的"饥饿"问题——低权重 RS 因 Overhead 值较大而长时间得不到新连接。NQ 通过首轮强制分配,保证每台 RS 立即承接流量。
适用场景:与 SED 相同,但需要避免低权重 RS 被"饿死"的场景,如集群启动或扩容后需所有 RS 快速预热。
不足:首轮强制分配可能将请求发往处理能力较低的 RS,若首轮请求量较大可能导致部分 RS 响应变慢。
5. LBLC(Locality-Based LC,基于局部性的最少连接)
调度逻辑:
-
某一目标 IP(DIP)首次被请求时,按 LC 算法选择一台 RS 承接,并建立目标 IP → RS 的映射关系
-
同一目标 IP 的后续请求,优先查找映射表转发至同一 RS(保障缓存命中)
-
若该 RS 的当前负载超过预设阈值,则重新按 LC 算法选择一台负载更轻的 RS,并更新映射
特点:在 DH 的"同一目标 IP 始终到同一 RS"基础上,引入负载均衡动态调整能力,避免因某目标 IP 请求量暴增导致对应 RS 过载。负载阈值由内核参数 /proc/sys/net/ipv4/vs/lblc_expiration 控制,默认值为 24 小时,超过该时间映射缓存过期。
适用场景:正向代理缓存集群,既要利用局部性原理(同一目标 IP 的内容集中在同一 RS 上)提升缓存命中率,又要防止热点目标 IP 导致单台 RS 被压垮。
不足:当某 RS 负载过高触发迁移时,目标 IP 对应的缓存数据在新 RS 上不存在,需重新回源拉取,会导致短暂的回源高峰。
6. LBLCR(LBLC with Replication,带复制功能的 LBLC)
调度逻辑:
-
当某目标 IP 对应的 RS 负载过重时,LBLC 的做法是直接迁移到另一台 RS(导致缓存失效需重新回源)
-
LBLCR 的做法是:先将该 RS 上对应目标 IP 的缓存数据复制到负载最轻的 RS,然后建立目标 IP 到多台 RS 的映射关系
-
后续发往该目标 IP 的请求,可在原 RS 与复制 RS 之间进行负载分担,调度时选择其中负载较轻者
特点:通过数据复制机制避免 LBLC 中因迁移导致的缓存失效问题,同时实现多 RS 之间的负载分担。复制操作实际依赖 RS 自身的缓存同步机制(如 ATS、Squid 的 peer 同步),LVS 仅提供调度层面的多服务器映射支持。
适用场景:缓存命中率要求较高的正向代理集群,不能接受因迁移导致的大量缓存失效和回源。
不足:缓存复制需要额外的网络带宽和存储开销,且多 RS 映射关系增加了调度器的状态维护成本。
7. FO(Weighted Fail Over,加权故障转移)—— 4.15 内核新增
调度逻辑:遍历虚拟服务所关联的 RS 链表,筛选出未设置过载标志(IP_VS_DEST_F_OVERLOAD)的 RS,从中选出权重最高的那台作为调度目标。若该 RS 被标记过载,调度器跳过该 RS,选择权重次高的 RS。
特点:不是多路均衡,而是单路集中 + 故障切换。所有流量全部转发给权重最高的健康 RS,直到该 RS 被管理员手动标记过载。此过程不评估连接数或响应延迟,唯一判定依据是 RS 是否被标记了过载标志。过载标记需由外部监控系统或管理员手动设置,LVS 本身不自动标记。
算例:RS-A 权重 10(正常),RS-B 权重 8(正常),RS-C 权重 5(正常)。当前所有请求 → RS-A。RS-A 被打上过载标记后,所有请求 → RS-B(权重次高)。RS-B 也过载后,所有请求 → RS-C。
适用场景:灰度发布。新版本 RS 权重最高,所有流量先切到新版本测试,有问题时通过脚本标记过载快速切回旧版本。
与 WRR 的区别:WRR 按权重比例分配流量,多台 RS 同时分担负载;FO 是"先全部给 A,A 不行再全部给 B"的轮转模式。
与 FW 标记的关联:FO 算法常与防火墙标记配合,将多端口服务绑定后统一按故障转移模式调度。
8. OVF(Overflow-Connection,溢出连接)—— 4.15 内核新增
调度逻辑:
-
遍历 RS 链表,筛选出同时满足以下条件的 RS:未过载(未设置
IP_VS_DEST_F_OVERLOAD)、当前活动连接数 < 权重值、权重值不为 0 -
在满足条件的 RS 中,选权重最高的那台
-
当该 RS 的 active >= weight 时,它被"溢出",新请求选择下一个权重次高且满足 active < weight 的 RS
特点:每台 RS 的调度配额上限 = weight(权重值)。当 RS 的活动连接数达到其权重上限后,新连接开始流向次高权重的 RS。比 WLC 更接近"按权重配额调度",与 WLC 的区别在于阈值判定是硬性的——WLC 是实时计算 Overhead 做加权均衡,只要 Overhead 最低就会持续接收连接;OVF 则是连接数一旦达到权重值即切走,不再继续接收。
算例:RS-A weight=10,当前 active=8,active(8) < weight(10) → 可接收;RS-B weight=5,当前 active=3,active(3) < weight(5) → 可接收。调度顺序:第 1-10 个请求全部给 RS-A(权重最高,且 active 未超过 10);第 11 个请求到达时 RS-A 的 active=10,等于 weight,溢出,选择 RS-B;RS-B 持续接收直到其 active=5 后溢出。
适用场景:需要严格按权重配额控制每台 RS 连接数的场景,防止单台 RS 连接数超过预设上限。
9. MQ(Multiple Queue,多队列调度)—— 4.15 内核新增
调度逻辑:按请求报文的目标端口号将流量分类到不同的队列中。每个目标端口对应一个独立的虚拟服务,每个虚拟服务独立关联一组后端 RS,且各队列可采用不同的调度算法(如队列 A 用 RR,队列 B 用 WLC)。
特点:同一端口号的所有请求在同一队列中按既定算法调度,不同端口号的请求完全隔离。例如,80 端口的请求仅在后端 80 端口 RS 组中调度,443 端口的请求仅在后端 443 端口 RS 组中调度——与防火墙标记的作用相反:防火墙标记是将多个端口捆绑为一个服务统一调度,MQ 是将不同端口拆分为独立队列隔离调度。
适用场景:多业务隔离。不同端口承载不同业务(如 80 端口是 Web、3306 端口是数据库、6379 端口是缓存),希望各业务使用独立的 RS 组和独立的调度策略,互不影响。
与 FWM 的对比:防火墙标记适用于需要把多个端口捆绑为一个服务的场景(如 Web 服务的 80/443 必须同一会话)。MQ 适用于需要把不同端口严格隔离为独立调度域的场景(如数据库和 Web 服务在同一 VIP 上但后端 RS 组不同)。
注意事项:MQ 与防火墙标记(FWM)存在互斥关系:同一个虚拟服务不能同时使用 -f(防火墙标记)和 MQ 特性。若使用了防火墙标记将多个端口捆绑,则 MQ 的端口隔离功能被覆盖。
5.4 算法选用核心原则
-
RS 配置相同 → 静态算法(RR)即可,无需引入动态计算开销
-
RS 配置不同 → 动态算法(WLC/SED)结合权重,按能力分配
-
长连接 → 动态算法(LC/WLC)优先,active 连接数更准确反映真实压力
-
缓存场景 → 哈希类算法(SH/DH)或局部性算法(LBLC/LBLCR),提高缓存命中率
-
灰度发布 → FO 算法,将流量集中到指定服务器,快速验证和回滚
-
多业务隔离 → MQ 算法,不同端口使用独立 RS 组和调度策略
-
严格配额调度 → OVF 算法,控制每台 RS 的连接数上限
-
新集群冷启动 → SED 或 NQ,高权重 RS 快速承接流量,低权重 RS 逐渐参与
-
不知如何选 → WLC(LVS 默认),适用绝大多数业务场景
对于LVS算法,应该熟练掌握,烂熟于心。
第二部分:基础操作命令
六、LVS 软件相关信息
| 项目 | 内容 |
|---|---|
| 程序包 | ipvsadm |
| Unit File | ipvsadm.service |
| 主程序 | /usr/sbin/ipvsadm |
| 规则保存工具 | /usr/sbin/ipvsadm-save |
| 规则重载工具 | /usr/sbin/ipvsadm-restore |
| 配置文件 | /etc/sysconfig/ipvsadm-config |
| ipvs 调度规则文件 | /etc/sysconfig/ipvsadm |
| IPVS 规则查看 | /proc/net/ip_vs |
| IPVS 连接查看 | /proc/net/ip_vs_conn |
七、ipvsadm 命令详解
7.1 核心功能
-
集群服务管理:增、删、改
-
集群服务的 RS 管理:增、删、改
-
查看
7.2 命令参数
管理集群服务:
ipvsadm -A|-E -t|u|f service-address [-s scheduler] [-p [timeout]] [-M netmask] [--pe persistence_engine] [-b sched-flags] ipvsadm -D -t|u|f service-address # 删除 ipvsadm -C # 清空所有规则 ipvsadm -R # 重载规则 ipvsadm -S [-n] # 保存规则
参数说明:
| 参数 | 说明 |
|---|---|
-A |
添加虚拟服务 |
-E |
修改虚拟服务 |
-D |
删除虚拟服务 |
-t |
TCP 服务 |
-u |
UDP 服务 |
-f |
FireWall Mark(防火墙标记),是一个数字 |
-s |
指定调度算法,默认为 WLC |
-p |
设置持久连接超时(秒),持久连接可以理解为在同一个时间段同一个来源的请求调度到同一 RealServer |
-C |
清空所有规则 |
-R |
重载规则 |
-S [-n] |
保存规则 |
管理集群中的 Real Server:
ipvsadm -a|-e -t|u|f service-address -r server-address [-g|-i|-m] [-w weight] ipvsadm -d -t|u|f service-address -r server-address # 删除 RS ipvsadm -L|l [options] # 查看 RS
参数说明:
| 参数 | 说明 |
|---|---|
-a |
添加 RealServer |
-e |
更改 RealServer |
-d |
删除 RealServer |
-r |
RealServer 地址 |
-g |
直连路由模式(DR 模式) |
-i |
IPIP 隧道模式(TUN 模式) |
-m |
NAT 模式 |
-w |
设定权重 |
-Z |
清空计数器 |
-C |
清空 LVS 策略 |
-L / -l |
查看 LVS 策略 |
-n |
不做解析(显示 IP 数字) |
--rate |
输出速率信息 |
7.3 LVS 集群中的增删改示例
1. 管理集群服务中的增删改
# 添加 [root@DR-server ~]# ipvsadm -A -t 172.25.254.100:80 -s rr [root@DR-server ~]# ipvsadm -A -f 66 -p 3000 # 修改 [root@DR-server ~]# ipvsadm -E -t 172.25.254.100:80 -s wrr -p 3000 # 删除 [root@DR-server ~]# ipvsadm -D -t 172.25.254.100:80 [root@DR-server ~]# ipvsadm -D -f 66
2. 管理集群中 RealServer 的增删改
# 添加 [root@DR-server ~]# ipvsadm -a -t 172.25.254.100:80 -r 192.168.0.30 -m [root@DR-server ~]# ipvsadm -a -t 172.25.254.100:80 -r 192.168.0.40 -m -w 2 # 更改 [root@DR-server ~]# ipvsadm -e -t 172.25.254.100:80 -r 192.168.0.30 -m -w 1 [root@DR-server ~]# ipvsadm -e -t 172.25.254.100:80 -r 192.168.0.30 -i -w 1 # 删除 [root@DR-server ~]# ipvsadm -d -t 172.25.254.100:80 -r 192.168.0.30 # 查看 [root@DR-server ~]# ipvsadm -Ln [root@DR-server ~]# ipvsadm -Ln --rate
--rate 输出示例:
IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port CPS InPPS OutPPS InBPS OutBPS -> RemoteAddress:Port TCP 172.25.254.100:80 0 0 0 0 0 -> 192.168.0.30:80 0 0 0 0 0 -> 192.168.0.40:80 0 0 0 0 0
速率指标说明:
-
CPS:每秒连接数,表示服务器处理新连接的速率
-
InPPS:每秒入站数据包数量,从客户端发送到负载均衡器的数据包速率
-
OutPPS:每秒出站数据包数量,从负载均衡器向后端服务器或客户端发送数据包的速率
-
InBPS:每秒入站流量(字节),从客户端到服务器的流量速率
-
OutBPS:每秒出站流量(字节),从服务器到客户端的流量速率
清空计数器:
[root@DR-server ~]# ipvsadm -Z -t 172.25.254.20:80 [root@DR-server ~]# ipvsadm -Ln --rate
清空所有策略:
[root@DR-server ~]# ipvsadm -C
LVS 规则保存的注意事项
LVS 的所有调度规则由内核模块 ip_vs 维护,存储在内核态内存中,而非写入磁盘。ipvsadm 命令操作的是内存中的规则,重启后全部丢失,必须手动保存至硬盘文件才能持久化。
规则持久化的三种操作
| 操作需求 | 命令 | 说明 |
|---|---|---|
| 保存内存规则到硬盘 | ipvsadm-save > /etc/sysconfig/ipvsadm |
改完规则必须执行这一步,否则重启丢失 |
| 从硬盘恢复规则到内存 | ipvsadm-restore < /etc/sysconfig/ipvsadm |
内存规则被误删(ipvsadm -C)后用此恢复 |
| 开机自动加载 | systemctl enable ipvsadm.service |
前提是 /etc/sysconfig/ipvsadm 文件已有内容 |
| 查看当前内存规则 | ipvsadm -Ln |
查看目前生效的规则 |
| 清空内存所有规则 | ipvsadm -C |
仅清空内存,不影响硬盘文件 |
| 查看服务状态 | systemctl status ipvsadm.service |
若启动报错,说明硬盘规则文件为空 |
注意事项
如果只执行了 ipvsadm -A 添加规则,没有执行 ipvsadm-save 保存,那么 /etc/sysconfig/ipvsadm 文件是空的。此时执行 systemctl enable --now ipvsadm.service,服务启动时读不到任何规则,会报错 control process exited。
记住:ipvsadm 操作的是内存,ipvsadm-save 才是把内存内容写入硬盘。两者缺一不可。
正确工作顺序
修改规则(ipvsadm -A/-a)→ 验证规则(ipvsadm -Ln)→ 保存规则(ipvsadm-save)→ 启用开机自启(systemctl enable)
第三部分:LVS的基础入门实验
八、部署 NAT 模式集群示例
8.1 实验要求
-
Director 服务器采用双网卡:桥接网卡连接外网,仅主机网卡与后端 Web 服务器相连
-
Web 服务器采用仅主机网卡与 Director 相连
-
Web 服务器网关指向
192.168.0.100 -
后端 Web 服务器不需要连接外网
8.2 实验环境
| 主机名 | IP | VIP | 角色 |
|---|---|---|---|
| node1 | 192.168.0.100 | 172.25.254.100 | 调度器(VS) |
| node2 | 192.168.0.101,GW 192.168.0.100 | null | 真实服务器(RS) |
| node3 | 192.168.0.102,GW 192.168.0.100 | null | 真实服务器(RS) |
| node4 | 172.25.254.104 | null | 测试机 |
8.3 配置命令与终端回显
步骤 1:在 node1 中启用内核路由功能
bash
[root@node1 ~]# echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/ip_forward.conf [root@node1 ~]# sysctl --system * Applying /etc/sysctl.d/ip_forward.conf ... net.ipv4.ip_forward = 1 * Applying /etc/sysctl.conf ... * Applying /etc/sysctl.d/99-sysctl.conf ... * Applying /etc/sysctl.d/50-default.conf ... [root@node1 ~]# sysctl net.ipv4.ip_forward net.ipv4.ip_forward = 1
步骤 2:在 node1 中安装 ipvsadm
bash
[root@node1 ~]# yum install ipvsadm -y Last metadata expiration check: 0:10:23 ago on Mon 28 Jul 2026 09:30:01 AM CST. Dependencies resolved. ================================================================================ Package Architecture Version Repository Size ================================================================================ Installing: ipvsadm x86_64 1.31-1.el9 baseos 65 k Transaction Summary ================================================================================ Install 1 Package Total download size: 65 k Installed size: 143 k Downloading Packages: ipvsadm-1.31-1.el9.x86_64.rpm 1.2 MB/s | 65 kB 00:00 Running transaction check Transaction check succeeded. Running transaction test Transaction test succeeded. Running transaction Preparing : 1/1 Installing : ipvsadm-1.31-1.el9.x86_64 1/1 Running scriptlet: ipvsadm-1.31-1.el9.x86_64 1/1 Verifying : ipvsadm-1.31-1.el9.x86_64 1/1 Installed: ipvsadm-1.31-1.el9.x86_64 Complete!
步骤 3:在 node1 中添加调度策略(NAT 模式,统一加 -m)
bash
[root@node1 ~]# ipvsadm -A -t 172.25.254.100:80 -s rr [root@node1 ~]# ipvsadm -a -t 172.25.254.100:80 -r 192.168.0.101:80 -m -w 1 [root@node1 ~]# ipvsadm -a -t 172.25.254.100:80 -r 192.168.0.102:80 -m -w 1
(命令无任何输出,静默成功)
步骤 4:查看策略
bash
[root@node1 ~]# ipvsadm -Ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 172.25.254.100:80 rr -> 192.168.0.101:80 Masq 1 0 0 -> 192.168.0.102:80 Masq 1 0 0
若显示
Route,说明误用了-g参数,需删除重加。
查看内核中的规则:
bash
[root@node1 ~]# cat /proc/net/ip_vs IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP AC19FE64:0050 rr -> C0A80066:0050 Masq 1 0 0 -> C0A80065:0050 Masq 1 0 0
查看连接追踪表(有访问后查看):
bash
[root@node1 ~]# cat /proc/net/ip_vs_conn protoname source sport dest dport state expire TCP 172.25.254.104 12345 172.25.254.100 80 TIME_WAIT 120 TCP 172.25.254.104 12346 172.25.254.100 80 ESTABLISHED 180
步骤 5:保存规则(关键!修复 systemctl 报错的根源)
bash
[root@node1 ~]# ipvsadm-save > /etc/sysconfig/ipvsadm-config [root@node1 ~]# cat /etc/sysconfig/ipvsadm-config -A -t 172.25.254.100:80 -s rr -a -t 172.25.254.100:80 -r 192.168.0.101:80 -m -w 1 -a -t 172.25.254.100:80 -r 192.168.0.102:80 -m -w 1
步骤 6:删除所有规则
bash
[root@node1 ~]# ipvsadm -C [root@node1 ~]# ipvsadm -Ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn
步骤 7:重新加载规则
bash
[root@node1 ~]# ipvsadm-restore < /etc/sysconfig/ipvsadm-config [root@node1 ~]# ipvsadm -Ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 172.25.254.100:80 rr -> 192.168.0.101:80 Masq 1 0 0 -> 192.168.0.102:80 Masq 1 0 0
步骤 8:开机启动(保存 + enable)
bash
[root@node1 ~]# cp /etc/sysconfig/ipvsadm-config /etc/sysconfig/ipvsadm
[root@node1 ~]# systemctl enable --now ipvsadm.service
Created symlink /etc/systemd/system/multi-user.target.wants/ipvsadm.service → /usr/lib/systemd/system/ipvsadm.service.
[root@node1 ~]# systemctl status ipvsadm.service
● ipvsadm.service - Initialise the Linux Virtual Server
Loaded: loaded (/usr/lib/systemd/system/ipvsadm.service; enabled; preset: disabled)
Active: active (exited) since Mon 2026-07-28 10:15:22 CST; 5s ago
Process: 12345 ExecStart=/usr/lib/systemd/scripts/ipvsadm start (code=exited, status=0/SUCCESS)
Main PID: 12345 (code=exited, status=0/SUCCESS)
CPU: 12ms
步骤 9:测试(在 node4 上执行)
bash
[Administrator.WIN-20240602BIS] ~$ for N in {1..6}; do curl 172.25.254.100; done
RS2 server - 192.168.0.102
RS1 server - 192.168.0.101
RS2 server - 192.168.0.102
RS1 server - 192.168.0.101
RS2 server - 192.168.0.102
RS1 server - 192.168.0.101
步骤 10:修改为权重调用算法(wrr)
bash
[root@node1 ~]# ipvsadm -E -t 172.25.254.100:80 -s wrr [root@node1 ~]# ipvsadm -e -t 172.25.254.100:80 -r 192.168.0.101:80 -m -w 2 [root@node1 ~]# ipvsadm -e -t 172.25.254.100:80 -r 192.168.0.102:80 -m -w 1 [root@node1 ~]# ipvsadm-save > /etc/sysconfig/ipvsadm
测试效果(在 node4 上执行):
bash
[Administrator.WIN-20240602BIS] ~$ for N in {1..6}; do curl 172.25.254.100; done
RS1 server - 192.168.0.101
RS1 server - 192.168.0.101
RS2 server - 192.168.0.102
RS1 server - 192.168.0.101
RS1 server - 192.168.0.101
RS2 server - 192.168.0.102
8.4 注意事项
-
内核转发必须开启,否则 Director 无法转发数据包。
-
RS 的网关必须指向 Director 的内网 IP(192.168.0.100)。
-
NAT 模式下,请求和响应都经过 Director,Director 可能成为瓶颈。
-
保存规则文件
/etc/sysconfig/ipvsadm是 systemctl 启动时读取的默认路径。
NAT 模式实验常见排错表格整理
| 报错现象 | 根本原因 | 解决方案 |
|---|---|---|
systemctl enable --now ipvsadm.service 报错退出 |
只加规则没保存,/etc/sysconfig/ipvsadm 为空 |
先 ipvsadm-save > /etc/sysconfig/ipvsadm,再执行 systemctl enable --now ipvsadm.service |
ipvsadm -Ln 显示 Route 而非 Masq |
添加 RS 时漏了 -m 或错用 -g |
删除错误规则,用 -m 重新添加 RS |
| curl 请求无响应或超时 | Director 未开启 IP 转发 | sysctl net.ipv4.ip_forward 输出应为 1;若为 0,检查 /etc/sysctl.d/ip_forward.conf |
| curl 请求无响应或超时 | RS 网关未指向 Director 内网 IP | RS 网关必须配置为 Director 内网 IP(实验环境为 192.168.0.100) |
| 测试机无法访问 VIP | 测试机网关未指向 Director 外网 IP | 配置测试机网关为 Director 外网 IP(实验环境为 172.25.254.100) |
| 修改权重后重启失效 | 修改后未重新保存 | 执行 ipvsadm-save > /etc/sysconfig/ipvsadm |
九、部署 DR 模式集群示例
9.1 实验环境
编辑
| 主机名 | IP | VIP | 角色 |
|---|---|---|---|
| client | 172.25.254.10(NAT 网络) | null | 测试主机 |
| router | NAT-eth0:172.25.254.100,仅主机-eth1:192.168.0.10 | null | 路由器 |
| lvs | 192.168.0.200,GW 192.168.0.10(仅主机) | lo:192.168.0.100 | 调度器 |
| RS1 | 192.168.0.101,GW 192.168.0.10(仅主机) | lo:192.168.0.100 | Web 服务器 1 |
| RS2 | 192.168.0.102,GW 192.168.0.10(仅主机) | lo:192.168.0.100 | Web 服务器 2 |
9.2 配置实验环境
1. 在客户端主机中配置 NAT 模式网卡
bash
[root@client ~]# vim /etc/NetworkManager/system-connections/eth0.nmconnection [connection] id=eth0 type=ethernet interface-name=eth0 [ipv4] method=manual address1=172.25.254.10/24,172.25.254.100 [root@client ~]# nmcli c reload [root@client ~]# nmcli c up eth0 连接已成功激活 [root@client ~]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 172.25.254.100 0.0.0.0 UG 100 0 0 eth0 172.25.254.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
2. 在路由主机中设定双网卡(eth0 为 NAT,eth1 为仅主机)
bash
[root@router ~]# vim /etc/NetworkManager/system-connections/eth0.nmconnection [connection] id=eth0 type=ethernet interface-name=eth0 [ipv4] method=manual address1=172.25.254.100/24 [root@router ~]# vim /etc/NetworkManager/system-connections/eth1.nmconnection [connection] id=eth1 type=ethernet interface-name=eth1 [ipv4] method=manual address1=192.168.0.10/24 [root@router ~]# nmcli c reload [root@router ~]# nmcli c up eth0 [root@router ~]# nmcli c up eth1
3. 配置 LVS 调度器(仅主机模式)
bash
[root@lvs ~]# vim /etc/NetworkManager/system-connections/eth0.nmconnection [connection] id=eth0 type=ethernet interface-name=eth0 [ipv4] method=manual address1=192.168.0.200/24,192.168.0.10 [root@lvs ~]# nmcli c reload [root@lvs ~]# nmcli c up eth0 连接已成功激活 [root@lvs ~]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.0.10 0.0.0.0 UG 100 0 0 eth0 192.168.0.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
设定 VIP 地址
bash
[root@lvs ~]# vim /etc/NetworkManager/system-connections/lo.nmconnection [connection] id=lo type=loopback interface-name=lo [ipv4] method=manual address1=127.0.0.1/8 address2=192.168.0.100/32 [root@lvs ~]# nmcli c reload [root@lvs ~]# nmcli c up lo 连接已成功激活
4. 设定 RS1
bash
[root@rs1 ~]# vim /etc/NetworkManager/system-connections/eth0.nmconnection [connection] id=eth0 type=ethernet interface-name=eth0 [ipv4] method=manual address1=192.168.0.101/24,192.168.0.10 [root@rs1 ~]# nmcli c reload [root@rs1 ~]# nmcli c up eth0 连接已成功激活 [root@rs1 ~]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.0.10 0.0.0.0 UG 100 0 0 eth0 192.168.0.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
设定 VIP 地址(⚠️ 修正:RS 上的 VIP 必须和 LVS 上的 VIP 一致,是 192.168.0.100,不是 192.168.0.200)
bash
[root@rs1 ~]# vim /etc/NetworkManager/system-connections/lo.nmconnection [connection] id=lo type=loopback interface-name=lo [ipv4] method=manual address1=127.0.0.1/8 address2=192.168.0.100/32 [root@rs1 ~]# nmcli c reload [root@rs1 ~]# nmcli c up lo 连接已成功激活
5. 设定 RS2
bash
[root@rs2 ~]# vim /etc/NetworkManager/system-connections/eth0.nmconnection [connection] id=eth0 type=ethernet interface-name=eth0 [ipv4] method=manual address1=192.168.0.102/24,192.168.0.10 [root@rs2 ~]# nmcli c reload [root@rs2 ~]# nmcli c up eth0 连接已成功激活 [root@rs2 ~]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.0.10 0.0.0.0 UG 100 0 0 eth0 192.168.0.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
设定 VIP 地址(⚠️ 修正:必须绑定 192.168.0.100,不是 192.168.0.200)
bash
[root@rs2 ~]# vim /etc/NetworkManager/system-connections/lo.nmconnection [connection] id=lo type=loopback interface-name=lo [ipv4] method=manual address1=127.0.0.1/8 address2=192.168.0.100/32 [root@rs2 ~]# nmcli c reload [root@rs2 ~]# nmcli c up lo 连接已成功激活
6. 确保每台主机 ping 都可以互相通信。
9.3 解决 VIP 响应问题
DR 模型中各主机上均需要配置 VIP,解决地址冲突的方式有三种:
-
在前端网关做静态绑定
-
在各 RS 使用 arptables
-
在各 RS 修改内核参数,来限制 arp 响应和通告的级别
限制响应级别:arp_ignore
-
0:默认值,表示可使用本地任意接口上配置的任意地址进行响应 -
1:仅在请求的目标 IP 配置在本地主机的接收到请求报文的接口上时,才给予响应
限制通告级别:arp_announce
-
0:默认值,把本机所有接口的所有信息向每个接口的网络进行通告 -
1:尽量避免将接口信息向非直接连接网络进行通告 -
2:必须避免将接口信息向非本网络进行通告
9.4 配置详情
配置要点:
-
Director 服务器采用双 IP 桥接网络,一个是 VIP,一个 DIP
-
Web 服务器采用和 DIP 相同的网段和 Director 连接
-
每个 Web 服务器配置 VIP
-
每个 Web 服务器可以出外网
在 RS1 和 RS2 中解决响应问题:
bash
# RS1 [root@rs1 ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore [root@rs1 ~]# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore [root@rs1 ~]# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce [root@rs1 ~]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce RS2 [root@rs2 ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore [root@rs2 ~]# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore [root@rs2 ~]# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce [root@rs2 ~]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
若未调整 ARP 参数,RS 会响应 VIP 的 ARP 请求,导致客户端请求直接发往 RS 而非 Director,调度完全失效。
在 LVS 中配置策略(DR 模式用 -g):
bash
[root@lvs ~]# ipvsadm -A -t 192.168.0.100:80 -s wrr [root@lvs ~]# ipvsadm -a -t 192.168.0.100:80 -r 192.168.0.101:80 -g -w 1 [root@lvs ~]# ipvsadm -a -t 192.168.0.100:80 -r 192.168.0.102:80 -g -w 1 [root@lvs ~]# ipvsadm -Ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.0.100:80 wrr -> 192.168.0.101:80 Route 1 0 0 -> 192.168.0.102:80 Route 1 0 0
Forward 列显示 Route 表示 DR 模式生效。若显示 Masq,说明误用了 -m 参数。
保存并设置自启:
bash
[root@lvs ~]# ipvsadm-save > /etc/sysconfig/ipvsadm [root@lvs ~]# systemctl enable --now ipvsadm.service Active: active (exited)
测试效果(在 client 执行):
bash
[root@node10 ~]# for N in {1..6}; do curl 192.168.0.100; done
RS2 server - 192.168.0.102
RS1 server - 192.168.0.101
RS2 server - 192.168.0.102
RS1 server - 192.168.0.101
RS2 server - 192.168.0.102
RS1 server - 192.168.0.101
9.5 注意事项
-
RS 上的 VIP 必须绑定在 lo 回环接口,且掩码为
/32,避免与物理接口冲突 -
务必在 RS 上调整 ARP 内核参数,否则 RS 会响应 VIP 的 ARP 请求,导致调度失效
-
DR 模式不支持端口映射,RS 必须使用与 VIP 相同的端口
-
响应报文直接从 RS 返回客户端,Director 只负责请求分发,Director 压力小于 NAT 模式
DR 模式实验常见排错表格整理
| 报错现象 | 根本原因 | 解决方案 |
|---|---|---|
| curl 不通,但 ping VIP 通 | RS 未调整 ARP 参数,RS 响应了 VIP 的 ARP 请求 | RS 执行 echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore、echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce |
| curl 不通,ping VIP 也不通 | RS 的 lo 绑定了错误的 VIP 地址 | RS 的 lo 必须绑定与 LVS 相同的 VIP(实验环境为 192.168.0.100/32) |
ipvsadm -Ln 显示 Masq 而非 Route |
添加 RS 时误用了 -m |
改用 -g 重新添加 |
| 客户端访问 VIP 只有一台 RS 响应 | 客户端 ARP 缓存了某台 RS 的 MAC 地址 | 客户端执行 arp -d 192.168.0.100 清除 ARP 缓存 |
| LVS 本机 curl VIP 不通 | DR 模式特性:本机发起的请求不经过 LVS 转发逻辑 | 属正常现象,需从外部客户端测试 |
十、防火墙标签解决轮询错误
基于 DR 模式实验环境(VIP: 192.168.0.100,RS1: 192.168.0.101,RS2: 192.168.0.102)
10.1 问题背景
当 RS 同时开放 80(HTTP)和 443(HTTPS)端口时,默认 LVS 将两者视为两个独立的虚拟服务,各自独立轮询。这会导致:第一次访问 80 被轮询到 RS1,下一次访问 443 可能被轮询到 RS2——会话错乱。
10.2 配置步骤
步骤 1:在 RS1 和 RS2 中安装 mod_ssl 并重启 httpd
bash
[root@rs1 ~]# yum install mod_ssl -y Complete! [root@rs1 ~]# systemctl restart httpd [root@rs2 ~]# yum install mod_ssl -y Complete! [root@rs2 ~]# systemctl restart httpd
步骤 2:在调度器中添加 80 和 443 的独立调度策略(展示问题)
bash
[root@lvs ~]# ipvsadm -C [root@lvs ~]# ipvsadm -A -t 192.168.0.100:80 -s rr [root@lvs ~]# ipvsadm -A -t 192.168.0.100:443 -s rr [root@lvs ~]# ipvsadm -a -t 192.168.0.100:80 -r 192.168.0.101:80 -g [root@lvs ~]# ipvsadm -a -t 192.168.0.100:80 -r 192.168.0.102:80 -g [root@lvs ~]# ipvsadm -a -t 192.168.0.100:443 -r 192.168.0.101:443 -g [root@lvs ~]# ipvsadm -a -t 192.168.0.100:443 -r 192.168.0.102:443 -g [root@lvs ~]# ipvsadm -Ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.0.100:80 rr -> 192.168.0.101:80 Route 1 0 0 -> 192.168.0.102:80 Route 1 0 0 TCP 192.168.0.100:443 rr -> 192.168.0.101:443 Route 1 0 0 -> 192.168.0.102:443 Route 1 0 0
步骤 3:问题呈现
bash
[root@client ~]# curl http://192.168.0.100; curl -k https://192.168.0.100 RS1 server - 192.168.0.101 RS1 server - 192.168.0.101
80 和 443 各自独立轮询,同一客户端可能被调度到不同 RS,导致会话错乱。
10.3 防火墙标记解决方案
FWM(FireWall Mark) 用于给特定报文打标记,基于标记定义集群服务,将多个端口捆绑为一个服务。
步骤 1:在调度器中打防火墙标记
bash
[root@lvs ~]# iptables -t mangle -A PREROUTING -d 192.168.0.100 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 6666
[root@lvs ~]# iptables -t mangle -L -n -v
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 MARK tcp -- * * 0.0.0.0/0 192.168.0.100 multiport dports 80,443 MARK set 0x1a0a
步骤 2:清空旧规则,基于标记添加调度策略
bash
[root@lvs ~]# ipvsadm -C [root@lvs ~]# ipvsadm -A -f 6666 -s rr [root@lvs ~]# ipvsadm -a -f 6666 -r 192.168.0.101 -g [root@lvs ~]# ipvsadm -a -f 6666 -r 192.168.0.102 -g [root@lvs ~]# ipvsadm -Ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn FWM 6666 rr -> 192.168.0.101:0 Route 1 0 0 -> 192.168.0.102:0 Route 1 0 0
Prot 列显示 FWM,Real Server 端口为 0(表示所有端口),80 和 443 已被捆绑为一个服务。
步骤 3:测试效果
bash
[root@client ~]# curl -k https://192.168.0.100 RS2 server - 192.168.0.102 [root@client ~]# curl -k https://192.168.0.100; curl 192.168.0.100 RS1 server - 192.168.0.101 RS2 server - 192.168.0.102
80 和 443 被捆绑调度,不再出现协议切换时的调度错乱。
10.4 注意事项
-
标记规则在 mangle 表的 PREROUTING 链 上设置
-
标记值(如 6666)自定义,需与
ipvsadm -f参数一致 -
标记规则重启后丢失,需持久化 iptables 规则
-
防火墙标记应始终与持久连接配合使用,以实现会话粘滞
防火墙标记实验常见排错表格整理
| 报错现象 | 根本原因 | 解决方案 |
|---|---|---|
ipvsadm -Ln 看不到 FWM 规则 |
iptables 标记规则未添加或标记值与 -f 不一致 |
确认 iptables -t mangle -A PREROUTING -d VIP -p tcp -m multiport --dports 80,443 -j MARK --set-mark N 中的 N 与 ipvsadm -f N 一致 |
iptables -t mangle -L -n -v 中 MARK 规则 pkts 计数始终为 0 |
没有流量命中标记规则 | 检查客户端能否正常访问 VIP;确认 -d 地址和 --dports 端口配置正确 |
| 80 和 443 仍被独立调度 | 新旧规则并存,未使用 -f 统一调度 |
先 ipvsadm -C 清空,再基于标记 -f 重新添加 |
| 标记规则重启后丢失 | iptables 规则未持久化 | yum install -y iptables-services;service iptables save;systemctl enable iptables |
| curl HTTPS 报证书错误 | 自签名证书未受客户端信任 | 测试环境使用 curl -k 忽略证书验证 |
十一、LVS 持久连接
基于 DR 模式实验环境(VIP: 192.168.0.100,RS1: 192.168.0.101,RS2: 192.168.0.102),在防火墙标记基础上新增持久连接配置。
11.1 问题背景
会话粘滞是指将来自同一个客户端的所有请求,始终转发到同一台 RS,确保用户会话数据不丢失。
无会话粘滞时的问题:
| 请求 | LVS 分配 | 问题 |
|---|---|---|
| 用户第 1 次请求(登录) | → RS1 | 登录状态保存在 RS1 |
| 用户第 2 次请求(查看订单) | → RS2(轮询切换) | RS2 没有登录状态,要求重新登录 |
SH 算法虽能实现会话粘滞,但存在缺陷:负载严重不均(大 NAT 出口下所有用户落入同一台 RS)。
持久连接是更优方案:既能保持会话粘滞,又能配合任意调度算法(RR/WRR/LC/WLC 等)。
11.2 持久连接核心机制
持久连接启用后,LVS 会在指定的超时时间内,将来自同一个源 IP 地址的所有请求,持续转发到第一次分配的那台 RS。
核心参数:-p N,N 为超时时间(秒)。超时从最后一次请求开始计时,持续访问则不断重置。
持久连接工作流程:
-
首次请求:按调度算法选 RS,在连接跟踪表中创建持久连接模板(
pro=IP,state=ASSURED) -
超时时间内:同一源 IP 的后续请求跳过调度算法,直接转发到模板绑定的 RS
-
超时后:模板自动删除,下次请求视为首次请求,重新调度
查看持久连接模板:
bash
[root@lvs ~]# ipvsadm -Lnc IPVS connection entries pro expire state source virtual destination TCP 01:56 FIN_WAIT 172.25.254.10:42420 192.168.0.100:80 192.168.0.102:80 IP 00:57 ASSURED 172.25.254.10:0 0.0.26.10:0 192.168.0.102:0
核心识别特征:
pro=IP且state=ASSURED即为持久连接模板,source中端口为0表示匹配该源 IP 的所有端口。
11.3 配置步骤
步骤 1:确保防火墙标记已配置
bash
[root@lvs ~]# iptables -t mangle -A PREROUTING -d 192.168.0.100 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 6666
步骤 2:配置 LVS 持久连接
bash
[root@lvs ~]# ipvsadm -C [root@lvs ~]# ipvsadm -A -f 6666 -s rr -p 300 [root@lvs ~]# ipvsadm -a -f 6666 -r 192.168.0.101 -g [root@lvs ~]# ipvsadm -a -f 6666 -r 192.168.0.102 -g [root@lvs ~]# ipvsadm -Ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn FWM 6666 rr persistent 300 -> 192.168.0.101:0 Route 1 0 0 -> 192.168.0.102:0 Route 1 0 0
persistent 300 表示持久连接已启用,超时时间为 300 秒(生产环境推荐值)。
步骤 3:验证持久连接效果
在客户端连续发起多次请求:
bash
[root@client ~]# for N in {1..10}; do curl 192.168.0.100; done
RS1 server - 192.168.0.101
RS1 server - 192.168.0.101
RS1 server - 192.168.0.101
RS1 server - 192.168.0.101
RS1 server - 192.168.0.101
RS1 server - 192.168.0.101
RS1 server - 192.168.0.101
RS1 server - 192.168.0.101
RS1 server - 192.168.0.101
RS1 server - 192.168.0.101
虽然调度算法是 RR(轮询),但 10 次请求全部落到 RS1。持久连接生效,调度算法在模板有效期内被完全跳过。
步骤 4:观察连接跟踪表
bash
[root@lvs ~]# ipvsadm -Lnc IPVS connection entries pro expire state source virtual destination IP 00:58 ASSURED 172.25.254.10:0 0.0.26.10:0 192.168.0.101:0 TCP 01:55 FIN_WAIT 172.25.254.10:46222 192.168.0.100:80 192.168.0.101:80
只要 state=ASSURED 的模板记录存在且未超时,该源 IP 后续所有请求都会跳过调度算法,直接转发到 destination 列记录的 RS。
步骤 5:验证超时后重新调度
等待超时时间(300 秒)后:
bash
[root@client ~]# curl 192.168.0.100 RS2 server - 192.168.0.102
持久连接模板超时失效,LVS 重新执行调度算法,此时可能轮询到 RS2。
11.4 生产环境推荐配置
| 配置项 | 推荐值 | 原因 |
|---|---|---|
| 超时时间 | -p 300~600 |
5-10 分钟,覆盖用户一次浏览会话 |
| 调度算法 | -s wlc |
加权最小连接,比 RR 更均衡 |
| 防火墙标记 | 必须配合 | 捆绑 HTTP/HTTPS,防止协议切换丢失会话 |
11.5 注意事项
-
持久连接可配合任意调度算法(RR/WRR/LC/WLC 等),比 SH 算法更灵活
-
防火墙标记应始终与持久连接配合使用,否则 HTTP/HTTPS 仍可能被独立调度
-
超时时间从最后一次请求开始计时,持续访问则不断重置
-
持久连接模板在
ipvsadm -Lnc中显示为pro=IP、state=ASSUREDLVS持久连接实验常见排错表格整理
报错现象 根本原因 解决方案 每次请求都轮询切换,未粘滞 添加虚拟服务时未加 -p参数ipvsadm -E -f N -s rr -p 超时秒数修改,或删除后重新添加ipvsadm -Lnc中看不到pro=IP、state=ASSURED模板记录持久连接未配置,或该源 IP 尚未发起请求 确认 -p已添加;客户端发起至少一次请求后再查看同一客户端 80 和 443 被调度到不同 RS 使用了防火墙标记但未配置持久连接 防火墙标记 -f+ 持久连接-p必须同时使用超时后客户端再次请求表现异常 模板超时后重新调度,属正常行为 如需更长粘滞时间,增大 -p值(生产环境推荐300~600秒)不同客户端也被调度到同一台 RS 多个客户端位于同一 NAT 网关后,源 IP 相同 持久连接基于源 IP,此为特性;需更精细会话保持考虑应用层 Session 共享
十二、部署 TUN 模式集群案例
12.1 从 DR 模式的局限说起
DR 模式要求调度器与所有 RS 必须在同一二层网络内,因为 DR 模式通过修改 MAC 地址转发数据包,而 MAC 地址只在同一广播域内有效。
这个约束带来了两个问题:
-
部署不灵活:RS 必须与调度器在同一个机房、同一个交换机下
-
扩容受限:业务需要跨机房扩容时,DR 模式无法支持
LVS TUN 模式(IP Tunneling,IP 隧道模式)通过 IP 隧道封装技术,将数据包从一个网络"隧道"传输到另一个网络,打破了二层网络的限制。
12.2 TUN 模式核心原理
IP 隧道是一种将整个数据包作为另一个数据包的负载进行封装的技术,即 "包中包":
-
内层数据包:原始的客户端请求包(源 IP=客户端,目标 IP=VIP)
-
外层数据包:调度器新封装的一层 IP 头(源 IP=DIP,目标 IP=RIP)
封装后的数据包可在三层网络(IP 层)中自由路由,不受二层网络限制。
TUN 模式与 DR 模式的本质区别:
| 对比维度 | DR 模式 | TUN 模式 |
|---|---|---|
| 操作层级 | 第 2 层(数据链路层)——改 MAC | 第 3 层(网络层)——IP 隧道封装 |
| 网络要求 | 同一二层网络 | 可跨网段、跨公网 |
| 封装内容 | 不改动 IP 包 | 增加外层 IP 头(包中包) |
12.3 TUN 模式数据流程
-
客户端发出请求:源 IP=客户端,目标 IP=VIP,到达调度器
-
调度器封装:保留原始包不变,新增外层 IP 头(源 IP=DIP,目标 IP=选中的 RIP)
-
网络传输:路由器根据外层目标 IP(RIP)进行三层路由,转发到 RS
-
RS 解封装:RS 内核识别出 IP 隧道包,剥掉外层 IP 头,露出内层包
-
RS 处理请求:内核检查目标 IP=VIP(绑在
tunl0上),交给应用 -
RS 直接响应客户端:响应包源 IP=VIP,目标 IP=客户端,不经过调度器
12.4 实验环境
| 主机名 | 网卡 | IP 地址 | 网关 | 角色 |
|---|---|---|---|---|
| router | eth0 | 172.25.254.100/24 | - | 路由器(外网侧) |
| router | eth1 | 192.168.0.100/24 | - | 路由器(内网侧) |
| client | eth0 | 172.25.254.99/24 | 172.25.254.100 | 客户端 |
| vsnode | eth0 | 192.168.0.50/24 | 192.168.0.100 | LVS 调度器 |
| vsnode | eth0:0 | 172.25.254.200/32 | - | VIP(调度器物理网卡别名) |
| RS1 | eth0 | 192.168.0.10/24 | 192.168.0.100 | 真实服务器 1 |
| RS1 | tunl0 | 172.25.254.200/32 | - | VIP(RS 隧道接口) |
| RS2 | eth0 | 192.168.0.20/24 | 192.168.0.100 | 真实服务器 2 |
| RS2 | tunl0 | 172.25.254.200/32 | - | VIP(RS 隧道接口) |
12.5 配置步骤
步骤 1:所有节点前置准备
bash
[root@all ~]# systemctl stop firewalld [root@all ~]# systemctl disable firewalld [root@all ~]# setenforce 0 [root@all ~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
步骤 2:路由器配置
bash
[root@router ~]# vim /etc/NetworkManager/system-connections/eth0.nmconnection [connection] id=eth0 type=ethernet interface-name=eth0 [ipv4] method=manual address1=172.25.254.100/24 [root@router ~]# vim /etc/NetworkManager/system-connections/eth1.nmconnection [connection] id=eth1 type=ethernet interface-name=eth1 [ipv4] method=manual address1=192.168.0.100/24 [root@router ~]# nmcli c reload [root@router ~]# nmcli c up eth0 [root@router ~]# nmcli c up eth1 连接已成功激活
开启内核 IP 转发:
bash
[root@router ~]# echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf [root@router ~]# sysctl -p net.ipv4.ip_forward = 1
配置 SNAT:
bash
[root@router ~]# iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 172.25.254.100 [root@router ~]# iptables -t nat -A POSTROUTING -o eth1 -j SNAT --to-source 192.168.0.100
验证路由器:
bash
[root@router ~]# cat /proc/sys/net/ipv4/ip_forward 1 [root@router ~]# iptables -t nat -L -n -v | grep SNAT 0 0 SNAT all -- * eth0 0.0.0.0/0 0.0.0.0/0 to:172.25.254.100 0 0 SNAT all -- * eth1 0.0.0.0/0 0.0.0.0/0 to:192.168.0.100
步骤 3:调度器配置(vsnode)
加载 IPIP 隧道内核模块:
bash
[root@vsnode ~]# modprobe ipip [root@vsnode ~]# lsmod | grep ipip ipip 16384 0 tunnel4 16384 1 ipip
配置物理网卡:
bash
[root@vsnode ~]# vim /etc/NetworkManager/system-connections/eth0.nmconnection [connection] id=eth0 type=ethernet interface-name=eth0 [ipv4] method=manual address1=192.168.0.50/24,192.168.0.100 [root@vsnode ~]# nmcli c reload [root@vsnode ~]# nmcli c up eth0 连接已成功激活
在物理网卡上绑定 VIP(TUN 模式关键区别:VIP 配置在物理网卡别名上,而不是 lo 口):
bash
[root@vsnode ~]# nmcli c mod eth0 +ipv4.addresses 172.25.254.200/32 [root@vsnode ~]# nmcli c up eth0 连接已成功激活
验证 VIP:
bash
[root@vsnode ~]# ip a | grep 172.25.254.200
inet 172.25.254.200/32 scope global noprefixroute eth0
安装 ipvsadm 并配置 TUN 模式调度规则(关键参数 -i 表示 TUN 模式):
bash
[root@vsnode ~]# yum install -y ipvsadm Complete! [root@vsnode ~]# ipvsadm -A -t 172.25.254.200:80 -s rr [root@vsnode ~]# ipvsadm -a -t 172.25.254.200:80 -r 192.168.0.10:80 -i [root@vsnode ~]# ipvsadm -a -t 172.25.254.200:80 -r 192.168.0.20:80 -i
参数说明:DR 模式用
-g,TUN 模式用 -i。
验证调度规则:
bash
[root@vsnode ~]# ipvsadm -Ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 172.25.254.200:80 rr -> 192.168.0.10:80 Tunnel 1 0 0 -> 192.168.0.20:80 Tunnel 1 0 0
Forward 列显示 Tunnel,表示 TUN 模式已生效。
清空 NAT 表并持久化:
bash
[root@vsnode ~]# iptables -t nat -F [root@vsnode ~]# ipvsadm-save > /etc/sysconfig/ipvsadm [root@vsnode ~]# systemctl enable ipvsadm Created symlink... [root@vsnode ~]# echo "ipip" > /etc/modules-load.d/ipip.conf
步骤 4:RS1 配置
安装 httpd 并创建测试页面:
bash
[root@RS1 ~]# yum install -y httpd Complete! [root@RS1 ~]# echo "RS1" > /var/www/html/index.html [root@RS1 ~]# systemctl start httpd
配置物理网卡:
bash
[root@RS1 ~]# vim /etc/NetworkManager/system-connections/eth0.nmconnection [connection] id=eth0 type=ethernet interface-name=eth0 [ipv4] method=manual address1=192.168.0.10/24,192.168.0.100 [root@RS1 ~]# nmcli c reload [root@RS1 ~]# nmcli c up eth0 连接已成功激活
加载 IPIP 隧道模块:
bash
[root@RS1 ~]# modprobe ipip [root@RS1 ~]# lsmod | grep ipip ipip 16384 0 tunnel4 16384 1 ipip
在 tunl0 隧道接口绑定 VIP(TUN 模式关键区别:RS 通过 tunl0 绑定 VIP,而不是 lo 口):
bash
[root@RS1 ~]# nmcli c add type ip-tunnel ifname tunl0 con-name tunl0 连接 "tunl0" (xxxx) 已成功添加。 [root@RS1 ~]# nmcli c mod tunl0 ip-tunnel.mode ipip ip-tunnel.remote 0.0.0.0 [root@RS1 ~]# nmcli c mod tunl0 ipv4.method manual ipv4.addresses 172.25.254.200/32 [root@RS1 ~]# nmcli c up tunl0 连接已成功激活
验证 VIP 已绑定:
bash
[root@RS1 ~]# ip a | grep 172.25.254.200
inet 172.25.254.200/32 scope global tunl0
抑制 ARP 响应并关闭 rp_filter:
bash
[root@RS1 ~]# cat >> /etc/sysctl.conf << EOF net.ipv4.conf.all.arp_ignore = 1 net.ipv4.conf.tunl0.arp_ignore = 1 net.ipv4.conf.tunl0.arp_announce = 2 net.ipv4.conf.all.arp_announce = 2 net.ipv4.conf.default.rp_filter = 0 net.ipv4.conf.all.rp_filter = 0 EOF [root@RS1 ~]# sysctl -p net.ipv4.conf.all.arp_ignore = 1 net.ipv4.conf.tunl0.arp_ignore = 1 ...
若未调整 ARP 参数,RS 会响应 VIP 的 ARP 请求,导致调度失效。若 rp_filter 未关闭,RS 会丢弃目标 IP 不是本机物理接口 IP 的数据包,导致解封装后的内层包被丢弃。
清空 NAT 表并持久化:
bash
[root@RS1 ~]# iptables -t nat -F [root@RS1 ~]# echo "ipip" > /etc/modules-load.d/ipip.conf
验证 RS1:
bash
[root@RS1 ~]# curl http://127.0.0.1 RS1 [root@RS1 ~]# cat /proc/sys/net/ipv4/conf/all/arp_ignore 1
步骤 5:RS2 配置
配置与 RS1 完全相同,仅 IP 地址不同。
bash
[root@RS2 ~]# yum install -y httpd Complete! [root@RS2 ~]# echo "RS2" > /var/www/html/index.html [root@RS2 ~]# systemctl start httpd [root@RS2 ~]# vim /etc/NetworkManager/system-connections/eth0.nmconnection [connection] id=eth0 type=ethernet interface-name=eth0 [ipv4] method=manual address1=192.168.0.20/24,192.168.0.100 [root@RS2 ~]# nmcli c reload [root@RS2 ~]# nmcli c up eth0 连接已成功激活 [root@RS2 ~]# modprobe ipip [root@RS2 ~]# nmcli c add type ip-tunnel ifname tunl0 con-name tunl0 连接 "tunl0" (xxxx) 已成功添加。 [root@RS2 ~]# nmcli c mod tunl0 ip-tunnel.mode ipip ip-tunnel.remote 0.0.0.0 [root@RS2 ~]# nmcli c mod tunl0 ipv4.method manual ipv4.addresses 172.25.254.200/32 [root@RS2 ~]# nmcli c up tunl0 连接已成功激活 [root@RS2 ~]# cat >> /etc/sysctl.conf << EOF net.ipv4.conf.all.arp_ignore = 1 net.ipv4.conf.tunl0.arp_ignore = 1 net.ipv4.conf.tunl0.arp_announce = 2 net.ipv4.conf.all.arp_announce = 2 net.ipv4.conf.default.rp_filter = 0 net.ipv4.conf.all.rp_filter = 0 EOF [root@RS2 ~]# sysctl -p [root@RS2 ~]# iptables -t nat -F [root@RS2 ~]# echo "ipip" > /etc/modules-load.d/ipip.conf
验证 RS2:
bash
[root@RS2 ~]# ip a | grep 172.25.254.200 inet 172.25.254.200/32 scope global tunl0 [root@RS2 ~]# curl http://127.0.0.1 RS2
步骤 6:客户端配置
bash
[root@client ~]# vim /etc/NetworkManager/system-connections/eth0.nmconnection [connection] id=eth0 type=ethernet interface-name=eth0 [ipv4] method=manual address1=172.25.254.99/24,172.25.254.100 [root@client ~]# nmcli c reload [root@client ~]# nmcli c up eth0 连接已成功激活
步骤 7:连通性验证
验证 VIP 可达性:
bash
[root@client ~]# ping -c 3 172.25.254.200 PING 172.25.254.200 (172.25.254.200) 56(84) bytes of data. 64 bytes from 172.25.254.200: icmp_seq=1 ttl=64 time=1.08 ms 64 bytes from 172.25.254.200: icmp_seq=2 ttl=64 time=0.98 ms 64 bytes from 172.25.254.200: icmp_seq=3 ttl=64 time=1.02 ms
验证 HTTP 负载均衡(轮询):
bash
[root@client ~]# curl 172.25.254.200 RS1 [root@client ~]# curl 172.25.254.200 RS2 [root@client ~]# curl 172.25.254.200 RS1 [root@client ~]# curl 172.25.254.200 RS2
轮询调度生效,请求交替分配到 RS1 和 RS2。
检查调度器连接统计:
bash
[root@vsnode ~]# ipvsadm -L -n IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 172.25.254.200:80 rr -> 192.168.0.10:80 Tunnel 1 0 2 -> 192.168.0.20:80 Tunnel 1 0 2
12.6 TUN 模式注意事项
-
VIP 位置不同:调度器 VIP 配置在物理网卡别名(如 eth0:0),RS 的 VIP 配置在 tunl0 隧道接口,而非 DR 模式的
lo口 -
内核模块:调度器和 RS 都必须加载 ipip 内核模块
-
ARP 抑制:RS 需要针对
tunl0接口抑制 ARP -
rp_filter:RS 必须关闭 rp_filter,否则解封装后的内层包会被丢弃
-
调度参数:添加 RS 时使用 -i(TUN 模式),而非 DR 的
-g -
网络要求:调度器和 RS 可以跨网段、跨地域部署,这是 TUN 模式相对于 DR 模式的最大优势
TUN 模式实验常见排错表格整理
| 报错现象 | 根本原因 | 解决方案 |
|---|---|---|
| curl 不通,ping VIP 也不通 | 调度器 VIP 未配置在物理网卡上 | TUN 模式调度器 VIP 必须在物理网卡别名(如 eth0:0),非 lo 口;nmcli c mod eth0 +ipv4.addresses VIP/32 |
| curl 不通,ping VIP 通但 curl 无响应 | RS 未加载 ipip 内核模块 |
RS 执行 modprobe ipip,写入 /etc/modules-load.d/ipip.conf |
| curl 不通,ping VIP 通但 curl 无响应 | RS 未在 tunl0 绑定 VIP |
nmcli c mod tunl0 ipv4.addresses VIP/32 并激活 |
ipvsadm -Ln 显示 Route 而非 Tunnel |
添加 RS 时误用了 -g |
改用 -i 重新添加 |
| IPVS 统计中 ActiveConn/InActConn 无增长 | 数据包未到达调度器或被防火墙拦截 | 检查客户端到调度器网络连通性;确认 iptables -t nat -F 已清空 |
| RS 收到请求但无法响应客户端 | rp_filter 未关闭,内核丢弃解封装后的内层包 |
sysctl -w net.ipv4.conf.all.rp_filter=0 和 net.ipv4.conf.default.rp_filter=0,写入 /etc/sysctl.conf |
| RS 响应时源 IP 显示为 RIP 而非 VIP | tunl0 未绑定 VIP 或路由配置错误 |
确保 tunl0 绑定了 VIP;检查 RS 默认路由 |
| 重启后 TUN 模式失效 | ipip 模块未设置开机自动加载 |
echo "ipip" > /etc/modules-load.d/ipip.conf |
尾声:LVS的技术特点和学习注意事项
回顾LVS(Linux Virtual Server)作为Linux内核原生集成的四层负载均衡解决方案,其技术价值体现在三个层面:其一,基于IPVS模块工作于内核空间,通过Netfilter框架在PREROUTING链截获流量,绕开用户态与内核态的频繁切换,具备高吞吐量与低延迟的转发能力;其二,支持NAT、DR、TUN三种工作模式,分别适用于网关型转发、同二层网络高性能转发及跨网络隧道转发三种网络拓扑场景,部署灵活性强;其三,提供从静态调度算法(RR、WRR、SH、DH)到动态调度算法(LC、WLC、SED、NQ、LBLC、LBLCR),可依据后端RS的实时负载状态进行动态流量分配,覆盖大多数业务场景的调度需求。
但LVS存在明确的功能边界。在协议支持层面,LVS仅解析至传输层(L4),无法识别HTTP协议中的应用层信息,因此无法实现基于URL路径、Cookie、请求头等字段的精细化路由策略,七层负载均衡能力完全缺失。在高可用层面,LVS调度器为单节点架构,本身构成系统单点故障风险,需结合Keepalived通过VRRP协议实现VIP漂移以构建主备或主主高可用集群,这引入了额外的配置复杂度和故障切换延迟。在会话保持层面,持久连接(-p参数)基于源IP地址进行会话绑定,该机制在大型NAT网络环境中会导致同一出口IP后的海量用户全部落入同一后端RS,造成严重的负载倾斜,无法应用于需要大规模会话共享的场景。在部署约束层面,DR模式要求调度器与所有RS处于同一广播域,限制了跨VLAN或跨机房部署的灵活性;TUN模式虽通过IPIP封装实现跨三层网络转发,但封装过程增加了20字节的IP头部开销,且IPIP隧道在部分网络环境中可能被安全策略阻断或被中间设备标记为异常流量,部署时需额外关注底层网络的兼容性。在功能扩展层面,FullNAT模式虽通过同时修改源IP与目标IP解决了NAT模式的网关瓶颈和跨网段问题,但该模式未纳入Linux内核主线,需重新编译内核方可启用,由此带来的内核定制成本和长期维护负担使得该模式在生产环境中的采用率较低。
技术从来不是一蹴而就的,也不是放之四海而皆准的。LVS诞生于2000年前后,在往后的二十余年里被大规模验证和反复打磨,确实把这件事做到了极致。但技术终归是特定历史阶段和特定问题约束下的产物——它有自己的擅长领域,也必然有自己的能力边界。没有完美的技术,只有合适的场景。理解一项技术,不仅要掌握它能做什么,更要清楚它不能做什么,以及为什么不能。在架构设计中,识别边界往往比堆砌功能更重要——把合适的问题交给合适的工具,把LVS的四层能力与Nginx/HAProxy的七层治理、Keepalived的高可用、Redis的会话共享组合起来,才能构建出经得起生产环境考验的完整架构。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)