| LVS |

1、LVS介绍

LVS(Linux Virtual Server):Linux 虚拟服务器,是由章文嵩博士(前阿里云产品技术负责人,花名正明)于1998年发起的一个自由软件项目。是国内最早出现的自由软件项目之一。LVS 是全球最流行的四层负载项目之一,从 Linux2.4 版内核开始,已经完全内置了 LVS 的各个功能模块。官方网站:<www.linuxvirtualserver.org>

通过LVS提供的负载均衡技术和Linux操作系统可以实现一个高性能,高可用的服务器群集,LVS具有良好的可靠性、可扩展性和可操作性。从而以低廉的成本实现最优的服务性能。

阿里云的四层负载均衡服务也是基于 LVS 进行的二次开发。

1.1 LVS工作原理

LVS 是基于 Linux 内核中 netilter 框架实现的负载均衡系统,所以要学习 LVS 之前必须要先简单了解 netfilter 基本工作原理。netilter 其 实很复杂也很重要,平时我们说的 Linux防火墙就是 netilter,不过我们平时操作的都是iptables,iptables 只是用户空间编写和传递规则 的工具而已,真正工作的是 netfilter。通过下图可以简单了解下 netfilter的工作机制:

netfilter 在内核中设置了五个勾子函数,管理员在用户空间,通过程序设置过滤规则,内核中的勾子函数根据预设的规则进行工作,达到对流经的数据包进行过滤,拒绝,转发等功能。

iptables中有五个内置链(chain)对应内核中的五个勾子函数。

(1)当一个数据包进入网卡时,数据包首先进入PREROUTING链,内核根据数据包目的IP判断是否需要传送出去;

(2)如果数据包是进入本机的,则会进入INPUT链,然后交由本机的应用程序处理;

(3)如果数据包是要转发的,且内核允许转发,则数据包在PREROUTING链之后到达FORWARD链,再经由POSTROUTING链输出;

(4)本机的应用程序往外发送数据包,会先进入OUTPUT链,然后到达POSTROUTING链输出。

数据流入:PREROUTING --> INPUT

数据流出:OUTPUT --> POSTROUTING

数据转发:PREROUTING --> FORWARD --> POSTROUTING

LVS 是基于 netiter 框架,主要工作于 INPUT 链上,在 INPUT 上注册 ip_vs_in HOOK 函数,进行 IPVS 主流程,大概原理如图所示:

(1)当用户访问<www.sina.com.cn> 时,用户数据通过层层网络,最后通过交换机进入LVS 服务器网卡,并到达内核。 (2)进入PREROUTING 后经过路由查找,确定访问的目的VIP 是本机 IP 地址,所以数据包进入到INPUT 链上。 (3)IPVS 是工作在 INPUT 链上,会根据访问的vip+port 判断请求是否是IPVS 服务,如果是则调用注册的 IPVS HOOK 函数,进行IPVS相关主流程,强行修改数据包的相关数据,并将数据包发往POSTROUTING 链上。 (4)POSTROUTING上收到数据包后,根据目标IP地址(后端服务器),通过路由选路,将数据包最终发往后端的服务器上。

相关术语:

  • VS:Virtual Server(虚拟服务器),Director Server(DS,调度器),Load Balancer(LB,负载均衡服务器),负责流量转发服务;

  • RS:Real Server后端提供业务的服务器;

  • CIP:Client IP,客户端IP;

  • VIP:Virtual Server IP,虚似IP,负载均衡服务器的外网 IP,一般将域名解析到该IP;

  • DIP:Director IP,负载均衡服务器的内网 IP,该IP负责与后端业务服务器进行通讯;

  • RIP:Real Server IP,后端业务服务器的 IP。

1.2 LVS工作模式

LVS 官方支持三种工作模式, 分别是 NAT 模式,DR 模式,TUN 模式,不同的模式有各自不同的特点,使用者可以根据业务场景选择不同的的工作模式来实现其负载均衡集群。

在 2.6.32 的内核版中,阿里开发过 FULL NAT 模式,但在目前主流 LINUX 发行版中,内核版本都较高,该模式并没有被内置。

1.2.1 NAT模式

官网说明:Virtual Server via NAT

NAT:Network address translation (网络地址转换)。

NAT 模式本质上就是多目标的DNAT, LVS 将请求报文中的目标地址和目标端口修改为后端的 RS 服务器的 RIP 和 PORT 进行转发。

