LVS 项目知识点总结

系统性能扩展与集群简介

1. 系统性能扩展方式

常见的系统性能扩展方式有两种:

Scale Up(向上扩展):通过增强单台服务器的硬件配置(CPU、内存、硬盘)来提升性能,成本较高且有上限。

Scale Out(向外扩展):通过增加服务器数量形成集群,共同完成任务,处理能力可以线性增长,但需要解决负载均衡和任务调度问题。

2. 什么是集群(Cluster)

集群(Cluster)是为了解决某个特定问题,将多台计算机组合起来,对外表现为一个单一系统。集群根据用途通常分为三类:

负载均衡集群(LB, Load Balancing):由多台服务器组成,每台服务器只承担一部分访问请求,通过前端调度器分发流量,实现系统处理能力的高可扩展性。

高可用集群(HA, High Availability):通过冗余节点消除单点故障(SPOF),当主节点出现故障时,备用节点自动接管服务。衡量高可用性的关键指标包括 MTBF(平均无故障时间)、MTTR(平均恢复时间)和可用率 A = MTBF/(MTBF+MTTR),通常以"99.9%、99.99%"等形式体现 SLA(服务等级协议)。

高性能计算集群(HPC, High Performance Computing):将多台计算机的计算能力联合起来,解决复杂的科学计算问题,属于国家级战略资源,不在本次课程范围内。

3. 集群与分布式的区别

集群:同一套业务系统部署在多台服务器上,每台服务器的功能和代码完全相同,数据和业务逻辑没有差异。集群通过提高单位时间内处理的任务数量来提升效率。

分布式:一个业务系统被拆分成多个子业务,或本身就是不同的业务,部署到多台服务器上。每台服务器实现的功能不同,代码和数据也有差异,所有节点组合在一起才能完成完整业务。分布式通过缩短单个任务的执行时间来提升效率。

二、LVS 的作用与基本概念

LVS(Linux Virtual Server)是一个开源的负载均衡调度器,由章文嵩博士开发,已集成到 Linux 内核中。阿里的四层 SLB(Server Load Balance)便是基于 LVS + Keepalived 实现。LVS 工作在网络四层,不关心具体应用层数据,只根据 IP、端口和协议分发请求,具有极高的性能和稳定性。

1. LVS 核心术语

VS(Virtual Server):虚拟服务器,即调度器(Director),负责接收客户端请求并进行分发。

RS(Real Server):真实业务服务器,真正处理客户端请求并返回数据。

CIP(Client IP):客户端主机的 IP 地址。

VIP(Virtual IP):调度器对外暴露的 IP 地址,供客户端访问。

DIP(Director IP):调度器对内与 RS 通信使用的 IP 地址。

RIP(Real IP):真实服务器的 IP 地址。

基本访问流程:CIP ↔ VIP == DIP ↔ RIP。

2. LVS 工作原理

LVS 根据请求报文的目标 IP、目标协议及端口,按照选定的调度算法,将请求转发到某台 RS。整个转发过程对客户端是透明的。

LVS 安装部署与 ipvsadm 命令详解

1. LVS 的安装

bash 复制代码
[root@lvs-server ~]# dnf install ipvsadm.x86_64 -y

2. 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

3. ipvsadm 核心功能

ipvsadm 命令主要提供以下核心功能:集群服务管理:增、删、改集群服务的 RS 管理:增、删、改,查看规则在操作过程中,可以通过另一个 shell 开启实时监控:

