LVS实现负载均衡详解
2018/08/10 06:52:00 来源:Linux社区 作者:火星的小白

LVS是Linux Virtual Server的简称,即Linux虚拟服务器。从Linux内核2.4版本之后,已经将LVS内置于内核中,提供负载均衡技术。

目录

LVS理论基础

1、LVS的优势
高并发能力强  LVS基于内核网络层工作,有着超强的并发处理能力,单台LVS可以承受上万的并发连接。
稳定性高    LVS是基于4层的负载均衡软件,因此LVS在所有负载均衡软件中性能最强,稳定性最高,消耗CPU和内存少。
应用范围广  LVS是工作在4层,所以它可以对应用层的所有协议作负载均衡,包括http、DNS、ftp等。
2、LVS的组件
ipvsadm LVS已经集成于内核中,用户是无法直接操作内核空间的程序的,因此需要一个用户空间的管理工具,ipvsadm就是一个用户空间的命令行工具,用于管理集群。
ipvs   工作于内核netfilter INIPUT钩子上的一个程序,并且根据ipvsadm定义的规则实现请求的转发。
查看Linux内核是否支持ipvs:

`grep -i -C 10 --color=auto ipvs  /boot/config-2.6.32-696.el6.x86_64`

3、LVS的工作流程
LVS实现负载均衡
1、用户请求的数据包到达负载均衡器的内核空间,首先经过的是内核的PREROUTING链,
2、因为请求的数据包的目的地址一定是本机,然后将数据包送到INPUT链,
3、ipvs就工作在INPUT链上,ipvs利用ipvsadm定义的规则工作,ipvs对数据包进行检查,如果目的地址和端口不在规则里边,则将数据包送往用户空间,
4、如果目的地址和端口在规则里边,则将数据包的目的地址和端口修改为后端真实服务器,然后将修改后的数据包送往POSTROUTING链,
5、最后经过POSTROUTING链将数据包转发给后端服务器。
4、LVS的工作模式
NAT ①客户端发送数据包至负载均衡器,数据包的源IP是CIP,目的IP是VIP。数据包首先到达的是内核空间的PREROUTING链,②PREROUTING链判断目的IP是VIP,确定VIP是本地IP,然后将其送往INPUT链。③INPUT链上的ipvs将数据包的目的IP修改为RIP,然后发送给POSTROUTING链。④POSTROUTING链将数据包发送至后端服务器处理。⑤处理完之后,以源IP为RIP,目的IP为CIP的响应数据包返回给负载均衡器,⑥LVS收到之后再次修改数据包的IP地址,将数据包的源IP修改为VIP,目的IP保持不变仍为CIP,然后发往客户端。
LVS实现负载均衡
NAT工作模式中,请求的流量和回应的流量都必须经过前端的调度器,一次调度器成为了整个服务器集群的瓶颈,一旦调度器宕机,则整个集群将出去瘫痪状态,因此就出现了DR工作模式。
DR Direct Routing,①客户端发送数据包至负载均衡器,数据包的源IP是CIP,目的IP是VIP。数据包首先到达的是内核空间的PREROUTING链,②PREROUTING链判断目的IP是VIP,确定VIP是本地IP,然后将其送往INPUT链。③ipvs将数据包通过DIP的网卡发送给POSTROUTING链,其中源MAC自动修改为DIP的MAC(因为从DIP的网卡发送出去的),并且将目的MAC修改为RIP的MAC,源IP和目的IP保持不变,④POSTROUTING链将数据包发送给交换机,交换机根据RIP的MAC地址将数据包送往指定的后端服务器,⑤处理外后将数据包通过lo接口转发至eth0接口,由eth0将数据包发送出去,此时数据包的源IP和MAC是VIP:VIP的MAC,目的IP和MAC是CIP:CIP的MAC,⑥响应数据包最终交付给客户端。
LVS实现负载均衡
DR工作模式的特点:因为DR工作模式是根据MAC进行数据包转发,因此RS跟负载均衡器必须在同一个局域网(广播域)中;所有的请求报文都经过负载均衡器,所有的响应报文不经过负载均衡器;因为DR工作模式的响应报文是RS直接回应的,因此负载均衡器和RS必须都配置同一个VIP地址,RS的lo接口配置VIP,这样一来同一个局域网会有多个相同的IP,在进行ARP广播的时候会出现紊乱,这时需要通过修改RS的内核参数从而阻止RS对ARP广播进行回应,这样只有负载均衡器对VIP的ARP请求进行回应;由于DR工作模式仅需要分析数据包的MAC首部,因此DR的处理能力特别高,拥有和硬件负载均衡设备相媲美的网络吞吐和负载均衡能力。
TUN ①客户端发送请求至负载均衡器,该数据包的源IP是CIP,目的IP是VIP,②LVS收到数据包后,将该数据包的首部再封装一层IP首部,其中源IP为DIP,目的IP为RIP,将重整后的数据包送往后端服务器,③RS两次处理该数据包,将响应数据包通过lo接口送往eth0接口,然后直接发送给客户端。
LVS实现负载均衡
其中NAT和DR调度算法必须保证调度器和RS在同一个局域网中,也就是他们无法跨网段通信,而TUN调度算法则可以使得调度器和RS在不同的局域网中。
另外,通过对NAT工作模式进行改进,可以使得其跨网段通信,改进之后的工作模式为fullnat模式。工作流程和原理如图所示,
LVS实现负载均衡
5、LVS的调度算法
1、轮询(rr)
请求按顺序轮流分配到后端服务器上,后端每台服务器接受请求的概率是一样的。
2、加权轮询(wrr)
LVS根据后端服务器的处理能力给后端每台服务器设置权值。LVS可以自动询问真实服务器的负载情况,然后动态的调整权值,权值大的收到请求的概率大。
3、目标地址散列(dh)
根据请求的目标IP地址,得出hash值,进而找出对应的服务器,这种调度算法适用于缓存服务器的负载均衡。
4、源地址散列(sh)
根据请求的源IP地址,得出hash值,进而找出对应的服务器,这种调度算法适用于session共享的情况。
5、最少连接(lc)
动态地将请求调度到后端连接数最少的服务器上。这种调度算法适用于后端每台服务器性能相近的情况下。
6、加权最少连接(默认)(wlc)
LVS动态调整后端服务器的权值,权值大的将承受较大比例的活动连接负载。
7、最短延迟调度(sed)
8、永不排队/最少队列调度(nq)

