企业负载均衡LVS
01 LVS负载均衡介绍
1、LVS基本概述
1.1 什么是LVS
LVS的英文全称是 Linux Virtual Server ,即 Linux 虚拟服务器。其实它是⼀种 Cluster 集群技术,主要是用来实现负载均衡功能的,将用户请求均匀的调度到不同的后端服务器上处理。
注意: LVS 是基于四层 目标IP:目标PORT 实现的负载均衡,例如:请求目标IP为LVS,目标端口是80,LVS则将请求调度到后端的集群节点处理。
官网:http://www.linuxvirtualserver.org/
注意:LVS不支持HTTPS、Rewrite、Header首部改写、限速、限流等操作,因此在四层后面还可能会有七层负载均衡。
1.2 为何需要lVS
1、解决七层端口数不够问题,实现百万连接;
2、解决七层负载均衡高可用问题;

1.3 LVS组成部分
ipvs :⼯作在内核空间,实现集群服务的”调度“,借鉴了 iptables 的实现方式
ipvsadm :⼯作在用户空间,负责为 ipvs 内核框架编写规则。定义谁是集群服务,谁是后端服务器,数据包如何调度,调度到哪个节点。

1.4 LVS相关名词
接下来我们需要了解LVS中的名词,比如: DS、RS、CIP、VIP、DIP、RIP ,通过下面的图来做了解其含义。