NAT 模式特点:

  • RIP和DIP 应在同一个IP网络,且应使用私网地址;

  • RS 的网关要指向 DIP;

  • 请求报文和响应报文都必须经由 LVS 转发,LVS 易成为系统瓶颈;

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

  • VS 必须是 Linux 系统,RS 可以是任意 OS 系统;

  • LVS 主机需要开启 ip_forward 转发。

1.2.2 DR模式

DR:Direct Routing(直接路由)。

DR 模式是 LVS 的默认模式,应用广泛,通过为请求报文重新封装一个 MAC 首部进行转发,源 MAC 是DIP 所在的接口的 MAC,目标MAC 是挑选出的 RS 的 RIP 所在接口的 MAC 地址;源 IP/PORT,以及目标 IP/PORT 均保持不变,但源 MAC 和目标 MAC 会发生改变,DR 模式下,数据链路层之上的内容不会发生变化 。

官网说明:Virtual Server via Direct Routing

DR 模式特点:

  • LVS 服务器 和 RS 服务器 上都配置有 VIP 地址;

  • 确保前端路由器将目标 IP 为 VIP 的请求报文只发往 LVS 服务器;

  • 后端 RS 服务器上的 VIP 只用作封装响应报文,不可响应 ARP 广播,也不可主动对外发送 ARP 广播;

  • RS 的 RIP 可以使用私网地址,也可以是公网地址;RIP 与 DIP在同一 IP 网络;

  • RIP 的网关不能指向 DIP,以确保响应报文不会经由 LVS 服务器;

  • RS 服务器和 LVS 服务器要在同一个物理网络(不能跨路由,因为路由会隔离 ARP 广播);

  • LVS 服务器只处理请求报文,不处理响应报文,相对于 NAT 模式其负载性能会大幅提升,响应由RS 服务器自行完成;

  • 不支持端口映射(端口不能修改,数据链路层之上的内容不会发生变化);

  • 无需开启 ip_forward;

  • RS 服务器可以使用大多数 OS 系统(支持相关网络设置即可)

如何确保前端路由器将目标 IP 为 VIP 的请求报文只发往 LVS 服务器?

  • 方法1:在前端网关的 ARP 表中做静态绑定,将 VIP 和 LVS 服务器上的 VIP 所在的网卡的 MAC 地址写死;

  • 方法2:在 RS 服务器上用 arptables 工具设置 arp 防火墙,确保 RS 服务器上的 VIP 不对外发送ARP 广播,也不会响应 ARP 广播;

    复制代码
    arptables -F
    arptables -A INPUT -d $VIP -j DROP  #丢弃ARP广播数据包
    arptables -A OUT -s $VIP -j mangle --mangle-ip-s $RIP  #丢弃对外ARP广播的数据包
    #注:vip为客户端访问服务器的虚拟ip;RIP为真实服务器的真实ip
    arptables-save > /etc/sysconfig/arptables 
    systemctl enable --now arptables
  • 方法3:在 RS 服务器上修改内核参数关闭 ARP 广播和 ARP 应答。

复制代码
#将RS上的VIP配置为lo接口的别名,限制Linux仅对对应接口的ARP请求做响应
#忽略ARP广播,不应答
[root@server1 ~]# echo "1" > /proc/sys/net/ipv4/conf/lo/arp_ignore
#不主动发送ARP广播
[root@server1 ~]# echo "2" > /proc/sys/net/ipv4/conf/lo/arp_announce
#all表示所有网卡配置,除了对lo配置外还需要在此配置
[root@server1 ~]# echo "1" > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@server1 ~]# echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce
​
说明:
arp_ignore:定义对目标地址为本地IP的ARP询问不同的应答模式,限制响应。
    0 -(默认值):响应任意网卡上接收到的对本机IP地址的arp请求(包括回环网卡上的地址)。而不管该目的IP是否在接收网卡上。
    1 – 只响应目的IP地址为接收网卡上的本地地址的arp请求。
    2 – 只响应目标IP地址为接收网卡上的本地地址的ARP请求,且arp请求的源IP必须和接收网卡同网段。
    3 – 如果arp请求数据包所请求的IP地址对应的本地地址其作用域为主机,则不回应arp数据包,如果作用域为全局或链路,则回应arp响应数据包。
    4-7 –保留未使用。
    8 – 不回应所有(本地地址)的arp查询。