ipvsadm命令

ipvs是集成与内核空间的,用户无法直接操作,因此需要借助管理工具ipvsadm,通过定义规则使得ipvs工作,类似于iptables。同样该工具可以借助yum安装和源码安装。
常用选项:
-A --add-server 新加一条虚拟服务器记录
-E --edit-server 编辑虚拟服务器记录
-D --delete-server 删除一条虚拟服务器记录
-C --clear   清空所有的虚拟服务器记录
-S --save   保存虚拟服务器规则
-R --restore  恢复虚拟服务器规则,从-S保存的规则中恢复
-t --tcp-service 表示tcp服务,指虚拟服务器
-u --udp-service 表示udp服务,指虚拟服务器
-s --schedule 使用的调度算法
  rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq  the default scheduler is wlc
-p  代表持久连接
-f  代表防火墙的标记
例子:
  ipvsadm -A -t 192.168.239.129:80 -s wlc
  ipvsadm -E -t 192.168.239.129:80 -s rr
  ipvsadm -S > /etc/sysconfig/ipvsadm
  ipvsadm -R < /etc/sysconfig/ipvsadm
-a 添加一条新的真实主机记录
-r 添加真实主机的地址
-m 指定LVS的工作模式为NAT
-w 指定真实服务器的权值
-g 指定LVS的工作模式为DR(默认)
-i 指定LVS的工作模式为TUN
例子:
  ipvsadm -a -t 192.168.239.129:80 -r 192.168.239.130 -m -w 1
-e 编辑一条虚拟服务器记录中的某条真实服务器
-d 删除一条虚拟服务器记录中的某条真实服务器
-L|-l 列出所有的虚拟服务器记录
-Z 清空当前的连接数(-l会显示虚拟服务器中连接数量)
例子:
  ipvsadm -e -t 192.168.239.129:80 -r 192.168.239.130 -g -w 3
  ipvsadm -d -t 192.168.239.129:80 -r 192.168.239.230

实验

LVS-DR模型
环境拓扑:

主机IP功能
LVS 192.168.239.250 调度器
Web1 192.168.239.129 RS
Web2 192.168.239.133 RS

前端负载均衡器的配置:

# 配置VIP至网卡别名
[root@LVS ~]# ifconfig eth0:0 192.168.239.250  netmask 255.255.255.0 up
# 定义LVS规则
[root@LVS ~]# ipvsadm -A -t 192.168.239.250:80 -s wrr
[root@LVS ~]# ipvsadm -a -t 192.168.239.250:80 -r 192.168.239.129:80 -g -w 1
[root@LVS ~]# ipvsadm -a -t 192.168.239.250:80 -r 192.168.239.133:80 -g -w 2
[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.239.250:80 wrr
  -> 192.168.239.129:80          Route  1      0          0       
  -> 192.168.239.133:80          Route  2      0          0

后端RS的配置(两台RS的配置过程一样,下面仅以Web1为例):

[root@Web1 web]# ifconfig lo:0 192.168.239.250 broadcast 192.168.239.250 netmask 255.255.255.255 up
[root@Web1 web]# route add -host 192.168.239.250 dev lo:0
# 抑制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

上面的配置过程中有几个问题要说明:
① 把VIP绑定至RS的lo回环接口上边,并且广播地址为自身和子网掩码为4个255,这样做是为了防止VIP冲突。
② 关于arp_ignore和arp_announce两个内核参数的意义,请参考ARP抑制
然后在两台RS上边部署Nginx的Web环境,分别往首页写入静态内容
This is Web1
This is Web2
然后在浏览器的地址列中输入VIP--192.168.239.250,刷新页面,页面内容能够实现调转说明负载均衡功能实现。
LVS实现负载均衡
LVS实现负载均衡
LVS-NAT模型
环境拓扑

主机IP功能
LVS VIP:192.168.0.105 调度器
LVS DIP:192.168.239.130 调度器
Web1 192.168.239.129 RS
Web2 192.168.239.133 RS

前端负载均衡配置:
LVS实现负载均衡

[root@LVS ~]# ipvsadm -A -t 192.168.0.105:80 -s wrr
[root@LVS ~]# ipvsadm -a -t 192.168.0.105:80 -r 192.168.239.129:80 -m -w 1
[root@LVS ~]# ipvsadm -a -t 192.168.0.105:80 -r 192.168.239.133:80 -m -w 2
# 这样ipvs的规则已经定义完成
# 因为NAT工作模式涉及到地址转换,因此需要修改内核的ip_forward参数
[root@LVS ~]# vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
# 修改完成之后使其生效
[root@LVS ~]# sysctl -p

后端RS的配置:

# 因为NAT的工作模式中,请求数据和回应数据都需要经过调度器,因此需要将后端服务器的默认网关指向调度器的DIP
[root@Web1 ~]# route add default -gw 192.168.239.130
[root@Web2 ~]# route add default -gw 192.168.239.130

测试:
分别配置RS的web服务器,我这里将html文本内容作为后端RS的web内容,

[root@Web1 ~]# curl localhost
This is web1
[root@Web2 ~]# curl localhost
This is web2

然后访问调度的VIP,查看返回的web内容,出现如下图的效果说明负载均衡已经实现。
LVS实现负载均衡

LVS持久连接

HTTP协议是一种无状态的协议,即每次发送请求之后就会马上断开连接。假如这种无状态的协议运用在LVS负载均衡中,就会出现这样的情况,以购物网站为例子,用户浏览一商品并加入购物车,这时候请求被送往RS1,然后就断开连接,之后用户又浏览一商品并加入购物车,这时候请求又被送往RS2,这样用户再次访问购物车的时候,反馈给用户的信息是购物车里只有一件商品(假如请求被调度到RS1或RS2的其中一台),这样肯定是不行的。
解决这种问题的办法是可以利用源地址hash调度算法,当然还可以利用LVS的持久连接。

# 基于上面例子中的NAT模型试验,为其增加持久连接
[root@LVS ~]# ipvsadm -E -t 192.168.0.105:80  -s wrr -p

LVS实现负载均衡
现在规划这样一个场景,客户通过访问VIP发来http请求,需要将80端口的请求和8080端口的请求在一定时间范围内调度到后端同一台服务器上,就是端口联姻。完成这样的需求需要借助防火墙的标记持久连接。为了看到测试的效果,规划这样的环境拓扑:

主机IP备注(或html页面内容)
LVS VIP:192.168.0.105 调度器(NAT)
LVS DIP:192.168.239.130 调度器(NAT)
Web1 192.168.239.129:80 This is web1 with 80
Web1 192.168.239.129:8080 This is web1 with 8080
Web2 192.168.239.133:80 This is web2 with 80
Web2 192.168.239.133:8080 This is web2 with 8080

前端调度器的配置:

# 在防火墙上将VIP的80端口请求和8080端口请求都标记为100
[root@LVS ~]# iptables -F
[root@LVS ~]# iptables -t mangle -A PREROUTING -d 192.168.0.105 -p tcp --dport 80 -j MARK --set-mark 100
[root@LVS ~]# iptables -t mangle -A PREROUTING -d 192.168.0.105 -p tcp --dport 8080 -j MARK --set-mark 100
# 利用标记添加ipvs规则(借助ipvsadm命令的-f选项)
[root@LVS ~]# ipvsadm -C
[root@LVS ~]# ipvsadm -A -f 100 -s wrr -p
[root@LVS ~]# ipvsadm -a -f 100 -r 192.168.239.129 -m -w 1
[root@LVS ~]# ipvsadm -a -f 100 -r 192.168.239.133 -m -w 2

后端RS的配置:

# 开通后端服务器的80端口和8080端口的服务,然后他们各自的访问内容分别如下
[root@Web1 ~]# curl http://localhost:80
This is web1 with 80
[root@Web1 ~]# curl http://localhost:8080
This is web1 with 8080
[root@Web2 ~]# curl http://localhost:80
This is web2 with 80
[root@Web2 ~]# curl http://localhost:8080
This is web2 with 8080
# 因为是NAT的工作模式,因此需要将后端RS的网关指向DIP
[root@Web1 ~]# route add default gw 192.168.239.130
[root@Web2 ~]# route add default gw 192.168.239.130

最后访问VIP的80端口和8080端口,发现请求都会被调度到同一台RS上。
LVS实现负载均衡

LVS健康监测

LVS本身是无法监测后端服务器的状态的,即使后端某台服务器宕机,LVS还是会把请求调度到这台宕机的服务器上边,这样用户就会无法得到响应,这对用户的体验是极差的。因此为LVS加入了后端服务器健康状态检测机制,只有后端正常的服务器才会接受请求。
这里引入一个新的软件包ldirectord,这个软件包会为系统开启一个名叫ldirectord的守护进程,该进程专门用来管理ipvs的规则。该软件的rpm包下载地址如下:
ldirectord-3.9.6(centos6)下载
下载完成之后完成安装即可。安装命令如下:

[root@LVS ~]# yum -y localinstall ldirectord-3.9.6-0rc1.1.1.x86_64.rpm

ldirectord软件包的主配置文件为
  /etc/ha.d/ldirectord.cf
其中软件包中会默认提供一个主配置文件的模板文件供参考,它是
  /usr/share/doc/ldirectord-3.9.6/ldirectord.cf
以实验的LVS-DR模型的环境拓扑为例,这里使用ldirectord定义ipvs的规则,而不再使用ipvsadm命令。ldirectord的主配置文件的主要参数与其意义如下:

checktimeout=5      # 超时时间
checkinterval=1      # 两次检查的时间间隔
autoreload=yes      # 如果ldirectord的配置文件更新,是否主动重读配置文件
logfile="/var/log/ldirectord.log"    # 定义日志文件
quiescent=no        # 当后端某台服务器故障的时候,yes表示将节点的权值降为0,no表示将节点剔除ipvs的规则,当恢复正常后自动恢复值ipvs规则中
virtual=192.168.239.250:80  # 虚拟IP:port
    real=192.168.239.129:80 gate 1  # RS的IP:port+<工作模式>+[权值]
    real=192.168.239.133:80 gate 2
    service=http
    scheduler=wrr    # 调度算法
    #persistent=600
    protocol=tcp
# ldirectord实际上是根据下面参数来具体地监控RS是否正常
    checktype=negotiate  # ldirectord进程监控RS的方法
    checkport=80            # 监控的Port
    request="check.html" # 监控的文件
    receive="This web is OK" # 监控的文件内容

VIP的设置和后端服务器的ARP抑制的相关操作请参考实验的LVS-DR模型,这里不再重写。
在后端的服务器的web根目录下放入监控的文件

[root@Web1 web]# pwd
/data/web
[root@Web1 web]# cat check.html
This web is OK
[root@Web2 web]# pwd
/data/web
[root@Web2 web]# cat check.html
This web is OK

开启ldirectord进程,ipvsadm查看ipvs规则如下
LVS实现负载均衡
现在将后端Web1的监控的页面内容改成其他内容,再次查看ipvs规则,结果如下图。

[root@Web1 web]# pwd
/data/web
[root@Web1 web]# cat check.html
This web is Down

LVS实现负载均衡

Linux公社的RSS地址:https://www.linuxidc.com/rssFeed.aspx

本文永久更新链接地址https://www.linuxidc.com/Linux/2018-08/153443.htm


9

本栏最新