运维基础-负载均衡-LVS四层代理

1、LVS简介

  • LVS官网:http://www.linuxvirtualserver.org/
  • LVS(Linux Virtual Server,Linux虚拟服务器)是一个虚拟的服务器集群系统。此项目在1998年5月由章文嵩博士成立,是国内最早出现的自由软件项目之一,是根据iptables的实现来开发的,所以使用的时候会和iptables相类似。
  • 现在LVS需要的模块已经是Linux标准内核的一部分。
    • 在Linux2.4内核以前,要使用LVS就必须重新编译内核使其支持LVS功能。
    • 从Linux2.4内核之后,Linux内核已经内置了LVS的各个模块,因此可以直接使用LVS提供的各种功能。
  • LVS集群采用IP负载均衡技术和基于内容请求分发技术。
    • 负载调度器具有很好的吞吐率,将请求均衡地发送到不同的后端服务器上,且负载调度器自动屏蔽掉后端服务器的故障,从而将一组后端服务器构成一个高性能的、高可用的虚拟服务。
    • 整个服务器集群的结构对客户是透明的,而且无需修改客户端和服务器端的程序。为此,在设计时需要考虑系统的透明性、可伸缩性、高可用性和易管理性。

1.1、LVS集群架构

  • 一般来说,LVS集群采用三层结构,其主要组成部分为:
    • 负载调度器Director/load balancer):是整个集群对外面的前端机,负责将客户端的请求发送到一组服务器上,而客户端认为服务是来自一个IP地址(通常把这个IP成为虚拟ip或VIP)上的。
    • 服务器池Realserver/server pool):是一组真正执行客户端请求的服务器,服务一般有WEB、MAIL、FTP和DNS等。
    • 共享存储(shared storage):为服务器池提供一个共享的存储区,这样很容易使得服务器池拥有相同的内容,以便提供相同的服务。
  • LVS一般进行一级调度,然后通过nginx或haproxy进行二级调度。
    • 为什么要使用nginx进行二级调度,这是因为nginx可以对http协议的请求做更高级的调度,比如可以识别应用层数据、cookie、url或实现静动分离等。
    • 只要并发请求数量可以突破单个nginx或haproxy的负载数量(套接字数量),就要使用LVS(LVS不受套接字限制)

  • LVS相关术语
    • DS:Director Server、Virtual Server、Dispatcher、Balancer,是位于前端的负载均衡器(Director Server)。
    • RS:Real Server、upstream server、backend server,是后端真实的提供服务的服务器
    • VIP:用于和客户端通信的IP地址,即负载均衡器的外网IP。
    • DIP:Director Server IP,用于和后端真实服务器通信的IP地址,即负载均衡器的内网IP。
    • RIP:Real Server IP,后端真实服务器的IP地址
    • CIP:Client IP,客户端的IP地址,即请求的来源IP。

1.2、LVS软件组成

  • LVS的功能是由linux内核中的ipvs模块实现的
  • IPVS是工作在linux内核中的netfilter的INPUT钩子上的程序。(input钩子上的过滤规则(filter)会影响ipvs的功能)
  • ipvsadm是命令行工具,工作在用户空间,用于管理在IPVS上的虚拟服务和虚拟服务的RS(Real Server)。
  • 基于LVS实现4层负载均衡的原理
    • (1)当用户的请求报文到达DS后,请求报文会先经过内核空间的PREROUTING链,如果请求报文的目标IP是本机,就将请求报文发送至INPUT链。
    • (2)当请求报文到达INPUT链后,IPVS会查看请求报文请求的服务是否是IPVS上的虚拟服务(事先定义在IPVS上的规则)。如果是,IPVS就会修改请求报文(将目的IP和端口修改成RS的IP和端口),然后将请求报文发至POSTROUTING链,POSTROUTING链最终将请求报文发送给RS。

 

  • 查看内核是否编译了IPVS:
]# grep -i -C10 'ipvs' /boot/config-3.10.0-1062.el7.x86_64
......
# IPVS transport protocol load balancing support    //LVS支持协议
CONFIG_IP_VS_PROTO_TCP=y
CONFIG_IP_VS_PROTO_UDP=y
CONFIG_IP_VS_PROTO_AH_ESP=y
CONFIG_IP_VS_PROTO_ESP=y
CONFIG_IP_VS_PROTO_AH=y
CONFIG_IP_VS_PROTO_SCTP=y