#注:sysctl.conf中包含all和eth/lo(具体网卡)的arp_ignore参数,取其中较大的值生效。
​
arp_announce:控制系统在对外发送arp请求时,如何选择arp请求数据包的源IP地址。
    0 -(默认)允许使用任意网卡上的ip地址作为arp请求的源ip,通常就是使用数据包的源ip
    1 – 尽量避免使用不属于该发送网卡子网的本地地址作为发送arp请求的源ip地址
    2 – 忽略IP数据包的源ip地址,选择发送网卡上最合适的本地地址作为arp请求的源ip地址
#注:sysctl.conf中包含all和eth/lo(具体网卡)的arp_announce参数,取其中较大的值生效。

1.2.3 TUN模式

TUN:IP tunneling(IP隧道)。

TUN 模式不修改请求报文的IP首部(源 IP 为 CIP,目标 IP 为 VIP),而是在原 IP 报文之外再封装一个IP首部(源 IP 为 DIP,目标 IP 为 RIP),再将报文发往后端 RS,RS 直接响应客户端(源 IP 是 VIP,目标 IP 是 CIP),TUN 模式与 DR 模式的区别是 TUN 模式下 LVS 服务器和后端 RS 可以不在同一个物理网络,可以跨公网。

官网说明:http://www.linuxvirtualserver.org/VS-IPTunneling.html

TUN模式特点:

  • RIP 和 DIP 可以不处于同一物理网络中,RS 的网关一般不能指向 DIP,且 RIP 可以和公网通信;

  • 集群节点可以跨互联网实现,DIP,VIP,RIP 都可以是公网地址;

  • RS 服务器上的 tun 接口需要配置 VIP 地址,以便接收 LVS 服务器转发的数据包,以及作为响应报文的源 IP;

  • LVS 服务器转发给 RS 服务器时需要使用隧道,隧道外层的数据报文中的源 IP 是 DIP,目标 IP 是RIP;

  • RS 服务器响应给客户端的报文中源 IP 是 VIP,目标 IP 是 CIP;

  • LVS 服务器只处理请求报文,不处理响应报文,相对于 NAT 模式其负载性能会大幅提升,响应由RS 服务器自行完成;

  • 不支持端口映射;

  • 无需开启 ip_forward;

  • RS 服务器的操作系统必须支持隧道功能。

1.2.4 FULL NAT模式

FULL NAT:Full Network address translation (完全网络地址转换)。

FULL NAT 模式不是 LVS 官方内置的工作模式,是由阿里巴巴公司开发的第三方模式,仅在 2.6.32 版本的内核中存在过,目前主流的 LINUX 发行版并不支持该模式,相对于 NAT 模式而言,FULL NAT 在转发时,将请求报文中的源 IP 地址源端口和目标 IP 地址目标端口都进行了替换,然后再向后端转发。

FULL NAT 模式主要用于公有云环境中,在阿里云上,不建议将虚拟机设为流量穿透服务,虚拟机网关必须使用其自带的网关,在此情况下,无法修改后端 RS 服务器的网关,则无法使用 NAT 模式,所以需要使用 FULL NAT 模式来解决此类问题。

FULL NAT 模式特点:

  • RIP 和 DIP 不要求在同一网络,但要能通信;

  • RS 网关不必指向 DIP;

  • 请求报文和响应报文都必须经由 LVS 转发,LVS 易成为系统瓶颈;

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

  • VS 必须是 Linux 系统,RS 可以是任意 OS 系统;

  • LVS 主机需要开启 ip_forward 转发。

1.2.5 LVS工作模式总结和比较

RS说明 NAT TUN DR
RS 服务器OS系统 无任何额外要求 要求支持隧道功能 要求禁用ARP广播和 ARP应答
RS 服务器网络 私有网络 私有网络/公有网络 私有网络
RS 服务器数量 较少,一般不超过20台 可以超过100台 可以超过100台
RS 服务器网关 指向LVS 服务器,原路返回 指向自己的路由器,不需要原路返回 指向自己的路由器,不需要原路返回
优点 支持端口转换 支持公网 性能最好
缺点 性能存在瓶颈 要求支持隧道,不支持端口转换 不支持跨网段和端口转换

NAT 与 FULL NAT:请求报文和响应报文都经由 LVS,NAT 模式下的 RIP 网关要指向 DIP,FULL NAT 模式下无此要求;

DR 与 TUN:请求报文经由 LVS,响应报文由 RS 自行转发;DR 模式通过修改 MAC 首部实现,通过 MAC 网络转发; TUN 模式通过在原 IP 报文之外封装新的 IP 首部实现转发,支持跨公网通信。

1.3 LVS调度算法

调度算法是指 LVS 服务器将前端请求转发给后端 RS 服务器的转发策略。

