LVS(linuxvirtualserver)

目录

[1 名词介绍](#1 名词介绍)

[1.1 集群和分布式](#1.1 集群和分布式)

[1.1.1 集群](#1.1.1 集群)

[1.1.2 分布式](#1.1.2 分布式)

[1.1.3 集群于分布式应用比较](#1.1.3 集群于分布式应用比较)

[1.2 LVS](#1.2 LVS)

[2 LVS集群的类型](#2 LVS集群的类型)

[2.1 NAT模式](#2.1 NAT模式)

[2.1.1 说明](#2.1.1 说明)

[2.1.2 数据逻辑](#2.1.2 数据逻辑)

[2.1.3 数据传输过程](#2.1.3 数据传输过程)

[2.2 DR模式](#2.2 DR模式)

[2.2.1 说明](#2.2.1 说明)

[2.2.2 数据逻辑](#2.2.2 数据逻辑)

[2.2.3 数据传输过程](#2.2.3 数据传输过程)

抓包理解

[2.2.4 DR模式的特点](#2.2.4 DR模式的特点)

[2.3 TUN模式](#2.3 TUN模式)

[2.3.1 说明](#2.3.1 说明)

[2.3.2 数据传输过程](#2.3.2 数据传输过程)

[2.3.3 特点](#2.3.3 特点)

[2.4 FULLNAT模式](#2.4 FULLNAT模式)

[2.5 工作模式比较](#2.5 工作模式比较)

[3 LVS调度算法](#3 LVS调度算法)

[3.1 LVS静态调度算法](#3.1 LVS静态调度算法)

[3.2 LVS动态调度算法](#3.2 LVS动态调度算法)

[3.3 版本4.15内核后新增调度算法](#3.3 版本4.15内核后新增调度算法)

[4 LVS部署命令介绍](#4 LVS部署命令介绍)

[4.1 相关软件信息](#4.1 相关软件信息)

[4.2 ipvsadm命令](#4.2 ipvsadm命令)

[5 LVS实践](#5 LVS实践)

[5.1 NAT模式实现](#5.1 NAT模式实现)

[5.1.1 实验环境](#5.1.1 实验环境)

[5.1.2 策略编写](#5.1.2 策略编写)

调度器

规则持久化

[5.1.3 测试](#5.1.3 测试)

[5.2 DR模式实现](#5.2 DR模式实现)

[5.2.1 实验环境](#5.2.1 实验环境)

路由器

调度器

Client

RS1

RS2

[5.2.2 测试编写](#5.2.2 测试编写)

路由器

调度器

[5.2.3 测试](#5.2.3 测试)

[5.3 利用火墙解决轮询错误问题](#5.3 利用火墙解决轮询错误问题)

[5.3.1 现象复现](#5.3.1 现象复现)

RS

VSNode

错误展示

解决方案

重测试

[5.4 利用持久连接实现会话粘滞](#5.4 利用持久连接实现会话粘滞)

调度策略


1 名词介绍

1.1 集群和分布式

系统性能扩展方式:

Scale UP:向上扩展,增强

Scale Out:向外扩展,增加设备,调度分配问题,Cluster

1.1.1 集群

Cluster: 集群是为了解决某个特定问题将多台计算机组合起来形成的单个系统。

Cluster常见的三种类型:

  • LB:LoadBalancing(负载均衡)由多个主机组成,每个主机只承担一部分访问。

  • HA:High Availiablity(高可用)SPOF(single Point Of failure)

    • MTBF:Mean Time Between Failure 平均无故障时间,正常时间。

    • MTTR:Mean Time To Restoration( repair)平均恢复前时间,故障时间。

    • A=MTBF/(MTBF+MTTR)(0,1):99%, 99.5%, 99.9%, 99.99%, 99.999%

    • SLA:Service level agreement(服务等级协议)是在一定开销下为保障服务的性能和可用性,服务提供商与用户间定义的一种双方认可的协定。

  • HPC:High-performance computing(高性能计算,国家战略资源)

1.1.2 分布式

分布式存储:Ceph,GlusterFs,FastDFS,MogileFs

分布式计算:hadoop,Spark

分布式常见应用:

  • 分布式应用-->服务按照功能拆分,使用微服务。

  • 分布式静态资源-->静态资源放在不同的存储集群上。

  • 分布式数据和存储-->使用key-value缓存系统。

  • 分布式计算-->对特殊业务使用分布式计算,比如Hadoop集群。

1.1.3 集群于分布式应用比较

  • 集群:**同一个业务系统,部署在多台服务器上。**集群中,每一台服务器实现的功能没有差别,数据和代码都是类似的。

  • 分布式:**一个业务被拆成多个子业务,或者本身就是不同的业务,部署在多台服务器上。**分布式

    中,每一台服务器实现的功能是有差别的,数据和代码也是不一样的,分布式每台服务器功能加起来,才是完整的业务。

  • 分布式是以缩短单个任务的执行时间 来提升效率,而集群则是通过提高单位时间内执行的任务数来提升效率。

  • 对于大型网站,访问用户很多,实现一个群集,在前面部署一个负载均衡服务器,后面几台服务器完成同一业务 。如果有用户进行相应业务访问时,负载均衡器根据后端哪台服务器的负载情况,决定由给哪一台去完成响应,并且台服务器垮了,其它的服务器可以顶上来。分布式的每一个节点,都完成不同的业务,如果一个节点垮了,那这个业务可能就会失败。

1.2 LVS

LVS 全称 Linux Virtual Server ,是 Linux 内核层实现的高性能、高可用的负载均衡集群技术 ,由章文嵩博士开发,它的核心作用将前端的请求流量分发到后端多台真实服务器(Real Server)上 ,从而提升服务的并发处理能力和可用性。

  • LVS简介

    • LVS:Linux Virtual Server,负载调度器,内核集成,章文嵩,阿里的四层SLB(Server LoadBalance)是基于LVS+keepalived实现。
  • LVS相关术语

    • VS: Virtual Server,负责调度。

    • RS:RealServer,负责真正提供服务。

  • LVS概念

    • VS:Virtual Server(调度器)

    • RS:Real Server (真实业务主机)

    • CIP:Client IP (客户端主机的ip)

    • VIP: Virtual serve IP VS外网的IP (对外开放的让客户访问的ip)

    • DIP: Director IP VS内网的IP (调度器负责访问内网的ip)

    • RIP: Real server IP (真实业务主机IP)

  • 工作原理

    • VS(调度器)根据请求报文目标IP目标协议端口将其调度转发至某RS(真实业务主机),根据调度算法来挑选RS。
  • LVS访问流程

    • CIP <--> VIP == DIP <--> RIP
  • LVS集群的类型

    • lvs-nat:修改请求报文的目标IP,多目标IP的DNAT。

    • lvs-dr:操纵封装新的MAC地址。

    • lvs-tun:在原请求IP报文之外新加一个IP首部。

    • lvs-fullnat:修改请求报文的源和目标IP。

2 LVS集群的类型

2.1 NAT模式

2.1.1 说明

  • 本质是多目标IP的DNAT,通过将请求报文中的目标地址目标端口 修改为某挑出的RS的RIPPORT实现转发。

  • RIP和DIP应在同一个IP网络,且应使用私网地址;RS的网关要指向DIP。

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

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

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

2.1.2 数据逻辑

1.客户端发送访问请求,请求数据包中含有请求来源(CIP)、访问目标地址(VIP)、访问目标端口(9000Port)。

2.VS服务器接收到访问请求做DNAT把请求数据包中的目的地由VIP换成RS的RIP和相应端口。

3.RS1相应请求,发送响应数据包,包中的相应保温为数据来源(RIP1)响应目标(CIP)相应端口(9000Port)。

4.VS服务器接收到响应数据包,改变包中的数据来源(RIP1-->VIP),响应目标端口(9000-->80)。

5.VS服务器把修改过报文的响应数据包回传给客户端。

LVS的NAT模式接收和返回客户端数据包时都要经过LVS的调度机,所以LVS的调度机容易阻塞。

2.1.3 数据传输过程

客户请求到达VIP后进入PREROUTING,在没有ipvs的时候因该进入本机INPUT,当IPVS存在后访问请求在通过PREROUTING后被IPVS结果并作NAT转发。

因为IPVS的作用点是在PREROUTING和INPUT链之间,所以如果在prerouting中设定规则会干扰IPVS的工作。所以在做LVS时要把iptables的火墙策略全清理掉。

2.2 DR模式

2.2.1 说明

🔭因为NAT模式数据流向(Client访问RealServer和其的回复)都要经过VirtualServer,当真实主机过多时(比如10台以上这样)调度器会有顶不住的问题;DR(直连回复方式)模式就可以解决这个问题,让RS不通过VS回复Client而是直接回复Client。
DR:Direct Routing,直接路由,LVS默认模式,应用最广泛,通过为请求报文重新封装一个MAC首部进行转发,源MAC是DIP所在的接口的MAC,目标MAC是某挑选出的RS的RIP所在接口的MAC地址;源IP/PORT,以及目标IP/PORT均保持不变。
NAT模式主要玩三层,DR模式主要玩二层。NAT在VS中变IP和POST,DR在VS中变MAC。

2.2.2 数据逻辑

在DR模式中,RS接收到访问请求后不需要回传给VS调度器,直接把回传数据发送给Client,所以RS和VS上都要有vip。

2.2.3 数据传输过程

  1. 客户端发送数据帧给vs调度主机帧中内容为客户端IP+客户端的MAC+VIP+VIP的MAC。

  2. VS调度主机接收到数据帧后把帧中的VIP的MAC该为RS1的MAC,此时帧中的数据为客户端IP+客户端的MAC+VIP+RS1的MAC。

  3. RS1得到2中的数据包做出响应回传数据包,数据包中的内容为VIP+RS1的MAC+客户端IP+客户端IP的MAC。

抓包理解:

抓包理解LVS中的DR模式-CSDN博客

2.2.4 DR模式的特点

  1. Director和各RS都配置有VIP.

  2. 确保前端路由器将目标IP为VIP的请求报文发往Director.

  3. 在前端网关做静态绑定VIP和Director的MAC地址.

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

  5. RIP的网关不能指向DIP,以确保响应报文不会经由Director.

  6. RS和Director要在同一个物理网络.

  7. 请求报文要经由Director,但响应报文不经由Director,而由RS直接发往Client.

  8. 不支持端口映射(端口不能修败).

  9. RS可使用大多数OS系统.

2.3 TUN模式

2.3.1 说明

转发方式:不修改请求报文的IP首部(源IP为CIP,目标IP为VIP),而在原IP报文之外再封装一个IP首部

(源IP是DIP,目标IP是RIP),将报文发往挑选出的目标RS;RS直接响应给客户端(源IP是VIP,目标IP

是CIP)

2.3.2 数据传输过程

  1. 客户端发送请求数据包,包内有源IP+vip+dport。

  2. 到达vs调度器后对客户端发送过来的数据包重新封装添加IP报文头,新添加的IP报文头中包含TUNSRCIP(DIP)+TUNDESTIP(RSIP1)并发送到RS1。

  3. RS收到VS调度器发送过来的数据包做出响应,生成的响应报文中包含SRCIP(VIP)+DSTIP(CIP)+port,响应数据包通过网络直接回传给client。

2.3.3 特点

  1. DIP, VIP, RIP都应该是公网地址。

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

  3. 请求报文要经由Director,但响应不能经由Director。

  4. 不支持端口映射。

  5. RS的OS须支持隧道功能。

2.4 FULLNAT模式

fullnat:通过同时修改请求报文的源IP地址和目标IP地址进行转发;CIP --> DIP;VIP --> RIP .

  1. VIP是公网地址,RIP和DIP是私网地址,且通常不在同一IP网络;因此,RIP的网关一般不会指向DIP。

  2. RS收到的请求报文源地址是DIP,因此,只需响应给DIP;但Director还要将其发往Client。

  3. 请求和响应报文都经由Director。

  4. 支持端口映射。

2.5 工作模式比较

要求 NAT模式 DR模式 TUN模式
RS操作系统 不限 禁用arp 支持隧道
调度器和服务器网络 可跨网络 不可跨网络 可跨网络
调度服务器数量服务器数量
RS服务器网关 指向到调度器DIP 指向到路由 指向到路由
  • NAT与FULLNAT:请求和响应报文都经由Director。

  • FULLNAT:RIP和DIP未必在同一IP网络,但要能通信。

  • NAT:RIP的网关要指向DIP。

  • DR与TUN:请求报文要经由Director,但响应报文由RS直接发往Client。

  • DR:通过封装新的MAC首部实现,通过MAC网络转发。

  • TUN:通过在原IP报文外封装新IP头实现转发,支持远距离通信。

3 LVS调度算法

根据其调度时是否考虑各RS当前的负载状态被分为两种:静态方法和动态方法

3.1 LVS静态调度算法

静态方法:仅根据算法本身进行调度,不考虑RS的负载情况。

  • RR:roundrobin 轮询 RS分别被调度,当RS配置有差别时不推荐。

  • WRR:Weighted RR,加权轮询根据RS的配置进行加权调度,性能差的RS被调度的次数少。

  • SH:Source Hashing,实现session sticky,源IP地址hash;将来自于同一个IP地址的请求始终发往第一次挑中的RS,从而实现会话绑定。

  • DH:Destination Hashing;目标地址哈希,第一次轮询调度至RS,后续将发往同一个目标地址的请求始终转发至第一次挑中的RS,典型使用场景是正向代理缓存场景中的负载均衡,如:宽带运营商。

3.2 LVS动态调度算法

动态方法:主要根据每RS当前的负载状态及调度算法进行调度Overhead=value较小的RS将被调度。

  • LC(least connections最少链接发):适用于长连接应用Overhead(负载值)=activeconns(活动链接数) x 256+inactiveconns(非活动链接数)。

  • WLC(Weighted LC权重最少链接):默认调度方法Overhead=(activeconns x 256+inactiveconns)/weight。

  • SED(Shortest Expection Delay):初始连接高权重优先Overhead=(activeconns+1+inactiveconns) x 256/weight但是,当node1的权重为1,node2的权重为10,经过运算前几次的调度都会被node2承接。

  • NQ(Never Queue):第一轮均匀分配,后续SED。

  • LBLC(Locality-Based LC):动态的DH算法,使用场景:根据负载状态实现正向代理。

  • LBLCR(LBLC with Replication):带复制功能的LBLC,解决LBLC负载不均衡问题,从负载重的复制到负载轻的RS。

3.3 版本4.15内核后新增调度算法

  • FO(Weighted Fai Over):常用作灰度发布;在此FO算法中,遍历虚拟服务所关联的真实服务器链表,找到还未过载(未设置IP_VS_DEST_FOVERLOAD标志)的且权重最高的真实服务器,进行调度;当服务器承接大量链接,我们可以对此服务器进行过载标记(IP_VS_DEST_F OVERLOAD),那么vs调度器就不会把链接调度到有过载标记的主机中。

  • OVF(Overflow-connection):基于真实服务器的活动连接数量和权重值实现。将新连接调度到权重值最高的真实服务器,直到其活动连接数量超过权重值,之后调度到下一个权重值最高的真实服务器,在此OVF算法中,遍历虚拟服务相关联的真实服务器链表,找到权重值最高的可用真实服务器。一个可用的真实服务器需要同时满足以下条件:

    • 未过载(未设置IP_VS_DEST_F OVERLOAD标志)。

    • 真实服务器当前的活动连接数量小于其权重值。

    • 其权重值不为零。

4 LVS部署命令介绍

4.1 相关软件信息

程序包:ipvsadm

Unit File:ipvsadm.service

主程序:/usr/sbin/ipvsadm

规则保存工具:/usr/sbin/ipvsadm-save

规则重载工具:/usr/sbin/ipvsadm-restore

配置文件:/etc/sysconfig/ipvsadm-config

ipvs调度规则文件:/etc/sysconfig/ipvsadm

4.2 ipvsadm命令

核心功能:集群服务管理集群服务的RealServer:增、删、改、查。

pvs规则:/proc/net/ip_vs

ipvs连接:/proc/net/ip_vs_conn

命令参数:

  • 管理集群服务

    复制代码
     ipvsadm -A|E -t(tcp)|u(udp)|f(防护墙标签) \
     service-address(集群地址-->DIP) \
     [-s scheduler(调度算法)] \
     [-p [timeout]] \
     [-M netmask] \
     [--pepersistence_engine] \
     [-b sched-flags]
     ipvsadm -A|E -t|u|f DIP [-s scheduler] [-p [timeout]]
     -A #添加
     -E #修改
     -t #tcp服务
     -u #udp服务
     -s #指定调度算法,默认为WLC
     -p #设置持久连接超时,持久连接可以理解为在同一个时间段同一个来源的请求调度到同一RealServer
     -f #firewall mask 火墙标记,是一个数字
     ​
     # 增
     ipvsadm -A -t|u DIP -s [调度算法]
     ipvsadm -A -f [火墙标记] DIP -p [持久连接超时时间]
     ​
     # 改
     ipvsadm -E -t|u DIP -s [调度算法] -p [持久连接超时时间]
     ​
     # 删
     ipvsadm -D -t|u service-address
     ipvsadm -D -f [火墙标记]
  • 管理集群中的RS

    复制代码
     ipvsadm -a|e -t|u|f service-address -r server-address [-g | -i| -m](工作模式) [-w weight](权重)
     ipvsadm -a|e -t(tcp)|u(udp)|f(防护墙标签) \
     service-address(集群地址-->DIP) \
     -r server-address(真实服务地址--RIP) \
     [-g | -i| -m](工作模式) \
     [-w weight](权重)
     ipvsadm -a|e -t|u|f DIP -r RIP [-g|i|m] -w [weight]
     -a #添加realserver
     -e #更改realserver中的参数,注如果要更改RIP要删了再添加到达修改效果。
     -t #tcp协议
     -u #udp协议
     -f #火墙 标签
     -r #realserver地址
     -g #直连路由模式
     -i #ipip隧道模式
     -m #nat模式
     -w #设定权重
     -Z #清空计数器
     -C #清空lvs策略
     -L #查看lvs策略
     -n #不做解析
     --rate :输出速率信息
     ​
     # 增、改
     ipvsadm -a|e -t|u|f DIP -r RIP [-g|i|m]
     ipvsadm -a|e -t|u|f DIP -r RIP [-g|i|m] -w [weight]
     # 删
     ipvsadm -d -t|u|f service-address -r server-address # 删除RS
     ipvsadm -Z [-t|u|f service-address] # 清除计数器
  • 其它

    复制代码
     # 查
     ipvsadm -L|l [options] 查看RS
     ipvsadm -Ln --rate
     [root@DR-server ~]# ipvsadm -Ln --rate
     IP Virtual Server version 1.2.1 (size=4096)
     Prot LocalAddress:Port              CPS InPPS OutPPS InBPS OutBPS
     ………………
     #CPS:每秒连接数,表示服务器处理新连接的速率
     #InPPS:每秒入站数据包数量,即从客户端发送到负载均衡器的数据包速率
     #OutPPS:每秒出站数据包数量,即从负载均衡器向后端服务器或客户端发送数据包的速率
     #InBPS:每秒入站流量(字节),即从客户端到服务器的流量速率。
     #OutBPS:每秒出站流量(字节),即从服务器到客户端的流量速率。
     ​
     # 其它
     ipvsadm –C 清空策略
     ipvsadm –R 重载
     ipvsadm -S [-n] 保存

5 LVS实践

5.1 NAT模式实现

5.1.1 实验环境

主机名 角色 VIP DIP RIP CIP 网关
VSNode 调度器 172.25.254.100 192.168.0.100 NULL NULL (172.25.254.2)
RS1 真实服务器 NULL NULL 192.168.0.20 NULL 192.168.0.100
RS2 真实服务器 NULL NULL 192.168.0.30 NULL 192.168.0.100
Client 用户测试机 NULL NULL NULL 172.25.254.101 (172.25.254.2)

网络环境

复制代码
 # 调度器
 [root@VSNode ~]# ip a | egrep "eth0$|eth1$"
     inet 172.25.254.100/24 brd 172.25.254.255 scope global noprefixroute eth0
     inet 192.168.0.100/24 brd 192.168.0.255 scope global noprefixroute eth1
 [root@VSNode ~]# route -n
 Kernel IP routing table
 Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
 0.0.0.0         172.25.254.2    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
 192.168.0.0     0.0.0.0         255.255.255.0   U     101    0        0 eth1
 # RS1
 [root@RS1 ~]# ip a | grep eth0$
     inet 192.168.0.20/24 brd 192.168.0.255 scope global noprefixroute 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
 # RS2
 [root@RS2 ~]# ip a | grep eth0$
     inet 192.168.0.30/24 brd 192.168.0.255 scope global noprefixroute 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@VSNode ~]# sysctl -a | grep ip_forward
 net.ipv4.ip_forward = 0
 net.ipv4.ip_forward_update_priority = 1
 net.ipv4.ip_forward_use_pmtu = 0
 [root@VSNode ~]# echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf
 [root@VSNode ~]# sysctl -p
 net.ipv4.ip_forward = 1
 [root@VSNode ~]# sysctl -a | grep ip_forward
 net.ipv4.ip_forward = 1
 net.ipv4.ip_forward_update_priority = 1
 net.ipv4.ip_forward_use_pmtu = 0
 [root@VSNode ~]# sh /usr/bin/my_script/swhouse_set.sh
 ==============================Start wshouse_set.sh script==============================
 Enter [function name] to option function,script support local,network,custom.
 Local,Aliyun,Docker,Epel,Customize):Aliyun
 Updating Subscription Management repositories.
 Unable to read consumer identity
 ​
 This system is not registered with an entitlement server. You can use "rhc" or "subscription-manager" to register.
 ​
 repo id                                         repo name
 AliyunAppStream                                 Aliyun.appstream
 AliyunBaseOS                                    Aliyun.baseos
 ​
 Sucess modify!!!
 ==============================End wshouse_set.sh script================================
 [root@VSNode ~]# dnf install ipvsadm -y >/dev/null

服务环境

复制代码
 # RS1
 [root@RS1 ~]# sh /usr/bin/my_script/swhouse_set.sh
 ==============================Start wshouse_set.sh script==============================
 Enter [function name] to option function,script support local,network,custom.
 Local,Aliyun,Docker,Epel,Customize):Local
 Updating Subscription Management repositories.
 Unable to read consumer identity
 ​
 This system is not registered with an entitlement server. You can use "rhc" or "subscription-manager" to register.
 ​
 repo id                                         repo name
 LocalAppStream                                  Local.appstream
 LocalBaseOS                                     Local.baseos
 ​
 Sucess modify!!!
 ==============================End wshouse_set.sh script================================
 [root@RS1 ~]# dnf install httpd -y >/dev/null
 [root@RS1 ~]# systemctl enable --now httpd
 Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
 [root@RS1 ~]# echo RS1 - 192.168.0.20 > /var/www/html/index.html
 # RS2
 ……

测试环境

复制代码
 [root@VSNode ~]# curl 192.168.0.20
 RS1 - 192.168.0.20
 [root@VSNode ~]# curl 192.168.0.30
 RS2 - 192.168.0.30

5.1.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
 [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.20:80 -m  -w 1
 [root@VSNode ~]# ipvsadm -a -t 172.25.254.100:80 -r 192.168.0.30: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.20:80              Masq    1      0          0
   -> 192.168.0.30:80              Masq    1      0          0
规则持久化
复制代码
 # 1.利用自定义文件进行持久化
 [root@VSNode ~]# ipvsadm-save -n > /mnt/ipvs.rule
 [root@VSNode ~]# ipvsadm -C
 [root@VSNode ~]# reboot
 [root@VSNode ~]# ipvsadm-restore < /mnt/ipvs.rule
 [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.20:80              Masq    1      0          0
   -> 192.168.0.30:80              Masq    1      0          0
 # 2.利用守护进程进行规则持久化
 # 通过查看ipvsadm的状态知道是在这个文件/etc/sysconfig/ipvsadm中读取规则的,有规则就可以成功启动,没有就报错。
 [root@VSNode ~]# systemctl status ipvsadm | grep -i process
     Process: 28890 ExecStart=/bin/bash -c exec /sbin/ipvsadm-restore < /etc/sysconfig/ipvsadm (code=exited, status=0/SUCCESS)
 [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.
 [root@VSNode ~]# reboot
 [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.20:80              Masq    1      0          0
   -> 192.168.0.30:80              Masq    1      0          0

5.1.3 测试

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

5.2 DR模式实现

5.2.1 实验环境

主机名 角色 VIP DIP RIP CIP 网关
Router 路由器 172.25.254.100 192.168.0.100 NULL NULL (172.25.254.2)
VSNode 调度器 192.168.0.200 192.168.0.50 NULL NULL 192.168.0.100
RS1 真实服务器 192.168.0.200 NULL 192.168.0.20 NULL 192.168.0.100
RS2 真实服务器 192.168.0.200 NULL 192.168.0.30 NULL 192.168.0.100
Client 用户测试机 NULL NULL NULL 172.25.254.101 172.25.254.100
路由器
复制代码
 # IP配置
 [root@Router ~]# ip a | egrep "eth0$|eth1$"
     inet 172.25.254.100/24 brd 172.25.254.255 scope global noprefixroute eth0
     inet 192.168.0.100/24 brd 192.168.0.255 scope global noprefixroute eth1
 # 开启内核路由
 [root@Router ~]# echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf
 [root@Router ~]# sysctl -p
 net.ipv4.ip_forward = 1
调度器
复制代码
 # IP设置
 [root@VSNode ~]# cd /etc/NetworkManager/system-connections/
 [root@VSNode system-connections]# cp eth0.nmconnection lo.nmconnection
 [root@VSNode system-connections]# vim lo.nmconnection
 [connection]
 id=lo
 type=loopback
 interface-name=lo
 ​
 [ipv4]
 method=manual
 address1=172.0.0.1/8
 address2=192.168.0.200/32
 [root@VSNode system-connections]# nmcli c reload lo
 [root@VSNode system-connections]# nmcli c up lo
 [root@VSNode system-connections]# ip a | egrep "lo$|eth0$"
     inet 127.0.0.1/8 scope host lo
     inet 192.168.0.200/32 scope global lo
     inet 192.168.0.50/24 brd 192.168.0.255 scope global noprefixroute eth0
 [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 ~]# for i in {20,30};do
 > scp /etc/NetworkManager/system-connections/lo.nmconnection root@192.168.0.$i:/etc/NetworkManager/system-connections/lo.nmconnection
 > done
Client
复制代码
 [root@Client ~]# vim /etc/NetworkManager/system-connections/eth0.nmconnection
 [root@Client ~]# nmcli c reload eth0
 [root@Client ~]# nmcli c up eth0
 [root@Client ~]# route -n
 Kernel IP routing table
 Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
 0.0.0.0         172.25.254.100  0.0.0.0         UG    100    0        0 eth0
 172.25.254.0    0.0.0.0         255.255.255.0   U     100    0        0 eth0
RS1
复制代码
 [root@RS1 ~]# nmcli c reload
 [root@RS1 ~]# nmcli c up lo
 [root@RS1 ~]# ip a | egrep "lo$|eth0$"
     inet 127.0.0.1/8 scope host lo
     inet 192.168.0.200/32 scope global lo
     inet 192.168.0.20/24 brd 192.168.0.255 scope global noprefixroute 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
 # 禁止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
复制代码
 [root@RS2 ~]# nmcli c reload
 [root@RS2 ~]# nmcli c up lo
 [root@RS2 ~]# ip a | egrep "lo$|eth0$"
     inet 127.0.0.1/8 scope host lo
     inet 192.168.0.200/32 scope global lo
     inet 192.168.0.30/24 brd 192.168.0.255 scope global noprefixroute 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
 # 禁止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

5.2.2 测试编写

路由器
复制代码
 # 数据转发策略
 [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
 # 查看NAT表
 [root@Router ~]# iptables -t nat -L
 ………………
 Chain POSTROUTING (policy ACCEPT)
 target     prot opt source               destination
 SNAT       all  --  anywhere             anywhere             to:192.168.0.100
 SNAT       all  --  anywhere             anywhere             to:172.25.254.100
 [root@Router ~]# iptables -t nat -S
 -P PREROUTING ACCEPT
 -P INPUT ACCEPT
 -P OUTPUT ACCEPT
 -P POSTROUTING ACCEPT
 -A POSTROUTING -o eth1 -j SNAT --to-source 192.168.0.100
 -A POSTROUTING -o eth0 -j SNAT --to-source 172.25.254.100
调度器
复制代码
 [root@VSNode ~]# sh /usr/bin/my_script/swhouse_set.sh
 ==============================Start wshouse_set.sh script==============================
 Enter [function name] to option function,script support local,network,custom.
 Local,Aliyun,Docker,Epel,Customize):Local
 ==============================End wshouse_set.sh script================================
 [root@VSNode ~]# dnf install ipvsadm -y >/dev/null
 [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.20 -g
 [root@VSNode ~]# ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.30 -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.20:80              Route   1      0          0
   -> 192.168.0.30:80              Route   1      0          0
 [root@VSNode ~]# ipvsadm-save -n > /etc/sysconfig/ipvsadm
 [root@VSNode ~]# systemctl start ipvsadm

5.2.3 测试

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

5.3 利用火墙解决轮询错误问题

http和https是独立的service,轮询会出现重复问题

5.3.1 现象复现

RS
复制代码
 # RS中开启http和heeps协议
 [root@RS1 ~]# dnf install mod_ssl -y >/dev/null
 [root@RS1 ~]# systemctl restart httpd
VSNode
复制代码
 # 添加https策略
 [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.20:80              Route   1      0          0
   -> 192.168.0.30:80              Route   1      0          0
 [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.20:443 -g
 [root@VSNode ~]# ipvsadm -a -t 192.168.0.200:443 -r 192.168.0.30: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.20:80              Route   1      0          0
   -> 192.168.0.30:80              Route   1      0          0
 TCP  192.168.0.200:443 rr
   -> 192.168.0.20:443             Route   1      0          0
   -> 192.168.0.30:443             Route   1      0          0
错误展示
复制代码
 [root@Client ~]# curl  192.168.0.200;curl -k https://192.168.0.200
 RS2 - 192.168.0.30
 RS2 - 192.168.0.30
解决方案

使用火墙标记访问VIP的80和443的所有数据包,设定一个标记数,然后对此标记进行负载

复制代码
 [root@VSNode ~]# iptables -t mangle -A PREROUTING -d 192.168.0.200 -p tcp -m multiport --dports 80,443 -j MARK --set-mark  6666
 [root@VSNode ~]# ipvsadm -A -f 6666 -s rr
 [root@VSNode ~]# ipvsadm  -a -f 6666 -r 192.168.0.20 -g
 [root@VSNode ~]# ipvsadm  -a -f 6666 -r 192.168.0.30 -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.20:80              Route   1      0          0
   -> 192.168.0.30:80              Route   1      0          0
 TCP  192.168.0.200:443 rr
   -> 192.168.0.20:443             Route   1      0          0
   -> 192.168.0.30:443             Route   1      0          0
 FWM  6666 rr
   -> 192.168.0.20:0               Route   1      0          0
   -> 192.168.0.30:0               Route   1      0          0
重测试
复制代码
 [root@Client ~]# curl  192.168.0.200;curl -k https://192.168.0.200
 RS2 - 192.168.0.20
 RS2 - 192.168.0.30

5.4 利用持久连接实现会话粘滞

调度策略

复制代码
 [root@VSNode ~]# ipvsadm -E -f 6666 -s rr -p 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 rr
   -> 192.168.0.20:80              Route   1      0          0
   -> 192.168.0.30:80              Route   1      0          0
 TCP  192.168.0.200:443 rr
   -> 192.168.0.20:443             Route   1      0          0
   -> 192.168.0.30:443             Route   1      0          0
 FWM  6666 rr persistent 1
   -> 192.168.0.20:0               Route   1      0          0
   -> 192.168.0.30:0               Route   1      0          0
相关推荐
云道轩3 小时前
在Rocky Linux 上在线安装OpenClaw 2026.2.13
linux·运维·人工智能·智能体·openclaw
也许,也会3 小时前
PLC1200 TCP/IP通信实操全解析:从基础到落地
服务器·网络·tcp/ip
IT 行者4 小时前
OpenClaw 浏览器自动化测试的那些坑(一):Linux Snap 版本的 Chromium 无法使用托管模式
linux·运维·服务器·人工智能
枷锁—sha4 小时前
【CTFshow-pwn系列】03_栈溢出【pwn 046】详解:Ret2Libc 之 64位动态泄露
服务器·网络·安全·网络安全·系统安全
t***44234 小时前
CORS:跨域访问、如何在Nginx中配置允许跨域访问
运维·nginx
RisunJan6 小时前
Linux命令-lvdisplay(显示逻辑卷属性)
linux·运维·服务器
茶杯梦轩6 小时前
从零起步学习并发编程 || 第二章:多线程与死锁在项目中的应用示例
java·服务器·后端
何中应6 小时前
使用Jenkins部署后端项目(Maven)
运维·ci/cd·jenkins
Trouvaille ~6 小时前
【Linux】网络层与IP协议详解:从地址到路由的完整指南
linux·运维·服务器·网络·tcp/ip·路由器·网络层