# IPVS scheduler    //LVS支持算法
CONFIG_IP_VS_RR=m
CONFIG_IP_VS_WRR=m
CONFIG_IP_VS_LC=m
CONFIG_IP_VS_WLC=m
CONFIG_IP_VS_LBLC=m
CONFIG_IP_VS_LBLCR=m
CONFIG_IP_VS_DH=m
CONFIG_IP_VS_SH=m
CONFIG_IP_VS_SED=m
CONFIG_IP_VS_NQ=m

2、LVS负载均衡模型

  • LVS的负载均衡常用的模型有四种:
    • LVS_NAT:DS会修改请求报文的目标IP(类似多目标IP的DNAT)。
    • LVS_DR:(DirectRouting,直接路由)DS会修改请求报文中的MAC地址。
    • LVS_TUN:(Tunneling,隧道)DS会在原请求报文之外再添加一个新的IP首部。
    • LVS_FULLNAT:DS会修改请求报文的源IP和目标IP。

2.1、LVS_NAT模型

  • LVS_NAT架构图如下:

  • 一个客户端请求要经历的过程:
    • (1)当用户的请求报文到达DS后,请求报文会先经过内核空间的PREROUTING链,如果请求报文的目标IP是本机,就将请求报文发送IN给PUT链。此时请求报文的源IP为CIP,目标IP为VIP。
    • (2)当请求报文到达INPUT链后,IPVS会查看请求报文请求的服务是否是IPVS上的虚拟服务。如果是,IPVS就会修改请求报文(将目的IP和端口修改成RS的IP和端口),然后将请求报文发给POSTROUTING链,POSTROUTING链最终将请求报文发送给RS。此时请求报文的源IP为CIP,目标IP为RIP。
    • (3)当请求报文到达RS后,RS接受并处理请求报文。然后RS会构建响应报文并发送给DS。此时响应报文的源IP为RIP,目标IP为CIP。
    • (4)当响应报文到达DS后,DS会修改响应报文(将源IP和端口修改成自己的VIP和端口),然后将响应报文发送给客户端。此时响应报文的源IP为VIP,目标IP为CIP。
  • 注意事项:
    • (1)DS必须是Linux系统,RS可以是任意系统。
    • (2)RIP和DIP必须在同一个网络中,且应该使用私网地址。RS要将自己的默认网关指向DIP
    • (3)请求报文和响应报文都必须经由DS转发(DS容易成为系统的瓶颈)。
    • (4)LVS_NAT支持端口映射

2.2、LVS_DR模型

  • VIP和RIP在同一网络中,就不需要DIP了,这种LVS_DR的架构图如下:

  • VIP和RIP不在同一网络中,需要DIP,并且DIP要和RIP在同一网络,这种LVS_DR架构图如下:

  • 一个客户端请求要经历的过程:
    • (1)当用户的请求报文到达DS后,请求报文会先经过内核空间的PREROUTING链,如果请求报文的目标IP是本机,就将请求报文发送给INPUT链。此时请求报文的源IP为CIP,目标IP为VIP。
    • (2)当请求报文到达INPUT链后,IPVS会查看请求报文请求的服务是否是IPVS上的虚拟服务。如果是,IPVS就会修改请求报文(将请求报文中的源MAC修改为DIP的MAC,将目标MAC修改RIP的MAC),然后将请求报文发给POSTROUTING链,POSTROUTING链最终将请求报文发送给RS。此时请求报文的源IP和目的IP均未修改,仅修改了源MAC地址为DIP的MAC地址,目标MAC地址为RIP的MAC地址。
      • 由于DIP和RIP在同一个网络中,所以是通过二层链路(交换机)传输的。POSTROUTING链检查目标MAC为RIP,就会将该请求报文将会发给RS。
    • (3)当请求报文到达RS后,RS发现请求报文的MAC是自己的MAC,就接收此报文。处理完成之后,将响应报文通过lo接口发送给ens33网卡(在lo上没有抓到相关的包,ens33上抓到了),然后响应报文由ens33网卡发送给客户端。此时响应报文的源IP地址为VIP,目标IP为CIP。
  • 注意事项:
    • (1)DS和RS都需要配置VIP。(RS的VIP一般配置在lo接口上)
    • (2)RS要限制ARP通告和应答级别
    • (3)RIP和DIP要在同一个网络中。(RIP可以是私网地址,也可以是公网地址)
    • (4)RIP的网关不能指向DIP,以确保响应报文不会经由DS。(所有请求报文经过DS,但响应报文不经过DS)
    • (5)LVS_DR不支持端口映射