调度算法分为静态算法和动态算法两类,在这些调度算法中,实际使用较多的是

RR,WRR,WLC 等有限的几种。官网说明:Job Scheduling Algorithms in LVS

1.3.1 四种静态调度算法

静态算法仅根据算法本身来进行调度,不关注后端 RS 服务器负载情况。

  1. RR:Round Robin,轮询算法,LVS 服务器将前端请求轮流转发到后端每一台 RS 服务器上,后端每台 RS 服务器处理的请求量都是相同的;

  2. WRR:Weight RR,加权轮询算法,LVS 服务器将前端请求根据后端 RS 服务器的权重进行转发,对于后端 RS 服务器中性能好的机器可以设置较高的权重,物尽其用;

  3. SH:Source Hash,源 IP 地址 hash,将来自于同一个 IP 地址的客户端请求调度到后端同一台 RS服务器上,从而实现会话保持;

  4. DH:Destinatio Hash,目标 IP 地址 hash, 客户端的请求第一次被调度到某台 RS 服务器后,其后续的请求都将会被发往同一台 RS 服务器,一般用于正向代理缓存场景。

1.3.2 六种动态调度算法

动态算法要根据当前系统中后端 RS 服务器的负载情况进行调度,给负载较低的后端主机多转发,给负载较高的后端主机少转发。

活动连接:Activeconns ,在 LVS 中,有数据传输的连接被称为活动连接。