bash 复制代码
[root@lvs-server ~]# watch -n 1 ipvsadm -Ln
管理集群服务(增删改)
bash 复制代码
# 设定服务器 VIP、端口及调度算法
[root@lvs-server ~]# ipvsadm -A -t 172.25.254.100:80 -s rr
指定使用防火墙标记来进行轮询,-p 指定持久连接超时时间(秒)
[root@lvs-server ~]# ipvsadm -A -f 66 -p 3000
更改调度算法
[root@lvs-server ~]# ipvsadm -E -t 172.25.254.100:80 -s wrr
删除集群服务
[root@lvs-server ~]# ipvsadm -D -f 66
管理集群中的 RealServer(增删改)
bash 复制代码
# 增加 RS(-m 表示 NAT 模式,-g 表示 DR 模式,-i 表示 TUN 模式)
[root@lvs-server ~]# ipvsadm -a -t 172.25.254.100:80 -r 192.168.0.10 -m
[root@lvs-server ~]# ipvsadm -a -t 172.25.254.100:80 -r 192.168.0.20 -m
修改 RS 权重和工作模式
[root@lvs-server ~]# ipvsadm -e -t 172.25.254.100:80 -r 192.168.0.10 -w 2 -m
[root@lvs-server ~]# ipvsadm -e -t 172.25.254.100:80 -r 192.168.0.20 -w 5 -i
删除单个 RS
[root@lvs-server ~]# ipvsadm -d -t 172.25.254.100:80 -r 192.168.0.20
清空所有规则
[root@lvs-server ~]# ipvsadm -C

4. LVS 策略保存