2.3、LVS_TUN模型

  • 隧道模型运维起来会比较难,所以一般不用。
  • 隧道模型:IPVS不修改请求报文的IP首部(源IP为CIP,目标IP为VIP),而是在原IP首部之外再封装一个IP首部(源IP是DIP,目标IP是RIP),然后将请求报文发送给挑选出来的目标RS,RS直接将响应报文发给客户端(源IP是VIP,目标IP是CIP)。
  • LVS_TUN的架构图如下:

  • 一个客户端请求要经历的过程:
    • (1)当用户的请求报文到达DS后,请求报文会先经过内核空间的PREROUTING链,如果请求报文的目标IP是本机,就将请求报文发送至INPUT链。此时请求报文的源IP为CIP,目标IP为VIP。
    • (2)当请求报文到达INPUT链后,IPVS会查看请求报文请求的服务是否是IPVS上的虚拟服务。如果是,IPVS就会修改请求报文(在请求报文的首部再次封装一层IP首部,再次封装的源IP是DIP、目标IP是RIP。),然后将请求报文发至POSTROUTING链,POSTROUTING链最终将请求报文发送给RS。此时请求报文的源IP为DIP,目标IP为RIP。
    • (3)当请求报文到达RS后,RS能够理解并解析两层IP首部。处理完成之后,将响应报文通过lo接口发送给ens33网卡(在lo上没有抓到相关的包,ens33上抓到了),然后响应报文由ens33网卡发送给客户端。此时响应报文的源IP为VIP,目标IP为CIP。
  • 注意事项:
    • (1)RS的OS也要支持IP隧道功能。
    • (2)VIP、DIP、RIP都应该是公网地址。
    • (3)DS和RS都需要配置VIP。(RS的VIP一般配置在lo接口上)
    • (4)RS的网关不能指向DIP(所有请求报文经过DS,但响应报文不经过DS)
    • (5)LVS_TUN不支持端口映射

2.4、LVS_FULLNAT模型

  • LVS_FULLNAT模型和LVS_NAT相似,只是数据包在过IPVS时,不只修改目的IP,源IP也会被修改。
  • Linux内核不支持该模型,如果要使用该模型,需要重新编译内核。
  • LVS_FULLNAT的架构图如下:

  • 注意事项:
    • (1)DIP和RIP不需要在同一网络中。(RIP的网关一般不会指向DIP)
    • (2)请求报文和响应报文都必须经由DS转发(DS容易成为系统的瓶颈)。
    • (3)LVS_FULLNAT支持端口映射

3、LVS负载均衡调度算法

  • 根据调度时是否考虑各后端服务器当前的负载状态,可以将调度算法分为两种:
    • 静态算法:仅根据算法本身进行调度,不考虑后端服务器的负载状态。
    • 动态算法:根据调度算法和每个后端服务器当前的负载状态进行调度。

3.1、静态算法

1、RR:(Round-Robin Scheduling,轮询调度算法)

  • 轮询调度算法将所有请求依次发送到其列表中的下一个服务器,并循环服务器列表。
  • 轮询算法假设所有的服务器处理请求的能力是一样的,调度器会将所有的请求平均分配给每个服务器上。

2、WRR:(Weighted Round-Robin Scheduling,加权轮询调度算法)

  • 加权轮询调度算法可以为每台后端服务器可以分配一个权重(整数),表示处理能力。
  • 权重高的服务器比权重低的服务器优先接收新连接,权重高的服务器比权重低的服务器获得更多连接,权重相等的服务器获得相等连接。例如,服务器A、B、C的权值分别为4、3、2,一个调度周期为AABABCABC。
  • 当服务器的处理能力不同时,加权轮询调度优于轮询调度。但是,当请求的负载变化较大时,可能会导致服务器之间的动态负载不均衡。简而言之,大多数需要大量响应的请求都有可能被定向到相同的服务器上。

3、SH:(Source Hashing Scheduling,源地址散列(哈希)调度算法)

  • 先将请求的源IP转换成散列键(Hash Key),然后从静态分配的散列表中查找该散列键:
    • 如果可以查找到该散列键,且其对应的后端服务器是可用的也未超载,就将请求发送到这个后端服务器。
    • 如果查找不到该散列键,就做加权轮询调度,并记录到静态分配的散列表中。
  • 可以将来自同一个IP的请求始终发往第一次挑中的后端服务器,从而实现会话绑定。
  • 注意,绑定时间未知,它根据记忆空间的大小和淘汰算法进行淘汰决定的。

4、DH:(Destination Hashing Scheduling,目标地址散列(哈希)调度算法)

  • 先将请求的目标IP转换成散列键(Hash Key),然后从静态分配的散列表中查找该散列键:
    • 如果可以查找到该散列键,且其对应的后端服务器是可用的也未超载,就将请求发送到这个后端服务器。
    • 如果查找不到该散列键,就做加权轮询调度,并记录到静态分配的散列表中。
  • 可以将发往同一个目标IP的请求始终转发到第一次挑中的后端服务器(目标IP地址绑定),典型的使用场景是正向代理的负载均衡(使用正向代理服务器的缓存)。