非活动连接:InActiveconns,在 LVS 中,没有数据传输的连接被称为非活动连接。

  1. LC:Least Connections,最少连接算法,将前端请求调度到已建立的连接数最少的后端 RS 服务器上,如果集群后端服务器具有相同的配置和相近的系统性能,采用此调度算法可以较好的均衡负载(Overhead = Activeconns * 256 + InActiveconns,负载值越小,则被调度的优先级越高,256个非活动连接相当于1个活动连接);

  2. WLC:Weighted Least Connections,加权最少连接算法,此算法是 LVS 的默认调度算法,在 LC算法中,只考虑了 RS 服务器的连接数,而没有考虑 RS 服务器会有不同的配置和性能,此算法优化了负载均衡性能,具有较高权重值的 RS 服务器将承受较大比例的活动连接负载,(Overhead = (ActiveConns * 256 + InActiveConns)/ Weight,权重值越大,则计算出的负载值越小,相应的,被调度的优先级越高,256个非活动连接相当于1个活动连接);

  3. SED:Shortest Expected Delay,最短延迟调度算法,此算法是 WLC 算法的改进版,不再考虑非活动连接(Overhead =(Activeconns + 1)* 256 / Weight,权重值越大,则计算出的负载值越小,相应的,被调度的优先级越高,不考虑非活动连接的原因是为了防止 WLC 算法中InActiveconns 数过大影响调度的准确性,+1 是为了保证被除数大于0,防止出现计算结果为0的情况,计算结果为0则意味着每台 RS 被调度的概率是一致的,权重值设置无效;

  4. NQ:Never Queue,最少队列调度算法/永不排队调度算法,初始的时候先做一次轮循,保证每台RS 都至少被调度一次,后续使用 SED 调度算法;

  5. LBLC:Locality-Based Least Connections,基于局部性的最少链接调度算法,本质是动态的 DH算法,该算法优先使用 DH 算法将请求调度到同一台 RS 服务器上,如果该 RS 服务器负载较高或不可用,则再使用 LC 算法决定调度到哪一台 RS 服务器上,此 RS 服务器将成为一下次调度时 DH算法的首选项;

  6. LBLCR:Locality-Based Least Connections with Replication,带复制的基于局部性的最少链接调度算法,在 LBLC 算法中,如果 DH 算法选出的 RS 服务器不能被调度,则要使用 LC 算法重新选择。

1.3.3 高版本内核中新增的调度算法

在 4.15 版本的内核中,新增了 FO 和 OVF 两种调度算法,后续又增加了 MH调度算法:

  1. FO:Weighted Fail Over,加权故障转移调度,在此算法中,LVS 会遍历关联的后端 RS 服务器列表,找到未过载(未设置 IP_VS_DEST_F_OVERLOAD 标志)且权重最高的RS服务器进行调度,属于静态算法;可以用于灰度发布。

  2. OVF:Overflow-connection,溢出连接算法,该算法基于真实服务器的活动连接数量和权重值实现,将新的请求调度到权重最高的 RS 服务器,直到其活动连接数超过权重值,后续请求将调度到下一个权重最高的 RS 服务器上,属于动态算法;

  3. MH:Masquerading Hashing,源 IP 地址 hash,将来自于同一个 IP 地址的请求调度到后端同一台 RS 服务器上,hash 计算方式与 SH 算法不同;

复制代码
[root@lvs ~]# grep -A 15 "IPVS scheduler" /boot/config-5.14.0-362.8.1.el9_3.x86_64
# IPVS scheduler
#
CONFIG_IP_VS_RR=m
CONFIG_IP_VS_WRR=m
CONFIG_IP_VS_LC=m
CONFIG_IP_VS_WLC=m
CONFIG_IP_VS_FO=m
CONFIG_IP_VS_OVF=m
CONFIG_IP_VS_LBLC=m
CONFIG_IP_VS_LBLCR=m
CONFIG_IP_VS_DH=m
CONFIG_IP_VS_SH=m
CONFIG_IP_VS_MH=m
CONFIG_IP_VS_SED=m
CONFIG_IP_VS_NQ=m

1.4 lvs部署命令

1.4.1 软件说明

复制代码
[root@lvs ~]# yum install ipvsadm -y
/usr/sbin/ipvsadm  #主程序
/usr/sbin/ipvsadm-restore  #规则重载工具
/usr/sbin/ipvsadm-save  #规则保存工具

ipvsadm 是转发规则配置工具,主要用来配置接收前端请求的规则(集群),以及为该集群设置往后端RS 服务器的转发规则,包括调度算法,后端 RS 服务器IP地址,端口,权重等。

1.4.2 ipvsadm工具

ipvsadm命令用法

(1)管理虚拟服务

复制代码
#常用选项
-A|-E|-D  #添加/编辑/删除虚拟服务
-t | -u   #TCP/UDP协议的虚拟服务
-s #配置负载均衡算法,如:rr, wrr, lc,wlc等
-p #配置持久化时间
-C  #清除所有的虚拟服务规则
-R  #重载虚拟服务规则
复制代码
#添加一个虚拟服务器,使用轮询算法
ipvsadm -A -t 192.168.168.200:80 -s rr
#修改虚拟服务的算法为加权轮询
ipvsadm  -E -t 192.168.168.200:80 -s wrr
#删除虚拟服务
ipvsadm -D -t 192.168.168.200:80

(2)管理真实服务

复制代码
#常用选项
-a|-e|-d    #在一个虚拟服务中添加/编辑/删除一个新的真实服务器
-t|-u        #虚拟服务监听集群写法,一般是VIP
-r           #指定rs服务器
-g | -m | -i  #LVS模式为:DR | NAT | TUN
-w           #配置真实服务器的权重
复制代码
#添加一个真实服务器172.24.24.60,使用nat工作模式,使用rr算法
ipvsadm -a -t 192.168.168.200:80 -r 172.24.24.60 -m
#添加一个真实服务器172.24.24.60,使用DR工作模式,权重2  
ipvsadm -a -t 192.168.168.200:80 -r 172.24.24.60 -g -w 2
#修改真实服务器的权重
ipvsadm -e -t 192.168.168.200:80 -r 172.24.24.60 -g -w 5
#删除真实服务器
ipvsadm -d -t 192.168.168.200:80 -r 172.24.24.60

(3)查看统计

复制代码
#查看当前配置的虚拟服务和各个RS的权重(当前运行的规则在文件/proc/net/ip_vs中)
ipvsadm -ln
#查看当前ipvs模块中记录的连接(可用于观察转发情况,在文件/proc/net/ip_vs_conn中),超时后会消失 
ipvsadm -lnc
#查看当前超时时长值,单位为秒
ipvsadm -l --timeout
#清空计数器
ipvsadm -Z -t 192.168.168.200:80

--stats选项和--rate选项

复制代码
[root@director ~]# ipvsadm -ln --stats
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port               Conns   InPkts  OutPkts  InBytes OutBytes
#说明:
1. Conns (connections scheduled) 已经转发过的连接数
2. InPkts (incoming packets) 入包个数
3. OutPkts (outgoing packets) 出包个数
4. InBytes (incoming bytes) 入流量(字节)
5. OutBytes (outgoing bytes) 出流量(字节)
复制代码
[root@director ~]# ipvsadm -ln  --rate
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port                 CPS    InPPS   OutPPS    InBPS   OutBPS
#说明:
1. CPS (current connection rate) 每秒连接数
2. InPPS (current in packet rate) 每秒的入包个数
3. OutPPS (current out packet rate) 每秒的出包个数
4. InBPS (current in byte rate) 每秒入流量(字节)
5. OutBPS (current out byte rate) 每秒出流量(字节)

(4)保存ipvsadm的配置并恢复

复制代码
#将配置保存至文件(ipvsadm --save等同于ipvsadm-save等同于ipvsadm -S)
[root@lvs ~]# ipvsadm -Sn > lvs_nat.conf 
#恢复规则
[root@director ~]# ipvsadm -R < lvs_nat.conf

lvs不会检测后端RS服务器状态。

权重为0的RS服务器不会被调度,一般用作平滑升级。

2、lvs负载均衡实现

2.1 NAT模式集群构建

(1)real server配置

修改网关为lvs地址并配置web服务

复制代码
#rs1配置
[root@rs1 ~]# nmcli connection modify ens160 ipv4.addresses 172.24.24.60/24 ipv4.gateway 172.24.24.253
[root@rs1 ~]# nmcli connection up ens160
[root@rs1 ~]# ip a show ens160
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:a8:00:45 brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    inet 172.24.24.60/24 brd 172.24.24.255 scope global noprefixroute ens160
       valid_lft forever preferred_lft forever
    inet6 fe80::8234:d487:e28:4a8e/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
[root@rs1 ~]# yum install nginx -y
[root@rs1 ~]# echo rs1 172.24.24.60 > /usr/share/nginx/html/index.html
[root@rs1 ~]# systemctl restart nginx
[root@rs1 ~]# curl  172.24.24.60
rs1 172.24.24.60
#rs2配置
[root@rs2 ~]# nmcli connection modify ens160 ipv4.addresses 172.24.24.61/24 ipv4.gateway 172.24.24.253
[root@rs2 ~]# nmcli connection up ens160
[root@rs2 ~]# ip a show ens160
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:53:dc:d3 brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    inet 172.24.24.61/24 brd 172.24.24.255 scope global noprefixroute ens160
       valid_lft forever preferred_lft forever
    inet6 fe80::b7e4:df9b:c70f:c9e/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
[root@rs2 ~]# yum install nginx -y
[root@rs2 ~]# echo rs2 172.24.24.61 > /usr/share/nginx/html/index.html
[root@rs2 ~]# systemctl restart nginx
[root@rs2 ~]# curl 172.24.24.61
rs2 172.24.24.61

(2)lvs配置

nat模式需要开启路由转发

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

ip配置

复制代码
#查看网卡名和连接名
[root@lvs ~]# nmcli device
DEVICE  TYPE      STATE         CONNECTION
ens160  ethernet  已连接        ens160
ens224  ethernet  已连接        ens224
​
[root@lvs ~]# nmcli connection modify ens160 ipv4.addresses 192.168.168.200/24 ipv4.gateway  192.168.168.2 ipv4.dns 114.114.114.114 ipv4.method  manual autoconnect  yes
#如果有ens224连接就修改ip配置,没有就添加
[root@lvs ~]# nmcli connection add  type ethernet  con-name ens224 ifname  ens224 ipv4.address 172.24.24.253/24 ipv4.method  manual  autoconnect  yes
[root@lvs ~]# nmcli connection up ens160
[root@lvs ~]# nmcli connection up ens224
#查看网卡配置的ip信息
[root@lvs ~]# ip a show ens160
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:6f:b3:3f brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    inet 192.168.168.200/24 brd 192.168.168.255 scope global noprefixroute ens160
       valid_lft forever preferred_lft forever
    inet6 fe80::6beb:d2f9:4b57:f1ad/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
[root@lvs ~]# ip a show ens224
3: ens224: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:6f:b3:49 brd ff:ff:ff:ff:ff:ff
    altname enp19s0
    inet 172.24.24.253/24 brd 172.24.24.255 scope global noprefixroute ens224
       valid_lft forever preferred_lft forever
    inet6 fe80::6e4d:36e8:29a5:bb78/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

负载配置

复制代码
[root@lvs ~]# yum install ipvsadm -y
[root@lvs ~]# ipvsadm -A -t 192.168.168.200:80 -s rr
[root@lvs ~]# ipvsadm -a -t 192.168.168.200:80 -r 172.24.24.60:80 -m
[root@lvs ~]# ipvsadm -a -t 192.168.168.200:80 -r 172.24.24.61: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  192.168.168.200:80 rr
  -> 172.24.24.60:80              Masq    1      0          0
  -> 172.24.24.61:80              Masq    1      0          0
#Masq表示lvs为NAT模式
#lvs并不会监听80端口
[root@lvs ~]# ss -lntup | grep 80

测试

复制代码
[root@client ~]# for i in {1..10};do curl 192.168.168.200;done
rs1 172.24.24.60
rs2 172.24.24.61
rs1 172.24.24.60
rs2 172.24.24.61
rs1 172.24.24.60
rs2 172.24.24.61
rs1 172.24.24.60
rs2 172.24.24.61
rs1 172.24.24.60
rs2 172.24.24.61

修改lvs调度算法并测试

复制代码
[root@lvs ~]# ipvsadm -E -t 192.168.168.200:80 -s wrr
[root@lvs ~]# ipvsadm -e -t 192.168.168.200:80 -r 172.24.24.60:80 -m -w 2
[root@lvs ~]# ipvsadm -e -t 192.168.168.200:80 -r 172.24.24.61:80 -m -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.168.200:80 wrr
  -> 172.24.24.60:80              Masq    2      0          0
  -> 172.24.24.61:80              Masq    1      0          0
  
#客户端测试
[root@client ~]# for i in {1..10};do curl 192.168.168.200;done
rs2 172.24.24.61
rs1 172.24.24.60
rs1 172.24.24.60
rs2 172.24.24.61
rs1 172.24.24.60
rs1 172.24.24.60
rs2 172.24.24.61
rs1 172.24.24.60
rs1 172.24.24.60
rs2 172.24.24.61

可以看到web服务主机上的日志中查看到的是真正的客户端ip地址

复制代码
[root@rs1 ~]# cat /var/log/nginx/access.log
192.168.168.198 - - [21/Sep/2025:22:43:17 +0800] "GET / HTTP/1.1" 200 17 "-" "curl/7.29.0" "-"
192.168.168.198 - - [21/Sep/2025:22:43:17 +0800] "GET / HTTP/1.1" 200 17 "-" "curl/7.29.0" "-"

2.2 DR模式

(1)配置router

复制代码
[root@router ~]# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
[root@router ~]# sysctl -p
net.ipv4.ip_forward = 1
[root@router ~]# ip a show ens160
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:27:ba:3a brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    inet 192.168.168.3/24 brd 192.168.168.255 scope global noprefixroute ens160
       valid_lft forever preferred_lft forever
    inet 172.24.0.1/24 brd 172.24.0.255 scope global noprefixroute ens160
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe27:ba3a/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
[root@router ~]# ip a a 172.24.0.1/24 dev ens224
[root@router ~]# ip a show ens224
3: ens224: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:98:25:24 brd ff:ff:ff:ff:ff:ff
    altname enp19s0
    inet 192.168.168.3/24 brd 192.168.168.255 scope global noprefixroute ens224
       valid_lft forever preferred_lft forever
    inet 172.24.0.1/24 scope global ens224
       valid_lft forever preferred_lft forever
    inet6 fe80::33cc:f220:fde5:542d/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

(2)修改lo回环地址为VIP并抑制ARP广播,配置web服务

复制代码
#rs1配置
[root@rs1 ~]# ip a a 172.24.0.100/32  dev lo label lo:1
[root@rs1 ~]# ip a show lo
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.24.0.100/32 scope global lo:1
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
​
#忽略ARP广播,不应答
[root@rs1 ~]# echo "1" > /proc/sys/net/ipv4/conf/lo/arp_ignore
#不主动发送ARP广播
[root@rs1 ~]# echo "2" > /proc/sys/net/ipv4/conf/lo/arp_announce
[root@rs1 ~]# echo "1" > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@rs1 ~]# echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce
#配置ip
[root@rs1 ~]# nmcli connection modify ens160 ipv4.addresses  192.168.168.60/24 ipv4.gateway 192.168.168.3
[root@rs1 ~]# nmcli connection up ens160
#配置web服务
[root@rs1 ~]# yum install nginx -y
[root@rs1 ~]# echo rs1 192.168.168.60  > /usr/share/nginx/html/index.html
[root@rs1 ~]# systemctl restart nginx
[root@rs1 ~]# curl  192.168.168.60
rs1 192.168.168.60
复制代码
#rs2配置
[root@rs2 ~]# ip a a 172.24.0.100/32  dev lo label lo:1
[root@rs2 ~]# ip a show lo
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.24.0.100/32 scope global lo:1
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
​
​
#忽略arp广播,并不主动发送ARP广播
echo "1" > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" > /proc/sys/net/ipv4/conf/lo/arp_announce
echo "1" > /proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce
​
#配置ip
[root@rs2 ~]# nmcli connection modify ens160 ipv4.addresses  192.168.168.61/24 ipv4.gateway 192.168.168.3
[root@rs2 ~]# nmcli connection up ens160
#配置web服务
[root@rs2 ~]# yum install nginx -y
[root@rs2 ~]# echo rs2 192.168.168.61 > /usr/share/nginx/html/index.html
[root@rs2 ~]# systemctl restart nginx
[root@rs2 ~]# curl 192.168.168.61
rs2 192.168.168.61

(2)lvs配置

复制代码
[root@lvs ~]# ip a a 172.24.0.100/32  dev lo label lo:1
[root@lvs ~]# ip a show lo
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.24.0.100/32 scope global lo:1
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
[root@lvs ~]# nmcli connection modify ens160 ipv4.address 192.168.168.100/24 ipv4.gateway 192.168.168.3
[root@lvs ~]# nmcli connection up ens160
[root@lvs ~]# ip a show ens160
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:6f:b3:3f brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    inet 192.168.168.100/24 brd 192.168.168.255 scope global noprefixroute ens160
       valid_lft forever preferred_lft forever
    inet6 fe80::bbce:7fbf:e56c:3495/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
复制代码
#清空旧的配置
[root@lvs ~]# ipvsadm -C
[root@lvs ~]# ipvsadm -A -t 172.24.0.100:80 -s rr
[root@lvs ~]# ipvsadm -a -t  172.24.0.100:80 -r 192.168.168.60:80 -g
[root@lvs ~]# ipvsadm -a -t  172.24.0.100:80 -r 192.168.168.61:80 -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  172.24.24.100:80 rr
  -> 192.168.168.60:80            Route   1      0          0
  -> 192.168.168.61:80            Route   1      0          0
#Route表示使用的DR模式

测试

复制代码
[root@client ~]# nmcli connection modify ens32 ipv4.addresses 172.24.24.198/24 ipv4.gateway 172.24.24.3
[root@client ~]# nmcli connection up ens32
​
[root@client ~]# for i in {1..10};do curl 172.24.0.100;done
rs2 192.168.168.61
rs1 192.168.168.60
rs2 192.168.168.61
rs1 192.168.168.60
rs2 192.168.168.61
rs1 192.168.168.60
rs2 192.168.168.61
rs1 192.168.168.60
rs2 192.168.168.61
rs1 192.168.168.60

2.3 lvs持久连接

1、持久客户端连接 在短期内,将来自于同一个客户端的所有请求通通定向至此前选定的 RS;也就是只要 IP 相同,分配的服务器始终相同 。

复制代码
ipvsadm -A -t 172.16.0.8:0 -s wlc -p 120
# 添加一个 tcp 负载集群,集群地址为 172.16.0.8 ,0表示的是端口号,算法为 wlc,持久化时间为 120s

2、持久端口连接 将来自于同一个客户端对同一个服务(端口)的请求,始终定向至此前选定的RS。

复制代码
ipvsadm -A -t 172.16.0.8:80 -s rr -p 120
# 添加一个 tcp 负载集群,集群地址为 172.16.0.8:80 ,算法为 rr,持久化时间为 120s

3、持久防火墙标记连接 将来自于同一客户端对指定服务(端口)的请求,始终定向至此选定的 RS;不过它可以将两个毫不相干的端口定义为一个集群服务。

复制代码
iptables -t mangle -A PREROUTING -d 172.16.0.8 -p tcp --dport 80 -j MARK --set-mark 10 # 添加一个防火墙规则,当目标地址为 172.16.0.8 并且目标端口为 80 时给数据包打一个标记,设置mark 值为 10
iptables -t mangle -A PREROUTING -d 172.16.0.8 -p tcp --dport 443 -j MARK --set-mark 10
# 添加一个防火墙规则,当目标地址为 172.16.0.8 并且目标端口为 443 时给数据包打一个标记,设置mark 值为 10
service iptables save # 保存防火墙规则持久化生效
ipvsadm -A -f 10 -s wlc -p 120 # 添加一个负载调度器,当 mark 值为 10 时进行负载均衡使用wlc 算法,持久化生效时间为 120s
ipvsadm -a  -f 10 -r rs的地址 -m
相关推荐
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_115 天前
LVS+KeepAlived+Nginx实现企业级业务高可靠部署的实战教程
运维·nginx·lvs
tx112087635820 天前
LVS知识归纳与模式解析及常见问题复现解析
linux·运维·服务器·lvs·ipvsadm·nat/dr模式
輝太くん20 天前
LVS重新梳理
lvs