2、LVS应用场景
LVS主要应用场景:
3、LVS常⻅模型
LVS 负载均衡模型有 NAT、DR、TUN、FULL-NAT ,较为常⻅的模型有 NAT、DR ,使用最为广泛的模型是 DR
3.1 NAT模型
NAT :通过修改请求报文的目标 IP 地址,然后根据算法挑选出某台 RS 进行转发。(请求进⼊负载均衡器 LVS 时做 DNAT ,后端返回数据报文出负载均衡时做 SNAT
3.2 DR模型
DR :通过修改请求报文的目标 MAC 地址,然后根据算法挑选出某台RS进行转发。(请求进⼊负载均衡器 LVS 时做 MAC 地址转换,后端返回数据报文不经过负载均衡,所以无需做转换
4、LVS集群命令介绍
ipvsadm 的用法大概分类如下两类
管理集群服务(定义负载均衡配置)
管理后端RS(定义负载均衡后端节点的增删改查)
ipvsadm - Linux Virtual Server administration
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]
ipvsadm -a|e -t|u|f service-address -r server-address [options]
ipvsadm -d -t|u|f service-address -r server-address
ipvsadm -L|l [options]
ipvsadm -Z [-t|u|f service-address]
ipvsadm --set tcp tcpfin udp
ipvsadm --start-daemon state [--mcast-interface interface] [--syncid sid]
ipvsadm --stop-daemon state4.1 集群管理参数
# COMMANDS-Cluster
-A ,--add-service # 添加⼀个集群服务
-E ,--edit-service # 修改已添加的集群服务
-D ,--delete-service # 删除虚拟服务
-C ,--clear # 清空集群所有规则
-R ,--restore # 从文件中恢复集群
-S ,--save # 将集群信息报文至文件中
-L|-l,--list # 列出当前集群信息
-Z ,--zero # 清空集群计数器
-n # 数字格式显示 ip 和 port,注意-n只能写在-L之后4.2 节点管理参数
# COMMANDS-RS
-a,--add-server # 表示要添加 RS 节点
-e,--edit-server # 表示要修改 RS 节点
-d,--delete-server # 表示要删除 RS 节点
-t,service-address # 指定操作哪个节点地址与端口,host[:port],tcp协议
-u,service-address # 指定操作哪个节点地址与端口,host[:port],udp协议
-r,--real-server # 指定 RS 节点地址与端口
-w,--weight # 指定 RS 节点的权重
-m,--masquerading # 指定 LVS ⼯作模型 ( NAT模型 )
-g,--gatewaying # 指定 LVS ⼯作模型 ( DR模型 )
-i,--ipip # 指定 LVS ⼯作模型 ( tun模型 )
-s,--scheduler # 指定 LVS 调度策略,默认为wlc
-p,--persistent # 持久连接超时时间
-f,--fwmark-service # 防⽕墙标记
-c,--connection # 显示 ipvs 连接信息4.3 配置实例
1、定义负载均衡的IP地址为1.1.1.1,端口为80,然后后端节点为 1.1.1.2,1.1.1.3
[root@lvs01 ~]# ipvsadm -A -t 1.1.1.1:80
[root@lvs01 ~]# ipvsadm -a -t 1.1.1.1:80 -r 1.1.1.2:80
[root@lvs01 ~]# ipvsadm -a -t 1.1.1.1:80 -r 1.1.1.3:802、检查规则
[root@lvs01 ~]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 1.1.1.1:80 wlc
-> 1.1.1.2:80 Route 1 0 0
-> 1.1.1.3:80 Route 1 0 03、删除后端真实服务器
[root@lvs01 ~]# ipvsadm -d -t 1.1.1.1:80 -r 1.1.1.3:804、删除LVS集群
[root@lvs01 ~]# ipvsadm -D -t 1.1.1.1:8002 LVS负载均衡NAT模型
1、LVS NAT 模型介绍
通过修改请求报文的 目标IP 地址,而后根据调度算法挑选出⼀台 RS 节点进行转发。
(请求进⼊负载均衡器 LVS 时做 DNAT ,后端返回数据出负载均衡时做 SNAT )
1.1 NAT 基本逻辑

1.2 NAT 底层原理
客户端: 10.0.0.100(外网)
路由器: 10.0.0.20(外网) 、 172.16.1.20(内网)
DS 节点: 172.16.1.3(DIP) 、 172.16.1.10(VIP)
RS 节点: 172.16.1.5 、 172.16.1.6

1.3 NAT 访问原理
1、当用户请求到达 Director Server ,此时请求的数据报文会先到内核空间的 PREROUTING 链。 此时报文的 源IP为CIP , 目标IP为VIP
2、 PREROUTING 检查发现数据包的目标 IP 是本机,将数据包送至 INPUT 链。
3、 IPVS 比对数据包请求的服务是否为集群服务,若是,通过调度算法挑选⼀台后端 RS 服务器,并修改数据包的 目标IP 为 RS的IP ,然后将数据包发至 POSTROUTING 链。 此时报文的 源IP为CIP , 目标IP为RIP
4、 POSTROUTING 链通过选路,将数据包通过 Director Server 的DIP 发送给 RS
5、 RS 发现目标为自己的 IP ,则交给应用程序处理,然后构建响应报文发回给 Director Server 。 此时报文的 源IP为RIP , 目标IP为CIP
6、 Director Server 在响应客户端前,会将源 IP 地址修改为 VIP地址,然后响应给客户端。此时报文的 源IP为VIP , 目标IP为CIP
1.4 NAT 特性总结
1、RS 必须使用私网地址,并需要将网关指向 DS ;
2、RIP 和 DIP 必须为同⼀网段内;
3、NAT 模型支持端口映射;
4、RS 可以使用任意操作系统。例如 Linux、Windows 等;
5、请求和响应报文都要经过 DS ,高负载场景中, DS 易称为瓶颈。
2、LVS NAT 模型场景实战
2.1 NAT 架构规划

2.2 NAT Route 配置
使用Linux模拟路由器功能。
1、配置 eth0外 网卡
[root@route ~]# cat /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
id=eth0
type=ethernet
interface-name=eth0
[ethernet]
[ipv4]
address1=10.0.0.20/24
gateway=10.0.0.2 # 网关需要指向能上公网的IP
dns=223.5.5.5;
method=manual
# 重启网卡
[root@route ~]# nmcli connection reload && nmcli connection down eth0 && nmcli connection up eth02、配置 eth1内 网卡
[root@route ~]# cat /etc/NetworkManager/system-connections/eth1.nmconnection
[connection]
id=eth1
type=ethernet
interface-name=eth1
[ethernet]
[ipv4]
address1=172.16.1.20/24
method=manual
# 重启网卡
[root@route ~]# nmcli connection reload && nmcli connection down eth1 && nmcli connection up eth1vim新写的配置文件不被nmcli管理,使用nmcli connection migrate查看目前的所有文件
# 将新配置文件进行重加载
nmcli connection migrate /etc/NetworkManager/system-connections/eth1.nmconnection
# 再次重启
nmcli c reload
nmcli c up eth1
3、在 Route 节点启用 FORWARD 转发功能,实现路由功能。
[root@route ~]# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf && sysctl -p2.3 NAT RS节点配置
1、将所有RS的eth0网卡关闭;
2、将所有RS节点的eth1的网关指向到LVS的VIP地址上;
3、在所有RS节点上部署Nginx,后期通过LVS进行调度测试;
1、关闭所有RS节点的eth0网卡
[root@rs01 ~]# nmcli connection down eth02、配置所有RS节点的网关指向到LVS服务器的VIP地址上(所有的RS节点都需要操作)
[root@rs01 ~]# cat /etc/NetworkManager/system-connections/eth1.nmconnection
[connection]
id=eth1
type=ethernet
interface-name=eth1
[ethernet]
[ipv4]
address1=172.16.1.5/24
gateway=172.16.1.10 # 指向到LVS的VIP地址
dns=223.5.5.5;
method=manual
[root@proxy-node01 ~]# nmcli connection reload && nmcli connection down eth1 && nmcli connection up eth1
# 检查路由
[root@rs01 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.16.1.10 0.0.0.0 UG 100 0 0 eth13、在RS1节点上配置Nginx,然后测试访问
[root@rs01 ~]# yum install nginx -y
[root@rs01 ~]# vi /etc/nginx/conf.d/lvs.ops.net.conf
server {
listen 80;
server_name lvs.ops.net;
root /opt;
limit_rate 100k;
location / {
index index.html;
}
}
[root@rs01 ~]# dd if=/dev/zero of=/opt/bigdata bs=100M count=1
[root@rs01 ~]# echo "Web Page RS-Node1" > /opt/index.html
[root@rs01 ~]# systemctl start nginx
# 本机测试访问
[root@rs01 ~]# curl -HHost:lvs.ops.net http://172.16.1.5
Web Page RS-Node14、在RS2节点上配置Nginx,然后测试访问
[root@rs02 ~]# yum install nginx -y
[root@rs02 ~]# cat /etc/nginx/conf.d/lvs.ops.net.conf
server {
listen 80;
server_name lvs.ops.net;
root /opt;
limit_rate 100k;
location / {
index index.html;
}
}
[root@rs01 ~]# dd if=/dev/zero of=/opt/bigdata bs=100M count=1
[root@rs02 ~]# echo "Web Page RS-Node2" > /opt/index.html
[root@rs02 ~]# systemctl start nginx
# 本机测试访问
[root@rs02 ~]# curl -HHost:lvs.ops.net http://172.16.1.6
Web Page RS-Node22.4 NAT LVS节点配置
1、关闭eth0外网网卡
2、配置eth1网卡,将网关指向到路由器节点的内网IP;
3、添加VIP地址网卡配置,将VIP绑定到 eth1:1 子接口上;
4、开启 LVS节点的内核转发功能,不然 RS 节点返回的数据包经过LVS时会被丢弃。
5、配置 LVS NAT 负载均衡
1、关闭eth0网卡
[root@lvs01 ~]# nmcli connection down eth02、配置eth1网卡,将网关指向到路由器节点的内网IP
[root@lvs01 ~]# cat /etc/NetworkManager/system-connections/eth1.nmconnection
[connection]
id=eth1
type=ethernet
interface-name=eth1
[ethernet]
[ipv4]
address1=172.16.1.3/24
gateway=172.16.1.20 # 指向到路由器的IP
dns=223.5.5.5;
method=manual3、新增 VIP 地址的网卡配置,将 VIP 绑定到 eth1:1 网卡上。在Rockylinux9中不能使用配置文件方式指定 eth1:1 这样的设备,但可以通过以下命令的方式来临时添加VIP地址
[root@lvs01 ~]# ip addr add 172.16.1.10/32 dev eth1 label eth1:1
# 查看VIP是否配置成功
[root@lvs01 ~]# ip addr s eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:fa:4b:81 brd ff:ff:ff:ff:ff:ff
altname enp19s0
altname ens224
inet 172.16.1.3/24 brd 172.16.1.255 scope global noprefixroute eth1
valid_lft forever preferred_lft forever
inet 172.16.1.10/32 scope global eth1:1
valid_lft forever preferred_lft forever
inet6 fe80::3f2:1401:b0e9:8659/64 scope link noprefixroute
valid_lft forever preferred_lft forever4、开启 LVS 节点的内核转发功能,不然 RS 节点返回的数据包经过 DS 节点会被丢弃。
[root@lvs01 ~]# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf && sysctl -p5、配置LVS负载均衡
# 安装LVS
[root@lvs01 ~]# yum -y install ipvsadm
# 定义 LVS 集群
[root@lvs01 ~]# ipvsadm -A -t 172.16.1.10:80 -s rr
# 添加 RS1、RS2集群节点
[root@lvs01 ~]# ipvsadm -a -t 172.16.1.10:80 -r 172.16.1.5:80 -m
[root@lvs01 ~]# ipvsadm -a -t 172.16.1.10:80 -r 172.16.1.6:80 -m6、检查负载均衡配置
[root@lb01 ~]# 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.16.1.10:80 rr
-> 172.16.1.5:80 Masq 1 0 0
-> 172.16.1.6:80 Masq 1 0 02.5 客户端访问测试
1、关闭客户端eth1网卡;
2、配置客户端的eth0网关指向到路由器;
3、直接访问LVS的VIP地址;
注意:这属于伪实现,因为在实际的场景中,客户端是不可能直接指向到对端服务器的路由器上;
1、关闭客户端节点 eth1 网卡
[root@Client ~]# nmcli connection down eth12、配置客户端节点 eth0 网络
[root@Client ~]# cat /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
id=eth0
type=ethernet
interface-name=eth0
[ethernet]
[ipv4]
address1=10.0.0.100/24
gateway=10.0.0.20 # 真实场景不可能将客户端网关指向企业的路由器上
dns=223.5.5.5;
method=manual3、重启客户端网络
[root@Client ~]# nmcli connection reload && nmcli connection down eth0 && nmcli connection up eth04、使用 Client 测试访问效果
[root@Client ~]# curl -HHost:lvs.ops.net http://172.16.1.10
Web Page RS-Node2
[root@Client ~]# curl -HHost:lvs.ops.net http://172.16.1.10
Web Page RS-Node12.6 真实场景访问测试
1、删除客户端指向路由节点的网关
2、配置路由节点,添加DNAT配置
3、如果客户端需要上网,也可以添加⼀条SNAT(共享上网功能)
4、检查客户端究竟是与谁建⽴的TCP三次握手
1、删除 Client 节点的网关配置
[root@client ~]# sed -i '/gateway/d' /etc/NetworkManager/system-connections/eth0.nmconnection
[root@client ~]# nmcli connection reload && nmcli connection down eth0 && nmcli connection up eth0
# 查看路由表
[root@Client ~]# ip route
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.100 metric 1002、配置路由节点的DNAT以及SNAT
# DNAT (端口映射,虚拟环境使用)
[root@route ~]# iptables -t nat -A PREROUTING -d 10.0.0.20 -p tcp --dport 80 -j DNAT --to 172.16.1.10:80
#SNAT (让内部主机通过路由可以上网)
[root@route ~]# iptables -t nat -A POSTROUTING -s 172.16.1.0/24 -j SNAT --to 10.0.0.20
[root@web1 ~]# ping baidu.com
PING baidu.com (39.156.70.37) 56(84) 比特的数据。
来自 172.16.1.3 (172.16.1.3) icmp_seq=2 Redirect Host(新的下一跳: 172.16.1.20 (172.16.1.20))
来自 172.16.1.3 (172.16.1.3) icmp_seq=4 Redirect Host(新的下一跳: 172.16.1.20 (172.16.1.20))
来自 172.16.1.3 (172.16.1.3) icmp_seq=7 Redirect Host(新的下一跳: 172.16.1.20 (172.16.1.20))
来自 172.16.1.3 (172.16.1.3) icmp_seq=13 Redirect Host(新的下一跳: 172.16.1.20 (172.16.1.20))3、再次使用客户端进行测试
# 真实情况下,客户端节点也是无法连接企业内部网络
[root@Client ~]# curl -HHost:lvs.ops.net http://172.16.1.10
curl: (7) Couldn't connect to server
[root@Client ~]# curl -HHost:lvs.ops.net http://10.0.0.20
Web Page RS-Node2
[root@Client ~]# curl -HHost:lvs.ops.net http://10.0.0.20
Web Page RS-Node14、检查客户端是否是与 RS 节点建⽴的 TCP 连接(需要准备大文件持续下载,以便更好观测)
[root@rs01 ~]# netstat -nt
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 172.16.1.73:80 10.0.0.100:57426 ESTABLISHED
# windows cmd 查看
C:\Users\Administrator>netstat -ant | findstr "5541"
TCP 10.0.0.128:5541 10.0.0.20:80 ESTABLISHED InHost03 LVS负载均衡DR模型
1、LVS DR模型详解
它通过修改请求报文的目标 MAC 地址,然后根据算法挑选出合适的 RS 节点,进行转发。
(请求进⼊ DS Server 时做 MAC 地址替换,后端返回数据报文时无需经过 DS Server 节点,直接返回给客户端即可。)
1.1 DR基础图解

1.2 DR底层实现
客户端: 10.0.0.100(外网)
路由器: 10.0.0.20(外网) 、 172.16.1.20(内网)
DS 节点: 172.16.1.3(DIP) 、 172.16.1.10(VIP)
RS 节点: 172.16.1.5 、 172.16.1.6

问1:路由器如何找到 VIP 以及 MAC 地址呢?
答:路由器通过 ARP 广播获取VMAC,然后封装CIP、CMAC、VIP、VMAC,然后通过交换机转发至目标主机。
问2: RS 处理请求直接返回给 CIP ,不经过 LVS ,那么 RS 如何将数据包回传给 CIP?
由于 CIP 请求的是 VIP,而响应是通过 RIP 响应给CIP,所以数据报文⼀定会被丢弃。
那么就需要在所有的 RS 的 lo 接口上配置 VIP 地址。这样就可以通过 RS上的VIP 响应给 CIP 。
问3:所有RS节点都配置VIP,那么路由器在广播的时候,岂不是所有的VIP都会响应?
方式1:在路由器上绑定 VIP 与 VMAC 的对应关系。(但可能没有操作权限,且较为麻烦。)
方式2:在所有 RS 节点上配置 ARP 抑制,简单来说就是路由器广播获取 VMAC 时,所有的 RS 都不应答,其次所有的 RS 都不对外宣布自己的 VIP。
1.3 DR访问流程
1、当用户请求到达 DS节点 ,此时请求的数据报文会先到内核空间的 PREROUTING 链。 此时报文的 源IP为CIP , 目标IP为VIP 。
2、PREROUTING 检查发现数据包的 目标IP 是本机,将数据包送至 INPUT 链。
3、IPVS 比对数据包请求的服务是否为集群服务,是则将请求报文中的 源MAC 修改为 DMAC ,将 目标MAC 修改 RMAC ,然后将数据包通过 POSTROUTING 链发出。 此时的 源IP 和 目的IP 均未修改,仅将 源MAC 修改为 DMAC , 目标MAC 修改为 RMAC
4、RS 拆解数据报文发现请求的 IP 地址是本机,则会接收该数据报文,而后构建响应报文向外发出,此时的 源IP 是 VIP , 目标IP 是 CIP
5、响应报文最终送达至客户端
1.4 DR特性总结
1、请求报文必须由 DS 节点转发,但响应报文必须不经过 DS 节点
2、 RS 不能将网关指向 DS 节点的 DIP
3、 DS 和 RS 节点必须位于同⼀物理网络中,但不⼀定必须在同⼀个网段内
4、 DR 模型不支持地址转换,也不支持端口映射
5、 RS 可以是常⻅的操作系统 Windows、Linux、MacOS
6、 RS 在 lo 接口上配置 VIP
1.5 DR ARP参数
arp_ignore (控制系统在收到外部的 arp 请求时,是否应答。)
0 默认值,将本机所有接口的所有信息像每个连接的网络进行通告。
1 只应答本地主机访问网络接口( eth0-->lo ),才给予响应。
arp_announce (控制系统是否对外宣布自己的地址。)
0 默认值,把本机所有接口的所有信息向每个接口的网络进行通告。
1 "尽量避免" 将接口信息向非直接连接网络进行通告。
2 "必须避免" 将接口信息向非本网络进行通告。
2、DR 模型场景实践
2.1 DR 架构规划

2.2 DR Route配置
1、配置 eth0外 网卡
[root@route ~]# cat /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
id=eth0
type=ethernet
interface-name=eth0
[ethernet]
[ipv4]
address1=10.0.0.20/24
gateway=10.0.0.2 # 网关需要指向能上公网的IP
dns=223.5.5.5;
method=manual
# 重启网卡
[root@route ~]# nmcli connection reload && nmcli connection down eth0 && nmcli connection up eth02、配置 eth1内 网卡
[root@route ~]# cat /etc/NetworkManager/system-connections/eth1.nmconnection
[connection]
id=eth1
type=ethernet
interface-name=eth1
[ethernet]
[ipv4]
address1=172.16.1.20/24
method=manual
# 重启网卡
[root@route ~]# nmcli connection reload && nmcli connection down eth1 && nmcli connection up eth13、在 Route 节点启用 FORWARD 转发功能,实现路由功能
[root@route ~]# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf && sysctl -p2.3 DR RS节点配置
1、将所有RS的eth0网卡关闭;
2、将所有RS节点的eth1的网关指向能出公网的路由器;
3、在所有的RS节点上配置VIP;
4、在所有的RS节点上配置ARP抑制;
5、在所有RS节点上部署Nginx,后期通过LVS进行调度测试;
1、关闭所有RS节点的eth0网卡
[root@rs01 ~]# nmcli connection down eth0
[root@rs01 ~]# nmcli connection down eth02、配置所有RS节点的网关指向到LVS服务器的VIP地址上(所有的RS节点都需要操作)
[root@rs01 ~]# cat /etc/NetworkManager/system-connections/eth1.nmconnection
[connection]
id=eth1
type=ethernet
interface-name=eth1
[ethernet]
[ipv4]
address1=172.16.1.5/24
gateway=172.16.1.20 # 指向到能出公网的路由器地址
dns=223.5.5.5;
method=manual
[root@rs01 ~]# nmcli connection reload && nmcli connection down eth1 && nmcli connection up eth1
# 检查路由
[root@rs01 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.16.1.20 0.0.0.0 UG 100 0 0 eth1
172.16.1.0 0.0.0.0 255.255.255.0 U 100 0 0 eth13、在所有的RS节点的 lo:0 接口上添加VIP地址,在Rockylinux9中不能使用配置文件方式指定 lo:0 这样的设备,但可以通过以下命令的方式来临时添加VIP地址
[root@rs01 ~]# ip addr add 172.16.1.10/32 dev lo label lo:0
[root@rs02 ~]# ip addr add 172.16.1.10/32 dev lo label lo:0
# 检查IP地址
[root@rs01 ~]# ip addr
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 172.16.1.10/32 scope global lo:0
valid_lft forever preferred_lft forever4、在所有的RS节点上配置ARP抑制规则,不对外宣告本机 VIP 地址,也不响应其他节点发起 ARP请求 本机的 VIP;
echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "1" >/proc/sys/net/ipv4/conf/default/arp_ignore
echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
echo "2" >/proc/sys/net/ipv4/conf/default/arp_announce
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce5、在RS1节点上配置Nginx,然后测试访问
[root@rs01 ~]# yum install nginx -y
[root@rs01 ~]# cat /etc/nginx/conf.d/lvs.ops.net.conf
server {
listen 80;
server_name lvs.ops.net;
root /opt;
limit_rate 100k;
location / {
index index.html;
}
}
[root@rs01 ~]# dd if=/dev/zero of=/opt/bigdata bs=100M count=1
[root@rs01 ~]# echo "Web Page RS-Node1" > /opt/index.html
[root@rs01 ~]# systemctl start nginx
# 本机测试访问
[root@rs01 ~]# curl -HHost:lvs.ops.net http://172.16.1.5
Web Page RS-Node16、在RS2节点上配置Nginx,然后测试访问
[root@rs02 ~]# yum install nginx -y
[root@rs02 ~]# cat /etc/nginx/conf.d/lvs.ops.net.conf
server {
listen 80;
server_name lvs.ops.net;
root /opt;
limit_rate 100k;
location / {
index index.html;
}
}
[root@rs01 ~]# dd if=/dev/zero of=/opt/bigdata bs=100M count=1
[root@rs02 ~]# echo "Web Page RS-Node2" > /opt/index.html
[root@rs02 ~]# systemctl start nginx
# 本机测试访问
[root@rs02 ~]# curl -HHost:lvs.ops.net http://172.16.1.6
Web Page RS-Node22.4 DR LVS节点配置
1、关闭eth0外网网卡
2、配置eth1网卡,将网关指向能出公网的路由器;
3、添加VIP地址网卡配置,将VIP绑定到 eth1:1 子接口上;
4、配置 LVS NAT 负载均衡为DR模型
1、关闭eth0网卡
[root@lvs01 ~]# nmcli connection down eth02、配置eth1网卡,将网关指向到路由器节点的内网IP
[root@lvs01 ~]# cat /etc/NetworkManager/system-connections/eth1.nmconnection
[connection]
id=eth1
type=ethernet
interface-name=eth1
[ethernet]
[ipv4]
address1=172.16.1.3/24
gateway=172.16.1.20 # 指向到路由器的IP
dns=223.5.5.5;
method=manual3、新增 VIP 地址的网卡配置,将 VIP 绑定到 eth1:1 网卡上。在Rockylinux9中不能使用配置文件方式指定 eth1:1 这样的设备,但可以通过以下命令的方式来临时添加VIP地址
[root@lvs01 ~]# ip addr add 172.16.1.10/32 dev eth1 label eth1:1
# 查看VIP是否配置成功
[root@lvs01 ~]# ip addr
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state U
P group default qlen 1000
link/ether 52:54:00:f7:76:38 brd ff:ff:ff:ff:ff:ff
altname enp0s4
altname ens4
inet 172.16.1.3/24 brd 172.16.1.255 scope global noprefixroute eth1
valid_lft forever preferred_lft forever
inet 172.16.1.10/32 scope global eth1:14、配置LVS负载均衡为DR模型
# 定义 LVS 集群
[root@lvs01 ~]# ipvsadm -A -t 172.16.1.10:80 -s rr
# 添加 RS1、RS2集群节点
[root@lvs01 ~]# ipvsadm -a -t 172.16.1.10:80 -r 172.16.1.5:80 -g
[root@lvs01 ~]# ipvsadm -a -t 172.16.1.10:80 -r 172.16.1.6:80 -g5、检查负载均衡配置
[root@lb01 ~]# 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.16.1.10:80 rr
-> 172.16.1.5:80 Route 1 0 0
-> 172.16.1.6:80 Route 1 0 02.5 客户端访问测试
1、关闭客户端eth1网卡;
2、配置客户端的eth0网关指向到路由器;
3、直接访问LVS的VIP地址;
注意:这属于伪实现,因为在实际的场景中,客户端是不可能直接指向到对端服务器的网关上;
1、关闭客户端节点 eth1 网卡
[root@Client ~]# nmcli connection down eth12、配置客户端节点 eth0 网络
[root@Client ~]# cat /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
id=eth0
type=ethernet
interface-name=eth0
[ethernet]
[ipv4]
address1=10.0.0.100/24
gateway=10.0.0.20 # 真实场景不可能将客户端网关指向企业的路由器上
dns=223.5.5.5;
method=manual3、重启客户端网络
[root@Client ~]# nmcli connection reload && nmcli connection down eth0 && nmcli connection up eth04、使用 Client 测试访问效果
[root@Client ~]# curl -HHost:lvs.ops.net http://172.16.1.10
Web Page RS-Node2
[root@Client ~]# curl -HHost:lvs.ops.net http://172.16.1.10
Web Page RS-Node12.6 真实场景访问测试
1、删除客户端指向路由节点的网关;
2、配置路由节点,添加DNAT配置;
3、如果客户端需要上网,也可以添加⼀条SNAT(共享上网功能);
4、检查客户端究竟是与谁建⽴的TCP三次握手;
1、删除 Client 节点的网关配置
[root@client ~]# sed -i '/gateway/d' /etc/NetworkManager/system-connections/eth0.nmconnection
[root@client ~]# nmcli connection reload && nmcli connection down eth0 && nmcli connection up eth0
# 查看路由表
[root@Client ~]# route -n
Destination Gateway Genmask Flags Metric Ref Use Iface
10.0.0.0 0.0.0.0 255.255.255.0 U 100 0 0 eth02、配置路由节点的DNAT以及SNAT
# DNAT (端口映射,虚拟环境使用)
[root@route ~]# iptables -t nat -A PREROUTING -d 10.0.0.20 -p tcp --dport 80 -j DNAT --to 172.16.1.10:80
#SNAT (让内部主机通过路由可以上网)
[root@route ~]# iptables -t nat -A POSTROUTING -s 172.16.1.0/24 -j SNAT --to 10.0.0.203、再次使用客户端进行测试
# 真实情况下,客户端节点也是无法连接企业内部网络
[root@Client ~]# curl -HHost:lvs.ops.net http://172.16.1.10
curl: (7) Couldn't connect to server
[root@Client ~]# curl -HHost:lvs.ops.net http://10.0.0.20
Web Page RS-Node2
[root@Client ~]# curl -HHost:lvs.ops.net http://10.0.0.20
Web Page RS-Node14、检查客户端是否是与 RS 节点建⽴的 TCP 连接(需要准备大文件持续下载,以便更好观测);
[root@rs01 ~]# netstat -nt
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 172.16.1.10:80 10.0.0.100:53240 ESTABLISHED3、Shell脚本配置LVS DR实践
在网络规划没有问题的情况下,通过脚本来实现 LVS DR 模型。(注意修改脚本中的 IP 地址)
所有的节点,LVS、RS的网关都是指向到路由器节点 (172.16.1.20)
3.1 DS配置脚本
[root@lvs-01 ~]# cat lvs_dr.sh
#!/usr/bin/bash
VIP=172.16.1.10
RS1=172.16.1.5
RS2=172.16.1.6
HTTP_PORT=80
HTTPS_PORT=443
SCHEDULER=rr
DEV=eth1
DEV_LABLE=eth1:1
case $1 in
start)
# 配置VIP
ip addr add ${VIP}/32 dev ${DEV} label ${DEV_LABLE}
# 配置LVS规则
ipvsadm -A -t ${VIP}:${HTTP_PORT} -s ${SCHEDULER}
ipvsadm -a -t ${VIP}:${HTTP_PORT} -r ${RS1} -g
ipvsadm -a -t ${VIP}:${HTTP_PORT} -r ${RS2} -g
# 配置LVS规则HTTPS
ipvsadm -A -t ${VIP}:${HTTPS_PORT} -s ${SCHEDULER}
ipvsadm -a -t ${VIP}:${HTTPS_PORT} -r ${RS1} -g
ipvsadm -a -t ${VIP}:${HTTPS_PORT} -r ${RS2} -g
;;
stop)
# 删除VIP
ip addr del ${VIP}/32 dev ${DEV} label ${DEV_LABLE}
# 清除IPVS规则
ipvsadm -C
;;
*)
echo "Usage: sh $0 { start | stop }"
;;
esac3.2 RS配置脚本
[root@web01 ~]# cat lvs_rs.sh
#!/usr/bin/bash
VIP=172.16.1.10
DEV=lo
DEV_LABLE=lo:0
case $1 in
start)
# 配置ARP抑制
echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "1" >/proc/sys/net/ipv4/conf/default/arp_ignore
echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
echo "2" >/proc/sys/net/ipv4/conf/default/arp_announce
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
# 配置VIP
ip addr add ${VIP}/32 dev ${DEV} label ${DEV_LABLE}
;;
stop)
# 取消ARP抑制规则
echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "0" >/proc/sys/net/ipv4/conf/default/arp_ignore
echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce
echo "0" >/proc/sys/net/ipv4/conf/default/arp_announce
echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce
# 删除VIP
ip addr del ${VIP}/32 dev ${DEV} label ${DEV_LABLE}
;;
*)
echo "Usage: sh $0 { start | stop }"
esac04 LVS负载均衡高可用
1、LVS 高可用介绍
1.1 LVS目前面临的问题
尽管LVS提供了强大的负载均衡功能,但它在某些方面还是存在局限性:
1、健康检查:LVS本身不提供健康检查。如果⼀个RS宕机,LVS会继续将流量调度到这个故障的RS节点上。
2、单点故障:如果LVS节点本身发生故障,那么整个集群就无法正常对外提供服务。进行路由的。
3、配置不持久:LVS的配置是临时的,如果服务器出现重启,之前所有的配置都会丢失,需要重新配置。
1.2 LVS高可用解决方案
Keepalived提供了强大的功能,来弥补LVS的不足:
1、健康检查: Keepalived引⼊了健康检查机制,能够监测RS的状态并自动从负载均衡池中添加或移除故障节点,确保流量只会被路由到正常节点上。
2、故障转移: 配置多个LVS节点并使用VRRP协议,Keepalived就可以在主LVS节点故障时自动切换到备用的LVS节点是,以此来实现高可用。
3、配置持久化: 在Keepalived的配置文件,可以直接定义LVS负载均衡的规则以及健康检查机制等,并且这些配置在服务重启后,依然有效。
总结: Keepalived 就是为 LVS 而诞生的。
2、LVS高可用配置实践
2.1 Master节点配置
1、安装 Keepalived
[root@lvs01 ~]# yum install keepalived -y2、配置Keepalived
[root@lb01 ~]# cat /etc/keepalived/keepalived.conf
global_defs {
router_id lb01
}
vrrp_instance VI_1 {
state MASTER
priority 200
interface eth1
virtual_router_id 50
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.16.1.10
}
}
# 配置集群地址访问的IP+Port
virtual_server 172.16.1.10 80 {
# 健康检查的时间,单位:秒
delay_loop 6
# 配置负载均衡的算法
lb_algo rr
# 设置LVS的模式 NAT|TUN|DR
lb_kind DR
# 设置会话持久化的时间
# persistence_timeout 30
# 设置协议
protocol TCP
# 负载均衡后端的真实服务节点RS-1
real_server 172.16.1.5 80 {
# 权重配比设置为1
weight 1
# 设置健康检查
TCP_CHECK {
# 检测后端80端口
connect_port 80
# 超时时间
connect_timeout 3
# 重试次数2次
nb_get_retry 2
# 间隔时间3s
delay_beefore_retry 3
}
}
# 负载均衡后端的真实服务节点RS-2
real_server 172.16.1.6 80 {
# 权重配比设置为1
weight 1
# 设置健康检查
TCP_CHECK {
# 检测后端80端口
connect_port 80
# 超时时间
connect_timeout 3
# 重试次数2次
nb_get_retry 2
# 间隔时间3s
delay_beefore_retry 3
}
}
}
[root@lvs01 ~]# systemctl enable --now keepalived2.2 Backup节点配置
1、安装 Keepalived
[root@lvs02 ~]# yum install keepalived -y2、配置Keepalived
[root@lvs-02 ~]# cat /etc/keepalived/keepalived.conf
global_defs {
router_id lb02
}
vrrp_instance VI_1 {
state BACKUP
priority 150
interface eth1
virtual_router_id 50
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.16.1.10
}
}
# 配置集群地址访问的IP+Port
virtual_server 172.16.1.10 80 {
# 健康检查的时间,单位:秒
delay_loop 6
# 配置负载均衡的算法
lb_algo wlc
# 设置LVS的模式 NAT|TUN|DR
lb_kind DR
# 设置会话持久化的时间
# persistence_timeout 30
# 设置协议
protocol TCP
# 负载均衡后端的真实服务节点RS-1
real_server 172.16.1.5 80 {
# 权重配比设置为1
weight 1
# 设置健康检查
TCP_CHECK {
# 检测后端80端口
connect_port 80
# 超时时间
connect_timeout 3
# 重试次数2次
nb_get_retry 2
# 间隔时间3s
delay_beefore_retry 3
}
}
# 负载均衡后端的真实服务节点RS-2
real_server 172.16.1.6 80 {
# 权重配比设置为1
weight 1
# 设置健康检查
TCP_CHECK {
# 检测后端80端口
connect_port 80
# 超时时间
connect_timeout 3
# 重试次数2次
nb_get_retry 2
# 间隔时间3s
delay_beefore_retry 3
}
}
}
[root@lvs02 ~]# systemctl enable --now keepalived3、LVS高可用架构测试
3.1 当前架构环境说明
当启动两台 LVS 节点的 Keepalived 软件后,会发现两台节点都有 LVS的规则,但仅在 Master 节点上有 VIP 地址;
1、当有新的请求进⼊时,所有的请求都会发送至 Master 节点;
2、当 Master 节点故障, VIP 地址会漂移到 Backup 节点;
3、最后由 Backup 节点继续对外提供服务,以此来实现 LVS 的高可用;
1、检查 LVS-Master 节点
[root@lvs01 ~]# ip addr | grep 172.16.1.10
inet 172.16.1.10/32 scope global eth1
[root@lvs-01 ~]# 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.16.1.10:80 rr
-> 172.16.1.5:80 Route 1 0 0
-> 172.16.1.6:80 Route 1 0 02、检查 LVS-BACKUP 节点
[root@lvs02 ~]# ip addr | grep 172.16.1.10
[root@lb02 ~]# 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.16.1.10:80 rr
-> 172.16.1.5:80 Route 1 0 0
-> 172.16.1.6:80 Route 1 0 03.2 模拟RS节点故障
模拟 Real Server 故障(关闭⼀台 Nginx ), Keeplaived 检测后会自动将节点移除
1、关闭RS1节点的Nginx
[root@rs01 ~]# systemctl stop nginx2、检查LVS规则是否发生变化
[root@lvs01 ~]# 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.16.1.10:80 rr
-> 172.16.1.6:80 Route 1 0 0 #仅剩下6节点了3、查看Keepalived是否输出相应的信息
[root@lvs01 ~]# systemctl status keepalived.service
lvs01.ops.net Keepalived_healthcheckers[25970]: TCP_CHECK on service [172.16.1.5]:tcp:80 failed after 1 retries.
lvs01.ops.net Keepalived_healthcheckers[25970]: Removing service [172.16.1.5]:tcp:80 from VS [172.16.1.10]:tcp:80
# 如果恢复nginx,则会自动加⼊集群
lvs01.ops.net Keepalived_healthcheckers[25970]: TCP connection to [172.16.1.73]:tcp:80 success.
lvs01.ops.net Keepalived_healthcheckers[25970]: Adding service [172.16.1.73]:tcp:80 to VS [172.16.1.10]:tcp:803.3 模拟LVS节点故障
模拟 DS 故障,将 Master 节点 Keepalived 软件关闭,达到故障效果;
1、 Master 节点关闭Keepalived,会发现 VIP 地址自动漂移到备节点,同时Master上的 lvs 规则也会被清空;
[root@lvs01 ~]# systemctl stop keepalived.service
[root@lvs01 ~]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn2、检查Backup是否有VIP、以及IPVS规则
[root@lvs02 ~]# ip addr |grep 172.16.1.10
inet 172.16.1.10/32 scope global eth1
[root@lvs02 ~]# 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.16.1.10:80 wlc
-> 172.16.1.5:80 Route 1 0 0
-> 172.16.1.6:80 Route 1 0 03、使用客户端测试,验证VIP地址漂移后是否能正常对外提供服务
客户端测试,无任何异常
[root@client ~]# curl -HHost:lvs.ops.com http://10.0.0.200
Web Page RS-Node2
[root@client ~]# curl -HHost:lvs.ops.com http://10.0.0.200
Web Page RS-Node105 LVS负载均衡调度算法
1、LVS调度算法详解
LVS 根据后端服务器的负载,或其他的计算的标准,判断挑选哪台 RS 来进行请求处理。调度算法主要分为”静态调度算法“、”动态调度算法“。
静态调度算法: RR、WRR、SH、DH
动态调度算法: LC、WLC、SED、NQ、LBLC、LBLCR
2、LVS静态调度算法
静态:仅根据算法本身进行调度,不考虑后端实际负载情况(起点公平)
2.1 RR
RR:round robin 轮询调度算法,将每⼀次用户的请求,轮流分配给 Real Server 节点。
[root@lb01 ~]# ipvsadm -E -t 172.16.1.10:80 -s rr
[root@lb01 ~]# 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.16.1.10:80 rr
-> 172.16.1.7:80 Route 1 0 0
-> 172.16.1.8:80 Route 1 0 02.2 WRR
WRR:weighted round robin 加权轮询调度算法,根据服务器的硬件情况、以及处理能⼒,为每台服务器分配不同的权值,使其能够接受相应权值的请求。
[root@lb01 ~]# ipvsadm -E -t 172.16.1.10:80 -s wrr
[root@lb01 ~]# ipvsadm -e -t 172.16.1.10:80 -r 172.16.1.7:80 -g -w 5
[root@lb01 ~]# ipvsadm -e -t 172.16.1.10:80 -r 172.16.1.8:80 -g -w 1
[root@lb01 ~]# 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.16.1.10:80 wrr
-> 172.16.1.7:80 Route 5 0 0
-> 172.16.1.8:80 Route 1 0 02.3 SH
SH:Source Hashing 源地址 hash 调度算法,将请求的源 IP 地址进行 Hash 运算,得到⼀个具体的数值,同时对后端服务器进行编号,按照运算结果将请求分发到对应编号的服务器上。
1、可以实现不同来源 IP 的请求进行负载分发;
2、同时还能实现相同来源 IP 的请求始终被派发至某⼀台特定的节点;
[root@lb01 ~]# ipvsadm -E -t 172.16.1.10:80 -s sh
[root@lb01 ~]# 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.16.1.10:80 sh # 配置了Weight无效
-> 172.16.1.7:80 Route 5 0 3
-> 172.16.1.8:80 Route 1 0 12.4 DH
DH:destination hash 目标地址 hash 将客户端的请求,始终发往同⼀个RS 。
应用场景: LVS-cache-源站 ,始终调度到指定的 cache ,加速用户体验。