3.2、动态算法

1、LC:(Least-Connection Scheduling,最小连接调度算法)

  • Overhead = activeconns * 256 + inactiveconns
  • 把新的请求分配到当前Overhead最小的后端服务器。最小连接调度是一种动态的调度算法,它通过后端服务器当前活跃的连接数来估计服务器的情况。
  • 最小连接调度算法无法在具有不同处理能力的服务器之间实现负载均衡。
    • 乍一看,即使有不同处理能力的服务器,最少连接调度也可以执行得很好,因为更快的服务器将获得更多的网络连接。事实上,由于TCP的TIME_WAIT状态,它不能执行得很好。TCP的TIME_WAIT通常是2分钟,在这2分钟的时间里,一个繁忙的网站经常会收到数千个连接,例如,服务器a是服务器B的两倍强大,服务器a处理数千个请求,并保持它们在TCP的TIME_WAIT状态,但服务器B是爬行来完成它的数千个连接。

2、WLC:(Weighted Least-Connection Scheduling,加权最少连接调度算法)

  • Overhead = ( activeconns * 256 + inactiveconns ) / weight 
  • 把新的请求分配到当前Overhead最小的后端服务器。权值表示服务器处理请求的性能,默认权值为1。
    • 系统管理员可以动态地设置后端服务器的权值。
    • 大多数的时候WLC是最优的算法。
  • 加权最小连接调度算法比最小连接调度算法多个除法。同时采用最小连接调度算法和加权最小连接调度算法,希望在服务器处理能力相同的情况下最小化调度开销。

3、SED:(Shortest Expected Delay Scheduling,最短的期望的延迟调度算法)

  • Overhead = ( activeconns + 1 ) * 256 / weight
  • SED是WLC的优化。
    • 例如A、B、C三台服务器的权重分别为1、2、3,那么如果使用WLC算法的话一个新请求进入时它可能会分给ABC中的任意一个。使用SED算法后会进行一个运算A:(1+1)/1=2、B:(1+1)/2=1、C:(1+1)/3=2/3就把请求交给得出运算结果最小的服务器。

4、NQ:(Never Queue Scheduling,最少队列调度算法)

  • 最少队列调度算法采用双速度模型。
    • 当有空闲的后端服务器可用时,请求将被发送到空闲的服务器,而不是等待服务器。
    • 当没有空闲的后端服务器可用时,请求将被发送到期望延迟最小的服务器(Shortest Expected Delay Scheduling)。

5、LBLC:(Locality-Based Least-Connection Scheduling,基于局部的最少连接调度)

  • 动态的DH算法。
  • 先将请求的目标IP转换成散列键(Hash Key),然后从静态分配的散列表中查找该散列键:
    • 如果可以查找到该散列键,且其对应的后端服务器是可用的:
      • 未超载,就将请求发送到这个后端服务器。
      • 已超载,就通过加权最少连接调度算法(WLC)为该请求重新选取后端服务器,并记录到静态分配的散列表中。
    • 如果查找不到该散列键,不是做轮询而是根据后端服务器的负载情况进行调度,并记录到静态分配的散列表中。

6、LBLCR:(Locality-Based Least-Connection with Replication Scheduling,带复制的基于局部性的最少连接)

  • 将负载较重的服务器的一些请求匀到负载轻的服务器上,缓存项共享(即负载较重的服务器的缓存可以复制到负载较轻的服务器上)。 

4、ipvsadm命令

  • 安装ipvsadm:
]# yum install ipvsadm
  • ipvsadm命令的使用方法:
//查看IPVS上的虚拟服务列表
ipvsadm -L|l [options]
//管理虚拟服务
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 -Z [-t|u|f service-address]
ipvsadm -R
ipvsadm -S [-n]
//管理虚拟服务的RS
ipvsadm -a|e -t|u|f service-address -r server-address [-g|i|m] [-w weight] [-x upper] [-y lower]
ipvsadm -d -t|u|f service-address -r server-address

ipvsadm --set tcp tcpfin udp
ipvsadm --start-daemon state [--mcast-interface interface] [--syncid syncid]
ipvsadm --stop-daemon state

4.1、查看IPVS上的虚拟服务列表