方法一:利用自定义文件保存策略
bash 复制代码
# 添加规则
[root@lvs-server ~]# ipvsadm -A -t 172.25.254.100:80 -s rr
[root@lvs-server ~]# ipvsadm -a -t 172.25.254.100:80 -r 192.168.0.10 -m
[root@lvs-server ~]# ipvsadm -a -t 172.25.254.100:80 -r 192.168.0.20 -m
查看并保存规则
[root@lvs-server ~]# ipvsadm-save
-A -t lvs-server:http -s rr
-a -t lvs-server:http -r 192.168.0.10:http -m -w 1
-a -t lvs-server:http -r 192.168.0.20:http -m -w 1
导出到自定义文件
[root@lvs-server ~]# ipvsadm-save > /mnt/haha
清空规则验证
[root@lvs-server ~]# ipvsadm -C
[root@lvs-server ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port           Forward Weight ActiveConn InActConn
从文件恢复规则
[root@lvs-server ~]# ipvsadm-restore < /mnt/haha
[root@lvs-server ~]# 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.10:80              Masq    1      0          0
-> 192.168.0.20:80              Masq    1      0          0
方法二:ipvs 策略开机生效
bash 复制代码
# 保存规则到系统配置文件
[root@lvs-server ~]# ipvsadm-save > /etc/sysconfig/ipvsadm
启用 ipvsadm 服务
[root@lvs-server ~]# systemctl enable --now ipvsadm.service
重启后仍然生效
reboot
[root@lvs-server ~]# 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.10:80              Masq    1      0          0
-> 192.168.0.20:80              Masq    1      0          0

三、LVS 的四种工作模式及原理

1. NAT 模式

本质是多目标 IP 的 DNAT(目标地址转换)。调度器将请求报文中的目标 IP 和目标端口修改为挑选出的 RS 的 RIP 和对应端口,再将报文发送给 RS。响应报文同样必须经过调度器,由调度器把源地址从 RIP 改回 VIP 后返回客户端。

特点与限制:

RIP 和 DIP 通常位于同一 IP 网络,且应使用私网地址。

RS 的网关必须指向 DIP。

所有请求和响应都经过调度器,调度器容易成为性能瓶颈。

支持端口映射,可修改请求报文的目标端口。

VS 必须是 Linux 系统,RS 可以是任意操作系统。

实验步骤

**实验环境:**VS 主机 eth0=172.25.254.100(VIP),eth1=192.168.0.100(DIP);RS1=192.168.0.10;RS2=192.168.0.20;服务端口为 80。

环境设定

VS 主机网络配置:

bash 复制代码
[root@vsnode ~]# vmset.sh eth0 172.25.254.100 vsnode
[root@vsnode ~]# vmset.sh eth1 192.168.0.100 vsnode noroute

RS1 网络配置与业务部署:

bash 复制代码
# 设定网络
[root@RS1 ~]# vmset.sh eth0 192.168.0.10 RS1 noroute
[root@RS1 ~]# nmcli connection modify eth0 ipv4.gateway 192.168.0.100
[root@RS1 ~]# nmcli connection reload
[root@RS1 ~]# nmcli connection 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.100   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
设定访问业务真实数据
[root@RS1 ~]# dnf install httpd -y
[root@RS1 ~]# systemctl enable --now httpd
[root@RS1 ~]# echo RS1 - 192.168.0.10 > /var/www/html/index.html

RS2 网络配置与业务部署:

bash 复制代码
# 设定网络
[root@RS2 ~]# vmset.sh eth0 192.168.0.20 RS2 noroute
[root@RS2 ~]# nmcli connection modify eth0 ipv4.gateway 192.168.0.100
[root@RS2 ~]# nmcli connection reload
[root@RS2 ~]# nmcli connection 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.100   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
设定访问业务真实数据
[root@RS2 ~]# dnf install httpd -y
[root@RS2 ~]# systemctl enable --now httpd
[root@RS2 ~]# echo RS2 - 192.168.0.20 > /var/www/html/index.html

在 VS 主机中测试环境连通性:

bash 复制代码
[root@vsnode ~]# curl 192.168.0.10
RS1 - 192.168.0.10
[root@vsnode ~]# curl 192.168.0.20
RS2 - 192.168.0.20
实现 NAT 模式负载均衡

1. 开启内核路由功能:

bash 复制代码
[root@vsnode ~]# echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf
[root@vsnode ~]# sysctl -p
net.ipv4.ip_forward = 1

2. 编写 ipvsadm 策略:

bash 复制代码
[root@vsnode ~]# ipvsadm -C
[root@vsnode ~]# ipvsadm -A -t 172.25.254.100:80 -s wrr
[root@vsnode ~]# ipvsadm -a -t 172.25.254.100:80 -r 192.168.0.10:80 -m -w 1
[root@vsnode ~]# ipvsadm -a -t 172.25.254.100:80 -r 192.168.0.20:80 -m -w 1
[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.100:80 wrr
  -> 192.168.0.10:80              Masq    1      0          0
  -> 192.168.0.20:80              Masq    1      0          0

3. 测试负载均衡效果:

bash 复制代码
[root@vsnode ~]# for i in {1..10};do curl 172.25.254.100;done
RS2 - 192.168.0.20
RS1 - 192.168.0.10
RS2 - 192.168.0.20
RS1 - 192.168.0.10
RS2 - 192.168.0.20
RS1 - 192.168.0.10
RS2 - 192.168.0.20
RS1 - 192.168.0.10
RS2 - 192.168.0.20
RS1 - 192.168.0.10

4. 更改权重并验证:

bash 复制代码
[root@vsnode ~]# ipvsadm -e -t 172.25.254.100:80 -r 192.168.0.10:80 -m -w 2
[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.100:80 wrr
  -> 192.168.0.10:80              Masq    2      0          5
  -> 192.168.0.20:80              Masq    1      0          5
[root@vsnode ~]# for i in {1..10};do curl 172.25.254.100;done
RS2 - 192.168.0.20
RS1 - 192.168.0.10
RS1 - 192.168.0.10
RS2 - 192.168.0.20
RS1 - 192.168.0.10
RS1 - 192.168.0.10
RS2 - 192.168.0.20
RS1 - 192.168.0.10
RS1 - 192.168.0.10
RS2 - 192.168.0.20
规则持久化

实验过程中可以通过打开另外一个 shell 并执行监控命令的方式进行观察:

bash 复制代码
[root@vsnode ~]# watch -n 1 ipvsadm -Ln

方法一:利用自定义文件进行持久化

bash 复制代码
[root@vsnode ~]# ipvsadm-save -n
-A -t 172.25.254.100:80 -s wrr
-a -t 172.25.254.100:80 -r 192.168.0.10:80 -m -w 2
-a -t 172.25.254.100:80 -r 192.168.0.20:80 -m -w 1
[root@vsnode ~]# ipvsadm-save -n > /mnt/ipvs.rule
[root@vsnode ~]# ipvsadm -C
[root@vsnode ~]# ipvsadm-restore < /mnt/ipvs.rule

方法二:利用守护进程进行规则持久化

bash 复制代码
[root@vsnode ~]# ipvsadm-save -n > /etc/sysconfig/ipvsadm
[root@vsnode ~]# ipvsadm -C
[root@vsnode ~]# systemctl enable --now ipvsadm.service
Created symlink /etc/systemd/system/multi-user.target.wants/ipvsadm.service → /usr/lib/systemd/system/ipvsadm.service.

2. DR 模式

DR(Direct Routing)是 LVS 默认模式,也是应用最广泛的模式。它通过重新封装请求报文的 MAC 首部,将源 MAC 改为 DIP 所在接口的 MAC,目标 MAC 改为选定 RS 的 MAC。请求报文中的 IP/PORT 保持不变,因此 RS 可以直接将响应报文返回给客户端,无需经过调度器。

特点与限制:

调度器和所有 RS 都必须在同一个物理网络(二层网络)中。

调度器和每个 RS 都需要配置 VIP,并且 RS 必须抑制对 VIP 的 ARP 响应。

请求报文由调度器转发,响应报文由 RS 直接返回客户端,极大降低调度器压力。

不支持端口映射。

RS 可使用大多数操作系统。

实验步骤

**实验环境:**路由器 eth0=172.25.254.100,eth1=192.168.0.100;调度器(vsnode)eth0=192.168.0.50/24;VIP=192.168.0.200(绑定在各 RS 的 lo 接口和调度器的 lo 接口上);RS1=192.168.0.10;RS2=192.168.0.20;客户端 eth0=172.25.254.99/24;服务端口为 80。

路由器设定

在路由器上关闭 ipvsadm 服务并清空规则,配置双网卡并开启内核路由转发和数据转发策略:

bash 复制代码
# 关闭 ipvsadm 服务(路由器不承担调度角色)
[root@router ~]# systemctl disable --now ipvsadm.service
Removed "/etc/systemd/system/multi-user.target.wants/ipvsadm.service".
[root@router ~]# ipvsadm -C
配置网卡
[root@router ~]# vmset.sh eth0 172.25.254.100 vsnode
[root@router ~]# vmset.sh eth1 192.168.0.100 vsnode noroute
开启内核路由功能
[root@router ~]# echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf
[root@router ~]# sysctl -p
net.ipv4.ip_forward = 1
数据转发策略(双向 SNAT)
[root@router ~]# iptables -t nat -A POSTROUTING -o eth1 -j SNAT --to-source 192.168.0.100
[root@router ~]# iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 172.25.254.100
调度器(vsnode)设定

配置调度器 eth0 的 IP 和网关,并在 lo 接口上绑定 VIP:

bash 复制代码
# 配置 eth0
[root@vsnode ~]# vmset.sh eth0 192.168.0.50 vsnode noroute
[root@vsnode ~]# nmcli connection modify eth0 ipv4.gateway 192.168.0.100
[root@vsnode ~]# nmcli connection reload
[root@vsnode ~]# nmcli connection up eth0
或者直接编辑 eth0 连接配置文件
[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 connection reload
[root@vsnode ~]# nmcli connection up eth0
在 lo 接口上绑定 VIP(192.168.0.200/32)
[root@vsnode ~]# cd /etc/NetworkManager/system-connections/
[root@vsnode system-connections]# cp -p eth0.nmconnection lo.nmconnection
[root@vsnode system-connections]# vim lo.nmconnection
[connection]
id=lo
type=loopback
interface-name=lo
[ipv4]
method=manual
address1=127.0.0.1/8
address2=192.168.0.200/32
[root@vsnode system-connections]# nmcli connection reload
[root@vsnode system-connections]# nmcli connection up lo
验证路由和 IP
[root@vsnode ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.0.100   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
[root@vsnode ~]# ip a
1: lo:  mtu 65536 ...
inet 127.0.0.1/8 scope host lo
inet 192.168.0.200/32 scope global lo
2: eth0:  mtu 1500 ...
inet 192.168.0.50/24 ...
RS1 设定

配置 RS1 的网络,在 lo 接口上绑定 VIP 并抑制 ARP 响应:

bash 复制代码
# 配置 eth0
[root@RS1 ~]# vmset.sh eth0 192.168.0.10 RS1 noroute
[root@RS1 ~]# nmcli connection modify eth0 ipv4.gateway 192.168.0.100
[root@RS1 ~]# nmcli connection reload
[root@RS1 ~]# nmcli connection 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.100   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
在 lo 接口上绑定 VIP(192.168.0.200/32)
[root@RS1 ~]# cd /etc/NetworkManager/system-connections/
[root@RS1 system-connections]# cp -p eth0.nmconnection lo.nmconnection
[root@RS1 system-connections]# vim lo.nmconnection
[connection]
id=lo
type=loopback
interface-name=lo
[ipv4]
method=manual
address1=127.0.0.1/8
address2=192.168.0.200/32
[root@RS1 system-connections]# nmcli connection reload
[root@RS1 system-connections]# nmcli connection up lo
[root@RS1 ~]# ip a
1: lo:  mtu 65536 ...
inet 127.0.0.1/8 scope host lo
inet 192.168.0.200/32 scope global lo
抑制对 VIP 的 ARP 响应
[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 设定

RS2 配置与 RS1 类似,仅 IP 不同:

bash 复制代码
# 配置 eth0
[root@RS2 ~]# vmset.sh eth0 192.168.0.20 RS2 noroute
[root@RS2 ~]# nmcli connection modify eth0 ipv4.gateway 192.168.0.100
[root@RS2 ~]# nmcli connection reload
[root@RS2 ~]# nmcli connection 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.100   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
在 lo 接口上绑定 VIP(192.168.0.200/32)
[root@RS2 ~]# cd /etc/NetworkManager/system-connections/
[root@RS2 system-connections]# cp -p eth0.nmconnection lo.nmconnection
[root@RS2 system-connections]# vim lo.nmconnection
[connection]
id=lo
type=loopback
interface-name=lo
[ipv4]
method=manual
address1=127.0.0.1/8
address2=192.168.0.200/32
[root@RS2 system-connections]# nmcli connection reload
[root@RS2 system-connections]# nmcli connection up lo
[root@RS2 ~]# ip a
1: lo:  mtu 65536 ...
inet 127.0.0.1/8 scope host lo
inet 192.168.0.200/32 scope global lo
抑制对 VIP 的 ARP 响应
[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
客户端设定

配置客户端网络,网关指向路由器的 eth0:

bash 复制代码
# 配置 eth0
[root@client ~]# vmset.sh eth0 172.25.254.99 client noroute
[root@client ~]# nmcli connection reload
[root@client ~]# nmcli connection up eth0
[root@client ~]# ip a
2: eth0:  mtu 1500 ...
inet 172.25.254.99/24 ...
设置网关和 DNS
[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
dns=8.8.8.8;
[root@client ~]# nmcli connection reload
[root@client ~]# nmcli connection 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
测试连通性
[root@client ~]# ping 192.168.0.200
PING 192.168.0.200 (192.168.0.200) 56(84) bytes of data.
64 bytes from 192.168.0.200: icmp_seq=1 ttl=128 time=1.08 ms
配置 DR 模式负载均衡规则

在调度器(vsnode)上使用 ipvsadm 配置 DR 模式的负载均衡规则(-g 表示 DR 模式):

bash 复制代码
# 清空已有规则并添加 DR 模式虚拟服务
[root@vsnode ~]# ipvsadm -C
[root@vsnode ~]# ipvsadm -A -t 192.168.0.200:80 -s wrr
[root@vsnode ~]# ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.10:80 -g -w 1
[root@vsnode ~]# ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.20:80 -g -w 1
查看规则
[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  192.168.0.200:80 wrr
-> 192.168.0.10:80              Route   1      0          0
-> 192.168.0.20:80              Route   1      0          0
测试验证

在客户端上多次访问 VIP,验证负载均衡效果:

bash 复制代码
[root@client ~]# for i in {1..10}; do curl 192.168.0.200; done
RS2 - 192.168.0.20
RS1 - 192.168.0.10
RS2 - 192.168.0.20
RS1 - 192.168.0.10
RS2 - 192.168.0.20
RS1 - 192.168.0.10
RS2 - 192.168.0.20
RS1 - 192.168.0.10
RS2 - 192.168.0.20
RS1 - 192.168.0.10

在调度器上查看连接统计,确认请求已按 DR 模式正确分发:

bash 复制代码
[root@vsnode ~]# ipvsadm -Ln --stats
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port               Conns   InPkts  OutPkts  InBytes OutBytes
  -> RemoteAddress:Port
TCP  192.168.0.200:80                    10       60        0     3480        0
  -> 192.168.0.10:80                     5       30        0     1740        0
  -> 192.168.0.20:80                     5       30        0     1740        0

注意:在 DR 模式下,调度器只转发入站请求,响应由 RS 直接返回客户端,因此 OutPkts 和 OutBytes 始终为 0。这也是 DR 模式高性能的关键原因之一。

3. TUN 模式(隧道模式)

调度器不修改请求报文的原始 IP 首部(CIP→VIP),而是在原始报文外层再封装一个 IP 头部(DIP→RIP),通过 IP 隧道将报文发往选定的 RS。RS 收到后去掉外层 IP 头,直接响应客户端。

特点与限制:

DIP、VIP、RIP 都应为公网地址,适合跨地域、跨机房部署。

RS 的网关一般不能指向 DIP。

请求报文经过调度器,但响应直接从 RS 返回客户端。

不支持端口映射。

RS 操作系统必须支持 IP 隧道功能。

4. FullNAT 模式

同时修改请求报文的源 IP(CIP→DIP)和目标 IP(VIP→RIP),实现完整的地址转换。响应报文同样需经过调度器,由调度器将源 IP 改回 VIP 后返回客户端。

特点与限制:

VIP 为公网地址,RIP 和 DIP 为私网地址,且通常不在同一 IP 网络。

RS 收到的请求源 IP 是 DIP,因此只需响应到 DIP,再由调度器转发给客户端。

请求和响应都经过调度器。

支持端口映射。

默认 Linux 内核不支持该模式,需要额外补丁。

四种模式核心差异对比
对比维度 NAT DR TUN FullNAT
原理 DNAT 目标地址转换 MAC 地址重写 IP 隧道封装 完整源/目标地址转换
网络要求 RIP/DIP 同网段,私网地址,RS 网关指向 DIP 同一二层网络,RS 需配置 VIP 并抑制 ARP 需公网 IP,RS 支持 IP 隧道 VIP 公网,RIP/DIP 私网,不需同网段
性能瓶颈 请求和响应均经过调度器,瓶颈明显 调度器仅转发请求,性能高 请求经调度器,响应直返,性能高 请求和响应均经过调度器,瓶颈明显
端口映射 支持 不支持 不支持 支持
适用场景 小型内网服务,需要端口映射 高性能大规模 Web 服务,同机房 跨地域、跨机房部署 需要透明代理和源 IP 转换的场景

四、LVS 的调度算法

LVS 调度算法分为静态调度算法和动态调度算法两大类,同时还包含新内核引入的特殊算法。下面一一介绍。

1. 静态调度算法

RR(Round Robin)轮询:依次将请求分发给所有 RS,不论 RS 的实际负载和性能差异,简单但不精准。

WRR(Weighted Round Robin)加权轮询:在轮询的基础上为 RS 赋予不同权重,性能高的 RS 获得更多请求。

SH(Source Hashing)源地址哈希:对客户端 IP 进行哈希运算,保证同一客户端的所有请求始终发往同一台 RS,用于实现会话保持(Session Sticky)。

DH(Destination Hashing)目标地址哈希:对请求的目标 IP 做哈希,将发往同一目标地址的请求始终转发到固定的 RS,常用于正向代理缓存场景(如宽带运营商)。

2. 动态调度算法

动态算法会根据各 RS 当前的负载状态(连接数)和权重进行调度,负载值 Overhead 越小的 RS 越优先被选中。

LC(Least Connections)最少连接:选择活动连接数最少的 RS,适用于长连接场景。Overhead = activeconns * 256 + inactiveconns。

WLC(Weighted Least Connections)加权最少连接:默认调度算法,在最少连接的基础上引入权重,Overhead = (activeconns * 256 + inactiveconns) / weight。

SED(Shortest Expected Delay)最短预期延迟:优先选择权重高、当前连接少的 RS,公式:(activeconns+1) * 256 / weight,初期高权重 RS 可能集中接收到大量连接。

NQ(Never Queue):第一轮平均分配,之后采用 SED 算法,避免加权模型下初期所有连接都涌向高权重 RS。

LBLC(Locality-Based Least Connection)基于局部性的最少连接:动态版 DH 算法,根据缓存负载状态将请求调度到与目标 IP "最接近"的 RS,用于正向代理缓存。

LBLCR(LBLC with Replication)带复制的 LBLC:在 LBLC 基础上增加负载均衡机制,可将负载较重的缓存 RS 上的部分内容复制到负载较轻的 RS 上,避免局部过载。

3. 新内核新增算法(4.15+)

FO(Weighted Failover)权重故障切换:常用于灰度发布,优先选择未标记为过载(OVERLOAD)且权重最高的 RS 进行调度。若该 RS 连接数过高,管理员可手动标记过载,让其暂时退出调度。

OVF(Overflow-Connection)溢出连接:基于 RS 的权重和当前活动连接数调度,只有当 RS 的活动连接数小于其权重值时才会被选中,依次使用下一个满足条件的 RS。

五、LVS 多端口轮询问题与防火墙标记解决方案

1. 问题描述

当一台 RS 同时提供多个服务端口(如 80 端口 HTTP 和 443 端口 HTTPS)时,如果分别为每个端口配置独立的 LVS 规则,不同端口的请求将被独立轮询。这会导致来自同一用户的 HTTP 和 HTTPS 请求分别落在不同的 RS 上,造成会话状态错乱。

2. 防火墙标签(FWM)解决方案

通过 Netfilter 的 mangle 表为来自 VIP 的特定协议、特定端口的报文打上相同的防火墙标记(MARK),然后将该标记绑定为一个 LVS 虚拟服务。这样,80 和 443 端口的流量被当作同一服务统一调度,保证了同一客户端的 HTTP 和 HTTPS 请求被发往同一 RS。

bash 复制代码
# 在 Director 上打标记,将 80 和 443 端口流量标记为 6666
iptables -t mangle -A PREROUTING -d 192.168.0.100 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 6666
基于防火墙标记创建 LVS 服务
ipvsadm -A -f 6666 -s rr
ipvsadm -a -f 6666 -r 192.168.0.101 -g
ipvsadm -a -f 6666 -r 192.168.0.102 -g
实验步骤

实验环境沿用 DR 模式实验环境:VIP=192.168.0.200,DIP/Router eth0=172.25.254.100,eth1=192.168.0.100,调度器 vsnode eth0=192.168.0.50/24,RS1=192.168.0.10,RS2=192.168.0.20。

1. 在 RS 上同时开启 HTTP 和 HTTPS 服务

在 RS1 和 RS2 上安装 mod_ssl 并重启 httpd:

bash 复制代码
# 在 RS1 和 RS2 中执行
[root@RS1 ~]# dnf install mod_ssl -y
[root@RS2 ~]# dnf install mod_ssl -y
[root@RS1 ~]# systemctl restart httpd
[root@RS2 ~]# systemctl restart httpd
2. 在调度器上添加 HTTP 和 HTTPS 的轮询规则

在 vsnode 上分别为 80 和 443 端口创建独立的 LVS 服务:

bash 复制代码
[root@vsnode ~]# ipvsadm -A -t 192.168.0.200:80 -s rr
[root@vsnode ~]# ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.10:80 -g
[root@vsnode ~]# ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.20:80 -g
[root@vsnode ~]# ipvsadm -A -t 192.168.0.200:443 -s rr
[root@vsnode ~]# ipvsadm -a -t 192.168.0.200:443 -r 192.168.0.10:443 -g
[root@vsnode ~]# ipvsadm -a -t 192.168.0.200:443 -r 192.168.0.20:443 -g
[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  192.168.0.200:80 rr
  -> 192.168.0.10:80              Route   1      0          0
  -> 192.168.0.20:80              Route   1      0          0
TCP  192.168.0.200:443 rr
  -> 192.168.0.10:443             Route   1      0          0
  -> 192.168.0.20:443             Route   1      0          0
3. 轮询错误展示

在客户端分别请求 HTTP 和 HTTPS,观察独立轮询导致的重复问题:

bash 复制代码
[root@client ~]# curl 192.168.0.200; curl -k https://192.168.0.200
RS2 - 192.168.0.20
RS2 - 192.168.0.20
# HTTP 和 HTTPS 是独立的 service,轮询可能出现相同的 RS
4. 使用防火墙标记解决轮询错误

在调度器上使用 iptables 对发往 VIP:80 和 VIP:443 的 TCP 报文打上相同的防火墙标记 6666,然后基于标记创建统一的 LVS 服务:

bash 复制代码
# 打标记
[root@vsnode ~]# iptables -t mangle -A PREROUTING -d 192.168.0.200 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 6666
基于防火墙标记创建 LVS 服务
[root@vsnode ~]# ipvsadm -A -f 6666 -s rr
[root@vsnode ~]# ipvsadm -a -f 6666 -r 192.168.0.10 -g
[root@vsnode ~]# ipvsadm -a -f 6666 -r 192.168.0.20 -g
5. 验证修复效果

在客户端再次测试,确认 HTTP 和 HTTPS 请求被调度到不同的 RS:

bash 复制代码
[root@client ~]# curl 192.168.0.200; curl -k https://192.168.0.200
RS2 - 192.168.0.20
RS1 - 192.168.0.10

六、LVS 会话粘滞(持久连接)解决方案

1. 问题背景

对于需要会话保持的应用(如用户登录、购物车),如果调度器仅按连接数或轮询分发请求,可能导致同一用户的连续请求到达不同的 RS,造成会话数据丢失。

2. 解决方案对比

SH 源地址哈希算法:将同一客户端 IP 所有请求固定调度到同一 RS,实现简单,但可能造成负载不均衡(同一源 IP 的流量过大时单台 RS 压力集中)。

持久连接(Persistent Connection):由 LVS 在内存中记录最近一段时间内每个源 IP 与对应 RS 的调度关系。在超时时间内,来自同一源 IP 的所有请求都会被转发到同一 RS,达到"粘滞"效果;超过超时时间后,该源 IP 可以被重新调度到其他 RS。此方法可与任意外部调度算法叠加使用,默认超时时间为 360 秒。

七、总结

LVS 是构建高可用、可扩展负载均衡集群的核心技术,掌握其四种工作模式的适用场景和十三种调度算法的选择策略,能够帮助我们在实际项目中灵活应对各种流量分发需求。结合防火墙标记可以解决多端口轮询错乱,利用持久连接或 SH 算法则可保证会话粘滞。理解这些知识点是深入企业级负载均衡架构的基础。

相关推荐
ly76893 天前
负载均衡详解:从四层、七层到 LVS、Keepalived、Nginx 与 HAProxy
nginx·负载均衡·lvs
小马同学-6 天前
Keepaloved+LVS(DR) +MariaDN主主
linux·运维·lvs
暖核7 天前
Keepalived + LVS(DR)+ MariaDB 主主高可用架构实战指南
架构·mariadb·lvs
闲云野鹤在人间8 天前
项目实战:LNMP-电商平台-ECshop
linux·运维·nginx·apache·lvs
黑泽明*8 天前
LVS-负载均衡全解析
运维·负载均衡·lvs
小马同学-9 天前
负载均衡-LVS全解析
运维·负载均衡·lvs
Archy_Wang_114 天前
LVS+KeepAlived+Nginx实现企业级业务高可靠部署的实战教程
运维·nginx·lvs
tx112087635820 天前
LVS知识归纳与模式解析及常见问题复现解析
linux·运维·服务器·lvs·ipvsadm·nat/dr模式
輝太くん20 天前
LVS重新梳理
lvs
苍狗T21 天前
LVS相关知识总结
linux·运维·服务器·lvs