[root@lb01 ~]# ipvsadm -E -t 172.16.1.10:80 -s dh
[root@lb01 ~]# 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.16.1.10:80 dh
-> 172.16.1.7:80 Route 5 0 0
-> 172.16.1.8:80 Route 1 0 03、LVS动态调度算法
动态:根据算法及 RS 节点负载状态进行调度,较小的 RS 将被调度(保证结果公平)
3.1 LC
LC:Least-Connection 最少连接数调度算法,哪台 RS 连接数少就将请求调度至哪台 RS 。
算法: Overhead = ( Active * 256 + Inactive仅连接 ) ⼀个活动连接相当于256个非活动连接

3.2 WLC
WLC:Weighted Least-Connection 加权最小连接数(默认调度算法),在服务器性能差异较大的情况下,采用“加权最少链接”调度算法优化负载均衡性能,权值较高的 RS 节点,将承受更多的连接;负载均衡可以自动问询 RS 节点服务器的负载状态,通过算法计算当前连接数最少的节点,而后将新的请求调度至该节点。
算法: Overhead =( Active * 256 + Inactive )/Weight

3.3 SED
SED:Shortest Expected Delay 最短期望延迟尽可能让权重高的优先接收请求,不考虑非活动状态,把当前处于活动状态的数目+1,通过算法计算当前连接数最少的节点,而后将新的请求调度至该节点。
算法:在WLC基础上改进, Overhead = (ACTIVE+1)*256/Weight