ipvsadm -L|l [options]
    -L, -l, --list       如果没有指定参数,则列出虚服务器表。如果选择了某个服务地址,只列出该服务。

    -n, --numeric        数字的格式输出IP地址和端口号,不进行反解。
    --exact              显示数据包和字节计数器的精确值。该选项仅与-L命令相关。

    -c, --connection     显示连接状态。列出当前的IPVS连接。
    --stats              输出统计信息。显示虚拟服务及其RS的统计信息。
    --rate               输出速率信息。显示虚拟服务及其RS的速率信息(如连接/秒、字节/秒和数据包/秒)。
    --thresholds         输出阈值信息。显示虚拟服务列表中每个RS的连接阈值上/下信息。
    --persistent-conn    输出的持久连接信息。在虚拟服务列表中显示每个RS的持久连接计数器信息。
    --timeout            超时输出。显示TCP会话超时时间(以秒为单位)、TCP会话收到FIN报文后超时时间(以秒为单位)和UDP报文超时时间(以秒为单位)
    --daemon             输出守护进程信息。显示守护进程状态及其多播接口。

4.2、管理虚拟服务

1、添加或修改虚拟服务

ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]] [-M netmask] [--pe persistence_engine] [-b sched-flags]
    -A, --add-service                    添加虚拟服务。由IP地址、端口号和协议三组数据唯一定义。
    -E, --edit-service                   编辑虚拟服务

    -t, --tcp-service service-address    TCP协议的虚拟服务,service-address是VIP的host[:port]
    -u, --udp-service service-address    UDP协议的虚拟服务,service-address是VIP的host[:port]
    -f, --fwmark-service fwmark          使用防火墙标记来定义一个虚拟服务,而不是地址、端口和协议(UDP或TCP)。fwmark是一个大于0的整数

    -s, --scheduler scheduler            指定调度算法(用于tcp和udp协议)。可选的调度算法有rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq,默认是wlc。

    -p, --persistent [timeout]           指定一个虚拟服务是持久的。如果指定了此选项,来自一个客户端的多个请求都将被发送到第一次请求时选择的RS。持久会话的超时默认300秒。此选项可以与SSL或FTP等协议一起使用,在这些协议中客户端始终与相同的RS连接是很重要的。
    -M, --netmask netmask                为持久虚拟服务指定客户端分组的粒度。
    --pe engine                          备用持久化引擎可能是sip,默认情况下没有设置。
    -b, --sched-flags flags              调度器旗帜(逗号分隔)

2、删除虚拟服务

ipvsadm -D -t|u|f service-address
    -D, --delete-service                删除虚拟服务,同时删除关联的RS。

3、清除所有的虚拟服务

ipvsadm -C
    -C, --clear                         清除所有的虚拟服务

4、清空虚拟服务的计数器

ipvsadm -Z [-t|u|f service-address]
    -Z, --zero                          将虚拟服务中的包、字节和速率计数器归零。

5、重载和保存虚拟服务规则

//重载虚拟服务规则
ipvsadm -R
    -R, --restore

//存虚拟服务规则
ipvsadm -S [-n]
    -S, --save

示例:

//将ipvs规则保存到文件
]# ipvsadm -S -n > save_ipvsadm.conf
//从文件中重载ipvs规则
]# ipvsadm -R  < save_ipvsadm.conf

4.3、管理虚拟服务的RS

1、向虚拟服务中添加或编辑RS

ipvsadm -a|e -t|u|f service-address -r server-address [-g|i|m] [-w weight] [-x upper] [-y lower]
    -a, --add-server                    向虚拟服务中添加RS。
    -e, --edit-server                   编辑虚拟服务中的RS。

    -r, --real-server server-address    要向虚拟服务中添加的RS,server-address是RIP的host[:port]

    -g, --gatewaying                    指定LVS的工作模型为直接路由模型(direct routing),即LVS_DR。这是默认值。
    -i, --ipip                          指定LVS的工作模型为隧道模型(tunneling),即LVS_TUN。
    -m, --masquerading                  指定LVS的工作模型为伪装模型(network access translation, or NAT),即LVS_NAT。

    -w, --weight weight                 指定RS的权重,取值范围是0-65535,默认值为1。静态服务器的权重为0。

    -x, --u-threshold uthreshold        用于指定服务器的连接上限阈值。uthreshold取值范围为0-65535。默认值是0,这意味着没有设置上限连接阈值。如果设置了uthreshold,则当服务器的连接数超过其最大连接数阈值时,不会再向服务器发送新的连接。
    -y, --l-threshold lthreshold        用于指定服务器的低连接阈值。lthreshold的取值范围是0-65535。默认值是0,这意味着没有设置低连接阈值。如果设置了lthreshold,那么当服务器的连接数低于其较低的连接阈值时,服务器将接收新的连接。如果没有设置lthreshold,但是设置了uthreshold,那么当服务器的连接数低于其上连接阈值的四分之三时,服务器将接收新的连接。

