LVS(Linux Virtual Server)是Linux虚拟服务器的简称,是一个由章文嵩博士发起的自由软件项目,现已成为Linux标准内核的一部分。LVS是一种基于TCP/IP的负载均衡技术,其转发效率极高,具备处理百万级并发连接请求的能力。LVS通过IPVS(IP Virtual Server)模块实现IP负载均衡技术,该模块是LVS集群的核心软件模块,安装在LVS集群作为负载均衡的主节点上,虚拟出一个IP地址和端口对外提供服务。
LVS主要有四种工作模式:
1. NAT模式(Network Address Translation)
- 原理:客户端发来的数据包在负载均衡器上进行目标地址(DNAT)转换,将目标IP地址转换为其中一台后端真实服务器的IP地址,并发至该服务器处理。服务器处理完成后,将数据包发回负载均衡器,负载均衡器再将数据包的原IP地址封装为自己的IP,目标地址封装为客户端IP地址,然后发给客户端。无论是进来的流量还是出去的流量,都必须经过负载均衡器。
- 优点:集群中的物理服务器可以使用任何支持TCP/IP的操作系统,只有负载均衡器需要一个合法的IP地址。
- 缺点:扩展性有限。当服务器节点增长过多时,负载均衡器会成为整个系统的瓶颈,因为所有请求包和应答包的流向都需经过负载均衡器。
2. DR模式(Direct Routing)
- 原理:负载均衡器在接到请求报文后,仅修改数据帧的目标MAC地址,使其变为某台后端真实服务器的MAC地址,然后将数据帧发送出去。服务器收到数据包后,由于目标IP地址(VIP)是自己的,因此接受数据包并给予处理。处理完成后,服务器直接向客户端返回响应,不再经过负载均衡器。
- 优点:性能最好,负载均衡器仅处理网络帧的MAC地址修改,不处理应用层数据,因此转发效率高。
- 缺点:要求负载均衡器的网卡与物理网卡在同一个物理段上。
3. TUN模式(Tunneling)
- 原理:客户端发来的数据包被负载均衡器封装一个新的IP头(仅包含目的IP),然后发送给后端真实服务器。服务器收到数据包后,先解开IP头,还原数据包,处理后再直接返回给客户端,无需再经过负载均衡器。
- 优点:负载均衡器只负责分发请求,减少了负载均衡器的大量数据流动,使其不再是系统瓶颈。
- 缺点:需要所有服务器支持IP Tunneling协议,可能仅适用于部分Linux系统。
4. FULLNAT模式
- 原理:FULLNAT模式在客户端请求VIP时,不仅替换数据包的目标IP地址,还替换源IP地址。当后端真实服务器处理完请求后,将数据包发送给负载均衡器,负载均衡器再将数据包的源IP地址和目标IP地址分别替换为负载均衡器的IP地址和客户端的IP地址,然后发送给客户端。
- 优点:无需负载均衡器与后端真实服务器在同一网段,提高了运维部署的便利性。
- 缺点:由于进行了四次地址转换,性能通常比NAT模式低约10%。
lvs常见的调度算法
- 轮询(Round Robin,RR)
- 原理:轮询调度算法以轮询的方式依次将请求调度到不同的服务器。即每次调度执行i = (i + 1) mod n,并选出第i台服务器。
- 特点:简洁性,无需记录当前所有连接的状态,是一种无状态调度。
- 加权轮询(Weighted Round Robin,WRR)
- 原理:由于每台服务器的配置、安装的业务应用等不同,其处理能力会不一样。加权轮询调度算法根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。
- 特点:能够更合理地分配请求到处理能力不同的服务器上。
- 目标地址散列(Destination Hashing,DH)
- 原理:针对目标IP地址的负载均衡,通过一个散列函数将一个目标IP地址映射到一台服务器。
- 特点:能够将发往同一个目标地址的请求始终转发到同一台服务器,适用于正向代理缓存场景。
- 源地址散列(Source Hashing,SH)
- 原理:根据请求的源IP地址作为散列键从静态分配的散列表找出对应的服务器。
- 特点:能够将来自同一个源IP地址的请求始终发往同一台服务器,实现会话绑定。
- 最少连接(Least Connections,LC)
- 原理:将新的连接请求分配到当前连接数最小的服务器。
- 特点:通过服务器当前所活跃的连接数来估计服务器的负载情况,适用于长连接应用。
- 加权最少连接(Weighted Least Connections,WLC)
- 原理:是最少连接调度的超集,各个服务器用相应的权值表示其处理性能。调度新连接时尽可能使服务器的已建立连接数和其权值成比例。
- 特点:适用于服务器性能差异较大的场景,能够更合理地分配负载。
- 最短期望延迟(Shortest Expected Delay Scheduling,SED)
- 原理:基于WLC算法,但只考虑活动连接,不考虑非活动连接。通过计算服务器的期望延迟来选择连接数相对较少且权重较高的服务器。
- 特点:能够确保高权重服务器优先处理请求,提高系统整体性能。
- 永不排队(Never Queue Scheduling,NQ)
- 原理:无需队列,如果有服务器的连接数为0,则直接分配请求给该服务器,否则使用SED算法进行调度。
- 特点:能够减少请求在负载均衡器上的等待时间,提高响应速度。
- 基于局部性的最少连接(Locality-Based Least Connections,LBLC)
- 原理:针对请求报文的目标IP地址进行负载均衡,将相同目标IP地址的请求调度到同一台服务器,以提高缓存命中率。
- 特点:主要用于Cache集群系统,能够提高系统的整体处理能力。
- 带复制的基于局部性最少连接(Locality-Based Least Connections with Replication,LBLCR)
- 原理:维护一个从目标IP地址到一组服务器的映射,根据最少连接原则从服务器组中选出一台服务器处理请求。若服务器组中的服务器都超载,则从整个集群中选出一台服务器加入到服务器组中。
- 特点:能够解决LBLC算法中负载不均衡的问题,提高Cache集群系统的使用效率
ipvsadm
ipvsadm是Linux系统中用于配置和管理IPVS(IP Virtual Server)模块的命令行工具。IPVS是Linux内核中的一个模块,它实现了一种基于网络地址转换的负载均衡技术,能够将来自客户端的请求分发到多个后端服务器上,从而提高系统的性能和可用性。
命令语法、子命令和选项
语法:
ipvsadm -A|E -t|u|f <集群服务地址> [-s <调度算法>] [-p <超时时间>] [-M <掩码>] [-b <标志>]
ipvsadm -D -t|u|f <集群服务地址>
ipvsadm -C
ipvsadm -R
ipvsadm -S [-n]
ipvsadm -a|e -t|u|f <集群服务地址> -r <真实服务器地址> [选项]
ipvsadm -d -t|u|f <集群服务地址> -r <真实服务器地址>
ipvsadm -L|l [options]
ipvsadm -Z [-t|u|f <集群服务地址>]
ipvsadm --set <超时时间>
ipvsadm --start-daemon <主或备> [--mcast-interface <组播接口>] [--syncid <SID>]
ipvsadm --stop-daemon <主或备>
ipvsadm -h
子命令:
--add-service -A 添加一个集群服务,需要使用选项
--edit-service -E 编辑一个集群服务,需要使用选项
--delete-service -D 删除指定集群服务,需要使用选项
--clear -C 删除所有集群服务,包括真实服务器转发策略规则
--restore -R 从标准输入中恢复策略规则
--save -S 保存策略规则到标准输出
--add-server -a 添加一个真实服务器,需要使用选项
--edit-server -e 编辑一个真实服务器,需要使用选项
--delete-server -d 删除一个真实服务器,需要使用选项
--list -L|-l 查看集群服务列表,包括真实服务器转发策略规则
--zero -Z 计数器清零。清除连接数、包转发等数量统计信息
--set <超时时间> 设置TCP、TCPFIN(TCP关闭连接状态)、UDP连接超时时间,用于
会话保持。一般情况下TCP和UDP超时时间保持默认就好,TCPFIN
可以根据情况设定,指定它则用户请求连接关闭,该连接则会变
为非活跃(InActive)空闲等待状态,在空闲等待时间内,如果
来自同一源IP的请求,则还会转发给后端的同一台真实服务器上
--start-daemon 开启连接同步守护进程。在选项后面指定自己是Master(主)还
是backup(备),主负载调度器会同步所有策略及连接状态到备
负载调度器,当主故障,备可以接替其工作
--stop-daemon 停止连接同步守护进程
--help -h 显示帮助信息
选项 :
--tcp-service -t <集群服务地址> 允许集群服务使用的传输协议为TCP。<IP:Port>
--udp-service -u <集群服务地址> 允许集群服务使用的传输协议为UDP。<IP:Port>
--fwmark-service -f <防火墙标识> 使用一个整数值来防火墙标识集群服务,而不是地址、
端口和协议使用它,我们可以通过结合IPtables将多
个以调度器为目标的端口定义成一个防火墙标识,由
ipvsdam通过此项关联标识,则可以实现对一个IP多
端口调度,即实现后端服务器可以开放多个服务
--scheduler -s scheduler 指定集群服务使用的调度算法:rr|wrr|lc|wlc|lblc
|lblcr|dh|sh|sed|nq,默认为wlc
--persistent -p <超时时间> 开启持久化服务,开启它则表示在指定时间内,来自同
一IP的请求都会转发到后端同一台真实服务器上
--netmask -M <网络掩码> 使用网络掩码来屏蔽持久化来源IP的地址范围,默认值
为255.255.255.255,即所有来源IP请求都会享受持久
化服务
--real-server -r <真实服务器地址> 指定真实服务器的主机IP与端口
--gatewaying -g 指定真实服务器转发工作模式,使用DR模式,默认
--ipip -i 指定真实服务器转发工作模式,使用TUN模式
--masquerading -m 指定真实服务器转发工作模式,使用NAT模式
--weight -w <权重值> 指定真实服务器的权重值
--u-threshold -x <上阀值> 设置转发请求的最大上连接阀值,范围为0~65535,当
当连接数超过指定上限时,LVS则不会转发请求
--l-threshold -y <下阀值> 设置转发请求的下连接阀值,范围为0~65535,当连接
数降低至指定值时,LVS则继续提供服务,默认值为0
--mcast-interface interface 设置用于连接同步守护进程的组播接口
--syncid sid 设置连接同步守护进程的SID号,用于标识,范围0~255
--connection -c 显示连接信息,一般与"-l"连用
--timeout 显示TCP、TCPFIN、UDP超时时间信息,一般与"-l"连用
--daemon 显示连接同步守护信息,一般与"-l"连用
--stats 显示统计信息,一般与"-l"连用
--rate 显示转发速率信息,一般与"-l"连用
--exact 显示数据包和字节计数器的确切值,扩大字符长度
--thresholds 显示阀值信息,一般与"-l"连用
--persistent-conn 显示持久化连接信息,一般与"-l"连用
--numeric -n 地址和端口以数字格式显示,一般与"-l"连用
--sched-flags -b <标识> 设置调度算法的范围标识,用于SH算法,有两个标识:
sh-fallback,如果真实服务器不可用,则将其转发到
其他真实服务器上。
sh-port,将源地址的端口号也添加到散列键=值中
实验:
1.NAT模式
实验准备:
主机 | IP | VIP | 角色 | 模式 |
LVS | 192.168.0.100 | 172.25.250.100 | 调度器 | NAT、仅主机 |
rs1 | 192.168.0.10 | 服务器1 | 仅主机 | |
rs2 | 192.168.0.20 | 服务器2 | 仅主机 | |
client | 172.25.250.200 | 客户端 | NAT |
拓扑:
网络配置
lvs:
rs1:
rs2:
client:
s
实验步骤:
1.在lvs中启动核路由功能
net.ipv4.ip_forward = 1表示启动成功
安装ipvsadm
[root@lvs ~]# yum install ipvsadm -y
添加路由调度策略
[root@lvs ~]# ipvsadm -A -t 172.25.250.100:80 -s rr
[root@lvs ~]# ipvsadm -a -t 172.25.250.100:80 -r 192.168.0.10:80 -m
[root@lvs ~]# ipvsadm -a -t 172.25.250.100:80 -r 192.168.0.20:80 -m
查看调度策略
[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 172.25.250.100:80 rr
-> 192.168.0.10:80 Masq 1 0 0
-> 192.168.0.20:80 Masq 1 0 0
保存策略
[root@lvs ~]# ipvsadm -Sn > /etc/sysconfig/ipvsadm
-A -t 172.25.250.100:80 -s rr
-a -t 172.25.250.100:80 -r 192.168.0.10:80 -m -w 1
-a -t 172.25.250.100:80 -r 192.168.0.20:80 -m -w 1
[root@lvs ~]# cat /etc/sysconfig/ipvsadm
-A -t 172.25.250.100:80 -s rr
-a -t 172.25.250.100:80 -r 192.168.0.10:80 -m -w 1
-a -t 172.25.250.100:80 -r 192.168.0.20:80 -m -w 1
为临时的 需设置开机启动
[root@lvs ~]# systemctl enable --now ipvsadm.service
启动服务
[root@lvs ~]# systemctl start ipvsadm.service
rs1与rs2:
dnf install httpd -y
[root@rs1 ~]# echo welcome to RS1 > /var/www/html/index.html
[root@rs1 ~]# systemctl restart httpd
[root@rs2 ~]# echo welcome to RS2 > /var/www/html/index.html
[root@rs2 ~]# systemctl restart httpd
client客户端测试:
[root@client ~]# curl 172.25.250.100
welcome to RS1
[root@client ~]# curl 172.25.250.100
welcome to RS2
#循环测试
[root@client ~]# for i in {1..6}
> do
> curl 172.25.250.100
> done
welcome to RS1
welcome to RS2
welcome to RS1
welcome to RS2
welcome to RS1
welcome to RS2
2.DR模式
实验准备
主机 | IP | VIP | 角色 | 模式 |
LVS | 192.168.0.50 | lo:192.168.0.200/32 | 调度器 | 仅主机 |
router | 172.25.250.100 192.168.0.100 | 路由器 | NAT、仅主机 | |
rs1 | 192.168.0.10 | lo:192.168.0.200/32 | 服务器1 | 仅主机 |
rs2 | 192.168.0.20 | lo:192.168.0.200/32 | 服务器2 | 仅主机 |
client | 172.25.250.200 | null | 客户端 | NAT |
网络配置
lvs
router
rs1
rs2
client
实验步骤:
在lvs中添加回环IP/VIP
[root@lvs ~]# ip addr add dev lo 192.168.0.200/32
[root@lvs ~]# ip ad
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 192.168.0.200/32 scope global lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:bb:bd:47 brd ff:ff:ff:ff:ff:ff
altname enp3s0
altname ens160
inet 192.168.0.50/24 brd 192.168.0.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 fe80::9a00:a113:9751:5d9e/64 scope link noprefixroute
valid_lft forever preferred_lft forever
添加调度策略
[root@lvs ~]# ipvsadm -A -t 192.168.0.200:80 -s wrr
[root@lvs ~]# ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.10:80 -g -w 1
[root@lvs ~]# ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.20:80 -g -w 2
保存策略
[root@lvs ~]# ipvsadm -Sn > /etc/sysconfig/ipvsadm
[root@lvs ~]# cat /etc/sysconfig/ipvsadm
-A -t 192.168.0.200:80 -s wrr
-a -t 192.168.0.200:80 -r 192.168.0.10:80 -g -w 1
-a -t 192.168.0.200:80 -r 192.168.0.20:80 -g -w 2
[root@lvs ~]# systemctl restart ipvsadm
设置内核参数
net.ipv4.ip_forward=1
sysctl -p
rs1和rs2中
添加lo回环IP/VIP
ip addr add dev lo 192.168.0.200/32
解决响应问题
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/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
web设置
dnf install httpd -y
[root@rs1 ~]# echo welcome to RS1 > /var/www/html/index.html
[root@rs2 ~]# echo welcome to RS2 > /var/www/html/index.html
systemctl restart httpd
client测试
[root@client ~]# curl 192.168.0.200
welcome to RS2
[root@client ~]# curl 192.168.0.200
welcome to RS1
#循环测试
[root@client ~]# for i in {1..6}
> do
> curl 192.168.0.200
> done
welcome to RS2
welcome to RS1
welcome to RS2
welcome to RS2
welcome to RS1
welcome to RS2
3.防火墙标签解决轮询错误
在rs1和rs2中安装mod_ssl并重启
yum install mod_ssl -y
systemctl restart httpd
在lvs调度器中设定端口标签,把80和443端口设定成一个整体
iptables -t mangle -A PREROUTING -d 192.168.0.200 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 666
设定调度规则
[root@lvs ~]# ipvsadm -C
[root@lvs ~]# ipvsadm -A -f 666 -s rr
[root@lvs ~]# ipvsadm -a -f 666 -r 192.168.0.10 -g
[root@lvs ~]# ipvsadm -a -f 666 -r 192.168.0.20 -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 666 rr
-> 192.168.0.10:0 Route 1 0 0
-> 192.168.0.20:0 Route 1 0 0
[root@lvs ~]# systemctl restart ipvsadm.service
[root@lvs ~]# cat /etc/sysconfig/ipvsadm
-A -f 666 -s rr
-a -f 666 -r 192.168.0.10:0 -g -w 1
-a -f 666 -r 192.168.0.20:0 -g -w 1
client客户端测试
[root@client ~]# curl -k https://192.168.0.200
welcome to RS1
[root@client ~]# curl -k https://192.168.0.200
welcome to RS2
[root@client ~]# curl -k https://192.168.0.200;curl 192.168.0.200
welcome to RS1
welcome to RS2