3.3 NQ
NQ:Never Queue 永不排队/最少队列调度
原理: SED 算法由于某台服务器的权重较小,比较空闲,甚至接收不到请求,而权重大的服务器会很忙,而 NQ 算法是说不管权重多大都会被分配到请求。简单来说,就是无需队列,如果有台 Real Server 的连接数为0会直接分配过去,后续采用 SED 算法
算法: Overhead = (ACTIVE+1)*256/Weight
3.4 LBLC
LBLC:Locality-Based Least-Connection 动态目标地址 hash 调度算法,解决 DH 调度算法负载不均衡。
应用场景: LVS-cache-源站 ,此前 DH 算法始终调度到后端 Cache1 节点,会造成 Cache1 负载过高, LBLC 会根据负载均衡动态调度到后端其他 Cache 节点。

3.5 LBLCR
LBLCR: Locality-Based Least-Connection with Replication 带复制功能的LBLC算法,解决LBLC负载不均衡的问题
应用场景: LVS-cache-源站 ,此前 LBLC 算法始终调度到后端 Cache1 节点,会造成 Cache1 负载过高,会根据负载均衡动态调度到后端其他 Cache 节点,同时也会将缓存数据同步⼀份至 Cache1、Cache2 节点。

06 LVS负载均衡场景实践
1、LVS实现MySQL负载均衡
1.1 场景说明
使用LVS的DR模型,来对MySQL进行的实例进行负载均衡调度。
1、准备两台MySQL服务器
2、关闭eth0网关
3、配置对应的eth1网卡:将网关指向出口的路由器,也就是 172.16.1.20
4、安装MySQL服务,然后配置MySQL服务允许远程用户能访问
5、为两台RS节点配置VIP地址,并且配置ARP抑制,可以执行 lvs_rs.sh 脚本
6、配置LVS规则,定义⼀个3306的集群,然后将请求调度到内部数据库节点
7、配置路由器端口映射,将请求公网地址的3306,映射到VIP地址的3306
1.2 地址规划
1.3 安装MySQL
1、安装MySQL
[root@web03 ~]# yum install mysql mysql-server -y2、配置⼀个可以远程访问的账户
mysql> create user 'lvs'@'%' identified by 'ops.net';
mysql> grant all privileges on *.* to 'lvs'@'%';
mysql> flush privileges;1.4 准备基础环境
1、关闭eth0网卡
[root@nfs ~]# nmcli connection down eth02、配置eth1网卡,将网关指向到路由器上
[root@nfs ~]# sed -i '/^address/a gateway=172.16.1.20' /etc/NetworkManager/system-connections/eth1.nmconnection
[root@nfs ~]# nmcli connection reload
[root@nfs ~]# nmcli connection down eth1 && nmcli connection up eth1
[root@nfs ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.16.1.20 0.0.0.0 UG 100 0 0 eth13、配置VIP、以及ARP的抑制,可以通过 lvs_rs.sh 脚本来实现
[root@nfs ~]# sh lvs_rs.sh start
# 检查是否有VIP
[root@nfs ~]# ifconfig lo:0
lo:0: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 172.16.1.10 netmask 255.255.255.255
loop txqueuelen 1000 (Local Loopback)1.5 配置LVS调度规则
方式1:通过命令行定义负载均衡规则
[root@lvs01 ~]# ipvsadm -A -t 172.16.1.10:3306 -s rr
[root@lvs01 ~]# ipvsadm -a -t 172.16.1.10:3306 -r 172.16.1.22:3306 -g
[root@lvs01 ~]# ipvsadm -a -t 172.16.1.10:3306 -r 172.16.1.9:3306 -g
# 检查
[root@lvs01 ~]# 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.16.1.10:3306 rr
-> 172.16.1.9:3306 Route 1 0 0
-> 172.16.1.22:3306 Route 1 0 0方式2:通过 keepalived 配置文件来定义负载均衡规则
# 配置集群地址访问的IP+Port
virtual_server 172.16.1.10 3306 {
delay_loop 6
lb_algo rr
lb_kind DR
protocol TCP
# 负载均衡后端的真实服务节点RS-1
real_server 172.16.1.9 3306 {
weight 1
TCP_CHECK {
connect_port 3306
connect_timeout 3
nb_get_retry 2
delay_beefore_retry 3
}
}
# 负载均衡后端的真实服务节点RS-2
real_server 172.16.1.22 3306 {
weight 1
TCP_CHECK {
connect_port 3306
connect_timeout 3
nb_get_retry 2
delay_beefore_retry 3
}
}
}1.6 路由器配置端口映射
1、将所有请求路由器公网的3306,调度到VIP的3306端口上
iptables -t nat -A PREROUTING -d 10.0.0.20 -p tcp --dport 3306 -j DNAT --to 172.16.1.10:33062、检查iptables的NAT规则
[root@route ~]# iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- 0.0.0.0/0 10.0.0.20 tcp dpt:3306
to:172.16.1.10:33061.7 客户端测试
1、客户端需要安装mysql命令
[root@clinet ~]# dnf -y install mariadb2、连接对应的MySQL测试
[root@clinet ~]# mysql -h 10.0.0.20 -ulvs -pops.net
mysql> select @@hostname;
+-----------------+
| @@hostname |
+-----------------+
| web03.ops.net |
+-----------------+
1 row in set (0.01 sec)
[root@clinet ~]# mysql -h 10.0.0.20 -ulvs -pops.net
mysql> select @@hostname;
+---------------+
| @@hostname |
+---------------+
| nfs.ops.net |
+---------------+
1 row in set (0.00 sec)2、配置四七层负载均衡
1、准备两台LVS节点,实现主备模式;
2、准备两台七层负载均衡,实现集群模式;
3、准备两台web节点,提供真实的站点内容;
4、关闭eth0的网络接口,配置eth1的网关指向到 172.16.1.20
2.1 配置七层负载均衡
1、关闭eth0的网络接口
2、配置eth1的网关指向到 172.16.1.20
3、配置VIP、以及ARP的抑制,可以执行 lvs_rs.sh 脚本
4、定义⼀个域名 lvs.ops.net ,然后代理到后端集群 172.16.1.7、172.16.1.8
1、关闭eth0
2、配置eth1的网关
[root@proxy1 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
TYPE="Ethernet"
BOOTPROTO=none
DEFROUTE="yes"
NAME="eth0"
DEVICE="eth0"
ONBOOT="yes"
NETMASK=255.255.255.0
IPADDR=172.16.1.11
GATEWAY=172.16.1.203、配置VIP、ARP抑制,7层负载均衡主机配置
ip addr add 172.16.1.10/32 dev lo label lo:1
echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "1" >/proc/sys/net/ipv4/conf/default/arp_ignore
echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
echo "2" >/proc/sys/net/ipv4/conf/default/arp_announce
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce4、配置七层负载均衡(两台负载均衡都需要配置)
[root@proxy02 ~]# vim /etc/nginx/conf.d/proxy_lvs.ops.net.conf
upstream lvs {
server 172.16.1.7:80;
server 172.16.1.8:80;
}
server {
listen 80;
server_name lvs.ops.net;
location / {
proxy_pass http://lvs;
proxy_set_header Host $http_host;
}
}2.2 配置应用服务器
1、应用服务器不需要配置网关指向,只要七层负载均衡能访问即可;
[root@web01 ~]# vim /etc/nginx/conf.d/lvs.ops.net.conf
server {
listen 80;
server_name lvs.ops.net;
root /opt;
location / {
index index.html;
}
}2、重启Nginx
[root@web01 ~]# nginx -t
[root@web01 ~]# systemctl reload nginx2.3 配置四层负载均衡
[root@lvs01 ~]# ipvsadm -A -t 172.16.1.100:80 -s rr
[root@lvs01 ~]# ipvsadm -a -t 172.16.1.100:80 -r 172.16.1.5:80 -g
[root@lvs01 ~]# ipvsadm -a -t 172.16.1.100:80 -r 172.16.1.6:80 -g
[root@lvs01 ~]# 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.16.1.100:80 rr
-> 172.16.1.5:80 Route 1 0 0
-> 172.16.1.6:80 Route 1 0 02.4 路由器配置端口映射
[root@route ~]# iptables -t nat -A PREROUTING -d 10.0.0.20 -p tcp --dport 80 -j DNAT --to 172.16.1.100:802.5 配置LVS支持HTTPS
1、配置路由器的映射
[root@route ~]# iptables -t nat -A PREROUTING -d 10.0.0.20 -p tcp --dport 443 -j DNAT --to 172.16.1.10:4432、配置LVS调度规则
[root@lvs01 ~]# ipvsadm -A -t 172.16.1.10:443 -s rr
[root@lvs01 ~]# ipvsadm -a -t 172.16.1.10:443 -r 172.16.1.5:443
[root@lvs01 ~]# ipvsadm -a -t 172.16.1.10:443 -r 172.16.1.6:443
[root@lvs01 ~]# 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.16.1.10:80 rr
-> 172.16.1.5:80 Route 1 1 1
-> 172.16.1.6:80 Route 1 1 1
TCP 172.16.1.10:443 rr
-> 172.16.1.5:443 Route 1 0 0
-> 172.16.1.6:443 Route 1 0 0 3、七层负载均衡主机
[root@proxy1 ~]# cat /etc/nginx/conf.d/proxy_lvs.ops.net.conf
upstream lvs {
server 172.16.1.5:80;
server 172.16.1.6:80;
}
server {
listen 443 ssl;
server_name www.zhouhaoit.com;
#ssl on;
ssl_certificate ssl_key/www.zhouhaoit.com.pem;
ssl_certificate_key ssl_key/www.zhouhaoit.com.key;
location / {
proxy_pass http://lvs;
proxy_set_header Host $http_host;
}
}
[root@proxy1 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
TYPE="Ethernet"
BOOTPROTO=none
DEFROUTE="yes"
NAME="eth0"
DEVICE="eth0"
ONBOOT="yes"
NETMASK=255.255.255.0
IPADDR=172.16.1.11
GATEWAY=172.16.1.204、web01和web02节点
[root@web01 ~]# cat /etc/nginx/conf.d/lvs.ops.net.conf
server {
listen 80;
server_name www.zhouhaoit.com;
root /opt;
limit_rate 100k;
location / {
index index.html;
}
}
[root@web01 ~]# cat /etc/NetworkManager/system-connections/eth1.nmconnection
[connection]
id=eth1
type=ethernet
interface-name=eth1
[ethernet]
[ipv4]
address1=172.16.1.5/24
#gateway=172.16.1.20
dns=223.5.5.5;
method=manual
2.6 Rocky9部署PHP7.4.33
部署参考:https://rpms.remirepo.net/wizard/
(如果第一条执行不了则)
cat > /etc/yum.repos.d/crb.repo << EOF
[crb]
name=Rocky Linux \$releasever - CRB
baseurl=https://dl.rockylinux.org/\$contentdir/\$releasever/CRB/\$basearch/os/
# 备用地址(若主地址不通,自动切换)
mirrorlist=https://mirrors.rockylinux.org/mirrorlist?arch=\$basearch&repo=CRB-\$releasever
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rockyofficial
enabled=1
# 允许解析变量
metadata_expire=6h
EOFcat > /etc/yum.repos.d/crb.repo << EOF
[crb]
name=Rocky Linux \$releasever - CRB
baseurl=https://dl.rockylinux.org/\$contentdir/\$releasever/CRB/\$basearch/os/
# 备用地址(若主地址不通,自动切换)
mirrorlist=https://mirrors.rockylinux.org/mirrorlist?arch=\$basearch&repo=CRB-\$releasever
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rockyofficial
enabled=1
# 允许解析变量
metadata_expire=6h
EOF
dnf config-manager --set-enabled crb
dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm -y
dnf install https://rpms.remirepo.net/enterprise/remi-release-9.rpm -y
dnf module install php:remi-7.4 -y
useradd www
sed -i '/^user/c user = www' /etc/php-fpm.d/www.conf
sed -i '/^group/c group = www' /etc/php-fpm.d/www.conf
systemctl enable --now php-fpm
mv /etc/nginx/default.d/php.conf /opt/
mv /etc/nginx/conf.d/php-fpm.conf /opt/
cat /etc/nginx/conf.d/lvs.ops.net.conf
server {
listen 80;
server_name www.zhouhaoit.com;
root /opt;
limit_rate 100k;
location ~ \.php$ {
root /opt;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
grep ^listen /etc/php-fpm.d/www.conf
listen = 127.0.0.1:9000
cat /opt/info.php
<?php
phpinfo();
?>
dnf -y install php-mysqli
systemctl restart php-fpm nginx
cat /opt/mysqli.php
<?php
$servername = "172.16.1.5";
$username = "lvs";
$password = "ops.net";
// 创建连接
$conn = mysqli_connect($servername,$username, $password);
// 检测连接
if (!$conn) {
die("Connection failed: " .
mysqli_connect_error());
}
echo "php连接MySQL数据库成功";
?>
dnf -y install php-mysqli
php /opt/mysqli.php
php连接MySQL数据库成功
dnf -y install unzip
unzip wordpress-6.8.3.zip
chown -R nginx.nginx /opt/wordpress
cat /etc/nginx/conf.d/lvs.ops.net.conf
server {
listen 80;
server_name www.zhouhaoit.com;
root /opt/wordpress;
index index.php;
location ~ \.php$ {
index index.php;
root /opt/wordpress;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
systemctl restart php-fpm nginx
head -2 /opt/wordpress/wp-admin/setup-config.php
<?php
#添加下面一行
$_SERVER['HTTPS'] = 'on';
mysql> create database wordpress;




head -2 /opt/wordpress/wp-login.php
<?php
#添加下面一行
$_SERVER['HTTPS'] = 'on';
head -2 /opt/wordpress/wp-admin/index.php
<?php
#添加下面一行
$_SERVER['HTTPS'] = 'on';
7层负载均衡
[root@proxy1 ~]# cat /etc/nginx/conf.d/proxy_lvs.ops.net.conf
upstream lvs {
server 172.16.1.5:80;
# server 172.16.1.6:80;
}
server {
#listen 80;
listen 443 ssl;
server_name www.zhouhaoit.com;
#ssl on;
ssl_certificate ssl_key/www.zhouhaoit.com.pem;
ssl_certificate_key ssl_key/www.zhouhaoit.com.key;
location / {
proxy_pass http://lvs;
proxy_set_header Host $http_host;
root /opt/wordpress;
}
# location ~* \.(jpg|jpeg|png|gif|ico)$ {
# proxy_pass http://lvs;
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_pass_header Content-Type;
# }
}
#server {
# listen 80;
# server_name www.zhouhaoit.com;
# return 302 https://$server_name$request_uri;
#}
[root@proxy1 ~]# ip a
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 172.16.1.10/32 scope global lo:1
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 pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:a2:01:02 brd ff:ff:ff:ff:ff:ff
inet 172.16.1.11/24 brd 172.16.1.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fea2:102/64 scope link
valid_lft forever preferred_lft forever
echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "1" >/proc/sys/net/ipv4/conf/default/arp_ignore
echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
echo "2" >/proc/sys/net/ipv4/conf/default/arp_announce
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce4层负载均衡
[root@lb01 ~]# 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.16.1.10:443 rr
-> 172.16.1.11:443 Route 1 1 0
[root@lb01 ~]# sysctl -p
net.ipv4.ip_forward = 1路由器主机
[root@route ~]# iptables -t nat -A PREROUTING -d 10.0.0.20 -p tcp --dport 443 -j DNAT --to 172.16.1.10:443
[root@route ~]# sysctl -p
net.ipv4.ip_forward = 1