2、删除虚拟服务中的RS

  • 当一个RS不再接受请求时,可以将其删除或权重置为零。
ipvsadm -d -t|u|f service-address -r server-address
    -d, --delete-server

5、实现LVS负载均衡

5.1、实现LVS_NAT

  • (1)DS必须是Linux系统,RS可以是任意系统。
  • (2)RS要将自己的默认网关指向DIP。
  • (3)DS要开启核心转发。在IPVS框架上配置虚拟服务,LVS_NAT支持端口映射

1、实验的架构

  • DS主机:
    • 第一块网卡:VMware网卡是VMnet8,主机网卡接口和地址分别是ens33、10.1.1.12
    • 第二块网卡:VMware网卡是VMnet1,主机网卡接口和地址分别是ens36、192.168.1.254
  • RS1主机:
    • 仅有一块网卡:VMware网卡是VMnet1,主机网卡接口和地址分别是ens33、192.168.1.101
  • RS2主机:
    • 仅有一块网卡:VMware网卡是VMnet1,主机网卡接口和地址分别是ens33、192.168.1.102

2、配置RS

  • (1)安装httpd,并配置index.html文件
//安装并启动httpd
]# yum install httpd -y
]# systemctl start httpd.service

//配置index.html文件(两个RS上的index.html不一样,这是为了测试可以观察出来)
]# echo '<h1>RS, 192.168.1.101</h1>' > /var/www/html/index.html

]# echo '<h1>RS, 192.168.1.102</h1>' > /var/www/html/index.html
  • (2)配置RS的默认网关为192.168.1.254(DIP)。
//在ifcfg-ens33文件中添加默认网关
]# vim /etc/sysconfig/network-scripts/ifcfg-ens33
GATEWAY=192.168.1.254
//重启网络
]# systemctl restart network.service
  • (3)在DS上测试两个RS上的httpd服务是否可用
]# curl 192.168.1.101
<h1>RS, 192.168.1.101</h1>
]# curl 192.168.1.102
<h1>RS, 192.168.1.102</h1>

3、配置DS

  • (1)安装ipvsadm
]# yum install ipvsadm
  • (2)开启核心转发(永久生效):
]# vim /etc/sysctl.conf    #/proc/sys/net/ipv4/ip_forward
net.ipv4.ip_forward=1
]# sysctl -p
  • (3)在IPVS上添加虚拟服务和RS
//添加一个虚拟服务
]# ipvsadm -A -t 10.1.1.12:80 -s rr

//为虚拟服务添加RS
]# ipvsadm -a -t 10.1.1.12:80 -r 192.168.1.101 -m
]# ipvsadm -a -t 10.1.1.12:80 -r 192.168.1.102 -m

//查看虚拟服务列表
]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.1.1.12:80 rr
  -> 192.168.1.101:80             Masq    1      0          0         
  -> 192.168.1.102:80             Masq    1      0          0 

4、在客户端测试请求

//在客户端上执行
]# for i in {1..10}; do curl 10.1.1.12; done

5、编辑IPVS上的规则

示例1:

  • 修改虚拟服务的调度算法,以及虚拟服务的RS的权重
]# ipvsadm -E -t 10.1.1.12:80 -s wrr
]# ipvsadm -e -t 10.1.1.12:80 -r 192.168.1.101:80 -m -w 2
]# ipvsadm -e -t 10.1.1.12:80 -r 192.168.1.102:80 -m -w 3

]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.1.1.12:80 wrr
  -> 192.168.1.101:80             Masq    2      0          0         
  -> 192.168.1.102:80             Masq    3      0          0  

示例2:

  • 在ipvs上再添加一个虚拟服务
]# ipvsadm -A -t 10.1.1.12:8080 -s wrr
]# ipvsadm -a -t 10.1.1.12:8080 -r 192.168.1.101:8080 -m -w 2
]# ipvsadm -a -t 10.1.1.12:8080 -r 192.168.1.102:8080 -m -w 3

]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.1.1.12:80 wrr
  -> 192.168.1.101:80             Masq    2      0          0         
  -> 192.168.1.102:80             Masq    3      0          0         
TCP  10.1.1.12:8080 wrr
  -> 192.168.1.101:8080           Masq    2      0          0         
  -> 192.168.1.102:8080           Masq    3      0          0  

5.2、实现LVS_DR

  • (1)DS和RS都需要配置VIP。(RS的VIP一般配置在lo接口上)
  • (2)RS要限制ARP通告和应答级别。
  • (3)LVS_DR不支持端口映射。

1、实验的架构(VIP和RIP在同一网络)

  • DS主机:
    • 仅有一块网卡:VMware网卡是VMnet8,主机网卡接口和地址分别是ens33、10.1.1.11
  • RS1主机:
    • 仅有一块网卡:VMware网卡是VMnet8,主机网卡接口和地址分别是ens33、10.1.1.12
  • RS2主机:
    • 仅有一块网卡:VMware网卡是VMnet8,主机网卡接口和地址分别是ens33、10.1.1.13
  • VIP:10.1.1.99
    • DS的VIP配置在ens33:0上,RS的VIP配置在lo:0上。

2、配置RS

  • (1)安装httpd,并配置index.html文件
//安装并启动httpd
]# yum install httpd -y
]# systemctl start httpd.service
 
//配置index.html文件(两个RS上的index.html不一样,这是为了测试可以观察出来)
]# echo '<h1>RS, 10.1.1.12</h1>' > /var/www/html/index.html
 
]# echo '<h1>RS, 10.1.1.13</h1>' > /var/www/html/index.html
  • (2)限制ARP通告和应答级别
//配置arp的内核参数,抑制arp的通告和应答
]# cat > /etc/sysctl.conf << EOF
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.all.arp_ignore = 1
EOF
//使配置生效
]# sysctl -p
  • (3)配置VIP
//将VIP配置到lo:0上
]# cat > /etc/sysconfig/network-scripts/ifcfg-lo:0 << EOF
DEVICE=lo:0
ONBOOT=yes
BOOTPROTO=static
IPADDR=10.1.1.99
PREFIX=32
EOF
//重启网络服务
]# systemctl restart network.service
  • (4)在DS上测试两个RS上的httpd服务是否可用
]# curl 10.1.1.12
<h1>RS, 10.1.1.12</h1>
]# curl 10.1.1.13
<h1>RS, 10.1.1.13</h1>

3、配置DS

  • (1)安装ipvsadm
]# yum install ipvsadm
  • (2)配置VIP
//将VIP配置到ens33:0上
]# cat > /etc/sysconfig/network-scripts/ifcfg-ens33:0 << EOF
DEVICE=ens33:0
ONBOOT=yes
BOOTPROTO=static
IPADDR=10.1.1.99
PREFIX=32
EOF
//重启网络服务
]# systemctl restart network.service 
  • (3)在IPVS上添加虚拟服务和RS
//添加一个虚拟服务
]# ipvsadm -A -t 10.1.1.99:80 -s rr

//为虚拟服务添加RS
]# ipvsadm -a -t 10.1.1.99:80 -r 10.1.1.12 -g
]# ipvsadm -a -t 10.1.1.99:80 -r 10.1.1.13 -g

//查看虚拟服务列表
]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.1.1.99:80 rr
  -> 10.1.1.12:80                 Route   1      0          0         
  -> 10.1.1.13:80                 Route   1      0          0 

4、在客户端测试请求

//在客户端上执行
]# for i in {1..10}; do curl 10.1.1.99; done

6、IPVS使用防火墙标记定义虚拟服务

  • 除了上面哪些使用地址、端口和协议(UDP或TCP)定义虚拟服务外,还可以使用防火墙标记定义虚拟服务。
  • iptables的处理动作--MARK:
    • MARK用于设置与数据包相关的Netfilter标记值。
      • --set-xmark value
  • IPVS使用防火墙标记定义虚拟服务,可以用于LVS_NAT、LVS_DR、LVS_TUN和LVS_FULLNAT模型,也可以使用任何调度算法
    • 先使用防火墙(iptables)来标记报文,而后基于该标记定义虚拟服务。
    • 可以将多个不同的应用(使用地址、端口和协议确定一个应用)使用同一个虚拟服务服务进行调度。
//给报文打上防火墙标记(在DS执行)
iptables -t mangle -A PREROUTING -d $VIP -p tcp -m multiport --dports 80,443 -j MARK --set-mark $NUMBER

//基于标记定义虚拟服务
ipvsadm -A -f $NUMBER -s $scheduler
//基于标记添加RS:
ipvsadm -a -f $NUMBER -r $RIP [-g|i|m]

示例:

  • IPVS使用防火墙标记定义虚拟服务,使用LVS_NAT模型进行测试(在DS上执行)。
//清空
]# iptables -F
]# ipvsadm -C

//给报文打上防火墙标记
]# iptables -t mangle -A PREROUTING -d 10.1.1.12 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 9
//基于标记定义虚拟服务
]# ipvsadm -A -f 9 -s rr
//基于标记添加RS
]# ipvsadm -a -f 9 -r 192.168.1.101 -m
]# ipvsadm -a -f 9 -r 192.168.1.102 -m

//查看mangle表
]# iptables -t mangle -nL PREROUTING
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
MARK       tcp  --  0.0.0.0/0            10.1.1.12            multiport dports 80,443 MARK set 0x9
//查看虚拟服务列表
]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
FWM  9 rr
  -> 192.168.1.101:0              Masq    1      0          0         
  -> 192.168.1.102:0              Masq    1      0          0 
  • 测试
]# for i in {1..10}; do curl http://10.1.1.12; curl https://10.1.1.12; done

7、LVS的持久连接

  • LVS的持久连接:无论使用任何调度算法,在一段时间内,会将来自同一个客户端的请求发送到同一个RS。
ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]]
    [-p [timeout]]
        指定一个虚拟服务是持久的。如果指定了此选项,来自一个客户端的多个请求都将被发送到第一次请求时选择的RS。
        持久会话的超时默认300秒。
        此选项可以与SSL或FTP等协议一起使用,在这些协议中客户端始终与相同的RS连接是很重要的。
  • LVS持久连接的类型:
    • 每端口持久:基于端口定义虚拟服务,一个端口对应一个虚拟服务。在一段时间内,会将同一个客户端对同一个端口的请求发送到同一个RS。
    • 每防火墙标记持久:基于防火墙标记定义虚拟服务。可实现将多个端口上的应用统一调度,即port Affinity。
    • 每客户端持久:基于0端口定义虚拟服务,将所有的端口都定义成了虚拟服务。会将同一个客户端对所有端口的请求都发送到同一个RS。(基于0端口定义虚拟服务时,必须使用持久连接

示例1:

  • 每端口持久,使用LVS_NAT模型进行测试(在DS上执行)。
//清空
]# ipvsadm -C
]# iptables -F
]# iptables -t mangle -F

//添加一个虚拟服务
]# ipvsadm -A -t 10.1.1.12:80 -s rr -p 60

//为虚拟服务添加RS
]# ipvsadm -a -t 10.1.1.12:80 -r 192.168.1.101 -m
]# ipvsadm -a -t 10.1.1.12:80 -r 192.168.1.102 -m

//查看虚拟服务列表
]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.1.1.12:80 rr persistent 60
  -> 192.168.1.101:80             Masq    1      0          0         
  -> 192.168.1.102:80             Masq    1      0          0 

示例2:

  • 每防火墙标记持久,使用LVS_NAT模型进行测试(在DS上执行)。
//清空
]# ipvsadm -C
]# iptables -F
]# iptables -t mangle -F

//给报文打上防火墙标记
]# iptables -t mangle -A PREROUTING -d 10.1.1.12 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 9
//基于标记定义虚拟服务
]# ipvsadm -A -f 9 -s rr -p
//基于标记添加RS
]# ipvsadm -a -f 9 -r 192.168.1.101 -m
]# ipvsadm -a -f 9 -r 192.168.1.102 -m

//查看mangle表
]# iptables -t mangle -nL PREROUTING
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
MARK       tcp  --  0.0.0.0/0            10.1.1.12            multiport dports 80,443 MARK set 0x9
//查看虚拟服务列表
]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
FWM  9 rr persistent 360
  -> 192.168.1.101:0              Masq    1      0          0         
  -> 192.168.1.102:0              Masq    1      0          70  

示例3:

  • 每客户端持久,使用LVS_NAT模型进行测试(在DS上执行)。
//清空
]# ipvsadm -C
]# iptables -F
]# iptables -t mangle -F

//添加一个虚拟服务(使用":0"时,-p是必需有的)
]# ipvsadm -A -t 10.1.1.12:0 -s rr -p 60

//为虚拟服务添加RS
]# ipvsadm -a -t 10.1.1.12:0 -r 192.168.1.101 -m
]# ipvsadm -a -t 10.1.1.12:0 -r 192.168.1.102 -m

//查看虚拟服务列表
]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.1.1.12:0 rr persistent 60
  -> 192.168.1.101:0              Masq    1      0          0         
  -> 192.168.1.102:0              Masq    1      0          0

8、使用keepalive的高可用LVS

  • ldirectord只做后端服务的健康状态检测。
  • keepalived即可以做高可用,也可以做后端服务的健康状态检测
    • 参见:https://www.cnblogs.com/maiblogs/p/16533764.html中的“4、通过ipvs实现负载均衡”。
#                                                                                                                        #
posted @ 2022-06-15 21:25  麦恒  阅读(511)  评论(0编辑  收藏  举报