一.LVS是什么?
LVS的英文全称是Linux Virtual Server,即Linux虚拟服务器。它是我们国家的章文嵩博士的一个开源项目。在linux内存2.6中,它已经成为内核的一部分,在此之前的内核版本则需要重新编译内核。
二.LVS能干什么?
LVS主要用于多服务器的负载均衡。它工作在网络层,可以实现高性能,高可用的服务器集群技术。它廉价,可把许多低性能的服务器组合在一起形成一个超级服务器。它易用,配置非常简单,且有多种负载均衡的方法。它稳定可靠,即使在集群的服务器中某台服务器无法正常工作,也不影响整体效果。另外可扩展性也非常好。
三.工作原理
如上图,LVS可分为三部分:
1.Load Balancer:这是LVS的核心部分,它好比我们网站MVC模型的Controller。它负责将客户的请求按照一定的算法分发到下一层不同的服务器进行处理,自己本身不做具体业务的处理。另外该层还可用监控下一层的状态,如果下一层的某台服务器不能正常工作了,它会自动把其剔除,恢复后又可用加上。该层由一台或者几台Director Server组成。
2.Server Array:该层负责具体业务。可有WEB Server、mail Server、FTP Server、DNS Server等组成。注意,其实上层的Director Server也可以当Real server用的。
3.Shared Storage:主要是提高上一层数据和为上一层保持数据一致。
四.负载均衡机制
前面我们说了LVS是工作在网络层。相对于其它负载均衡的解决办法,比如DNS域名轮流解析、应用层负载的调度、客户端的调度等,它的效率是非常高的。LVS的通过控制IP来实现负载均衡。IPVS是其具体的实现模块。IPVS的主要作用:安装在Director Server上面,在Director Server虚拟一个对外访问的IP(VIP)。用户访问VIP,到达Director Server,Director Server根据一定的规则选择一个Real Server,处理完成后然后返回给客户端数据。这些步骤产生了一些具体的问题,比如如何选择具体的Real Server,Real Server如果返回给客户端数据等等。IPVS为此有三种机制:
1.VS/NAT(Virtual Server via Network Address Translation),即网络地址翻转技术实现虚拟服务器。当请求来到时,Diretor server上处理的程序将数据报文中的目标地址(即虚拟IP地址)改成具体的某台Real Server,端口也改成Real Server的端口,然后把报文发给Real Server。Real Server处理完数据后,需要返回给Diretor Server,然后Diretor server将数据包中的源地址和源端口改成VIP的地址和端口,最后把数据发送出去。由此可以看出,用户的请求和返回都要经过Diretor Server,如果数据过多,Diretor Server肯定会不堪重负。
2.VS/TUN(Virtual Server via IP Tunneling),即IP隧道技术实现虚拟服务器。它跟VS/NAT基本一样,但是Real server是直接返回数据给客户端,不需要经过Diretor server,这大大降低了Diretor server的压力。
3.VS/DR(Virtual Server via Direct Routing),即用直接路由技术实现虚拟服务器。跟前面两种方式,它的报文转发方法有所不同,VS/DR通过改写请求报文的MAC地址,将请求发送到Real Server,而Real Server将响应直接返回给客户,免去了VS/TUN中的IP隧道开销。这种方式是三种负载调度机制中性能最高最好的,但是必须要求Director Server与Real Server都有一块网卡连在同一物理网段上。
五.负载调度算法
前面我们都知道Director Server要选择不同的Real server,那么它具体的如果选择Real Server以达到负载均衡的呢,IPVS实现了八种调度方法,具体算法可以查看官网或者百度,这里就不一一列出了。官网:www.linuxvirtualserver.org。
安装配置
工作方式:
NAT模型其实就是通过网络地址转换来实现负载均衡的。下面是它的流程
1.用户请求VIP(也可以说是CIP请求VIP) 2,Director Server 收到用户的请求后,发现源地址为CIP请求的目标地址为VIP,那么Director Server会认为用户请求的是一个集群服务,那么Director Server 会根据此前设定好的调度算法将用户请求负载给某台Real Server。 假如说此时Director Server 根据调度的结果会将请求分摊到RealServer1上去,那么Director Server 会将用户的请求报文中的目标地址,从原来的VIP改为RealServer1的IP,然后再转发给RealServer1 3,此时RealServer1收到一个源地址为CIP目标地址为自己的请求,那么RealServer1处理好请求后会将一个源地址为自己目标地址为CIP的数据包通过Director Server 发出去, 4.当Driector Server收到一个源地址为RealServer1 的IP 目标地址为CIP的数据包,此时Driector Server 会将源地址修改为VIP,然后再将数据包发送给用户
LVS-NAT的性能瓶颈:
在LVS/NAT的集群系统中,请求和响应的数据报文都需要通过负载调度器(Director),当真实服务器(RealServer)的数目在10台和20台之间时,负载调度器(Director)将成为整个集群系统的新瓶颈。
大多数Internet服务都有这样的特点:请求报文较短而响应报文往往包含大量的数据。如果能将请求和响应分开处理,即在负载调度器(Director)中只负责调度请求而响应直接(RealServer)返回给客户,将极大地提高整个集群系统的吞吐量。
部署
在RealServer上部署httpd服务并测试
两台RealServer上安装httpd
[root@localhost conf]# yum -y install httpd [root@localhost conf]# service httpd restart [root@localhost ~]# echo "RS1-web1 Allentuns.com" > /var/www/html/index.html 第一台RealServer [root@localhost conf]# echo "RS2-web2 Allentuns.com" > /var/www/html/index.html 第二台RealServer #测试httpd服务是否OK! [root@localhost ~]# curl http://localhost RS1-web1 Allentuns.com [root@localhost conf]# curl http://localhost RS2-web2 Allentuns.com
在Director上部署ipvs服务并测试
添加集群服务
[root@localhost ~]# ipvsadm -A -t 192.168.1.205:80 -s rr #定义一个集群服务 [root@localhost ~]# ipvsadm -a -t 192.168.1.205:80 -r 192.168.1.202 -m #添加RealServer并指派调度算法为NAT [root@localhost ~]# ipvsadm -a -t 192.168.1.205:80 -r 192.168.1.203 -m #添加RealServer并指派调度算法为NAT [root@localhost ~]# ipvsadm -L -n #查看ipvs定义的规则列表 IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.1.205:80 rr -> 192.168.1.202:80 Masq 1 0 0 -> 192.168.1.203:80 Masq 1 0 0 [root@localhost ~]# [root@localhost ~]# cat /proc/sys/net/ipv4/ip_forward #查看Linux是否开启路由转发功能 0 [root@localhost ~]# echo 1 > /proc/sys/net/ipv4/ip_forward #启动Linux的路由转发功能 [root@localhost ~]# cat /proc/sys/net/ipv4/ip_forward 1
测试访问http页面
[root@localhost ~]# curl http://192.168.1.205/index.html RS2-web2 Allentuns.com [root@localhost ~]# curl http://192.168.1.205/index.html RS1-web1 Allentuns.com [root@localhost ~]# curl http://192.168.1.205/index.html RS2-web2 Allentuns.com [root@localhost ~]# curl http://192.168.1.205/index.html RS1-web1 Allentuns.com [root@localhost ~]# curl http://192.168.1.205/index.html RS2-web2 Allentuns.com [root@localhost ~]# curl http://192.168.1.205/index.html RS1-web1 Allentuns.com [root@localhost ~]# curl http://192.168.1.205/index.html RS2-web2 Allentuns.com
更改LVS的调度算法并压力测试,查看结果
[root@localhost ~]# ipvsadm -C [root@localhost ~]# ipvsadm -a -t 192.168.1.205:80 -r 192.168.1.202 -m -w 3 [root@localhost ~]# ipvsadm -a -t 192.168.1.205:80 -r 192.168.1.203 -m -w 1 [root@localhost ~]# ipvsadm -L -n IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.1.205:80 wrr -> 192.168.1.202:80 Masq 3 0 0 -> 192.168.1.203:80 Masq 1 0 0
[root@localhost ~]# curl http://192.168.1.205/index.html RS2-web2 Allentuns.com [root@localhost ~]# curl http://192.168.1.205/index.html RS1-web1 Allentuns.com [root@localhost ~]# curl http://192.168.1.205/index.html RS1-web1 Allentuns.com [root@localhost ~]# curl http://192.168.1.205/index.html RS1-web1 Allentuns.com [root@localhost ~]# curl http://192.168.1.205/index.html RS2-web2 Allentuns.com [root@localhost ~]# curl http://192.168.1.205/index.html RS1-web1 Allentuns.com [root@localhost ~]# curl http://192.168.1.205/index.html RS1-web1 Allentuns.com
永久保存LVS规则并恢复
[root@localhost ~]# ipvsadm -S > /etc/sysconfig/ipvsadm.s1 [root@localhost ~]# ls /etc/sysconfig/ipvsadm.s1 /etc/sysconfig/ipvsadm.s1
模拟清空ipvsadm规则来恢复
[root@localhost ~]# ipvsadm -C [root@localhost ~]# ipvsadm -L -n IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn [root@localhost ~]# ipvsadm -R < /etc/sysconfig/ipvsadm.s1 [root@localhost ~]# ipvsadm -L -n IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 127.0.0.1:80 wrr -> 192.168.1.202:80 Masq 3 0 0 -> 192.168.1.203:80 Masq 1 0 0
脚本
LVS-NAT服务控制脚本部署在Director上
#!/bin/bash # # chkconfig: - 88 12 # description: LVS script for VS/NAT # . /etc/rc.d/init.d/functions # VIP=192.168.0.200 DIP=172.16.100.1 RIP1=172.16.100.10 RIP2=172.16.100.11 # case "$1" in start) # /sbin/ifconfig eth1:0 $VIP netmask 255.255.255.0 up # Since this is the Director we must be able to forward packets echo 1 > /proc/sys/net/ipv4/ip_forward # Clear all iptables rules. /sbin/iptables -F # Reset iptables counters. /sbin/iptables -Z # Clear all ipvsadm rules/services. /sbin/ipvsadm -C # Add an IP virtual service for VIP 192.168.0.219 port 80 # In this recipe, we will use the round-robin scheduling method. # In production, however, you should use a weighted, dynamic scheduling method. /sbin/ipvsadm -A -t $VIP:80 -s rr # Now direct packets for this VIP to # the real server IP (RIP) inside the cluster /sbin/ipvsadm -a -t $VIP:80 -r $RIP1 -m /sbin/ipvsadm -a -t $VIP:80 -r $RIP2 -m /bin/touch /var/lock/subsys/ipvsadm.lock ;; stop) # Stop forwarding packets echo 0 > /proc/sys/net/ipv4/ip_forward # Reset ipvsadm /sbin/ipvsadm -C # Bring down the VIP interface ifconfig eth1:0 down rm -rf /var/lock/subsys/ipvsadm.lock ;; status) [ -e /var/lock/subsys/ipvsadm.lock ] && echo "ipvs is running..." || echo "ipvsadm is stopped..." ;; *) echo "Usage: $0 {start|stop}" ;; esac lvs-nat-director.sh lvs-nat-director.sh
分享LVS-NAT一键安装脚本
#!/bin/bash # # 一键安装lvs-nat脚本,需要注意的是主机名成和ip的变化稍作修改就可以了 HOSTNAME=`hostname` Director='LVS' VIP="192.168.0.200" RIP1="172.16.100.10" RIP2="172.16.100.11" RealServer1="web1" RealServer2="web2" Httpd_config="/etc/httpd/conf/httpd.conf" #Director Server Install configure ipvsadm if [ "$HOSTNAME" = "$Director" ];then ipvsadm -C yum -y remove ipvsadm yum -y install ipvsadm /sbin/ipvsadm -A -t $VIP:80 -s rr /sbin/ipvsadm -a -t $VIP:80 -r $RIP1 -m /sbin/ipvsadm -a -t $VIP:80 -r $RIP2 -m echo 1 > /proc/sys/net/ipv4/ip_forward echo "========================================================" echo "Install $Director sucess Tel:13260071987 Qq:467754239" echo "========================================================" fi #RealServer Install htpd if [ "$HOSTNAME" = "$RealServer1" ];then yum -y remove httpd rm -rf /var/www/html/index.html yum -y install httpd echo "web1 Allentuns.com" > /var/www/html/index.html sed -i '/#ServerName www.example.com:80/a\ServerName localhost:80' $Httpd_config service httpd start echo "========================================================" echo "Install $RealServer1 success Tel:13260071987 Qq:467754239" echo "========================================================" fi if [ "$HOSTNAME" = "$RealServer2" ];then yum -y remove httpd rm -rf /var/www/html/index.html yum -y install httpd echo "web2 Allentuns.com" > /var/www/html/index.html sed -i '/#ServerName www.example.com:80/a\ServerName localhost:80' $Httpd_config service httpd start echo "Install $RealServer2" echo "=========================================================" echo "Install $RealServer1 success Tel:13260071987 Qq:467754239" echo "=========================================================" fi lvs-nat-install lvs-nat-install.sh
LVS-DR:直接路由
工作方式:
上面说了NAT模型的实现方式,那么NAT模型有个缺陷,因为进出的每个数据包都要经过Director Server,当集群系统负载过大的时候Director Server将会成为整个集群系统的瓶颈,
那么DR模型就避免了这样的情况发生,DR模型在只有请求的时候才会经过Director Server, 回应的数据包由Real Server 直接响应用户不需要经过Director Server,其实三种模型中最常用的也就是DR模型了。
下面是它的工作流程:
1, 首先用户用CIP请求VIP 2, 根据上图可以看到,不管是Director Server还是Real Server上都需要配置VIP,那么当用户请求到达我们的集群网络的前端路由器的时候,请求数据包的源地址为CIP目标地址为VIP, 此时路由器会发广播问谁是VIP,那么我们集群中所有的节点都配置有VIP,此时谁先响应路由器那么路由器就会将用户请求发给谁,这样一来我们的集群系统是不是没有意义了, 那我们可以在网关路由器上配置静态路由指定VIP就是Director Server,或者使用一种机制不让Real Server 接收来自网络中的ARP地址解析请求,这样一来用户的请求数据包都会经过Director Servrer 3,当Director Server收到用户的请求后根据此前设定好的调度算法结果来确定将请求负载到某台Real Server上去,假如说此时根据调度算法的结果,会将请求负载到RealServer 1上面去, 此时Director Server 会将数据帧中的目标MAC地址修改为Real Server1的MAC地址,然后再将数据帧发送出去 4,当Real Server1 收到一个源地址为CIP目标地址为VIP的数据包时,Real Server1发现目标地址为VIP,而VIP是自己,于是接受数据包并给予处理,当Real Server1处理完请求后, 会将一个源地址为VIP目标地址为CIP的数据包发出去,此时的响应请求就不会再经过Director Server了,而是直接响应给用户。
编辑DR有三种方式(目的是让用户请求的数据都通过Director Server)
第一种方式:在路由器上明显说明vip对应的地址一定是Director上的MAC,只要绑定,以后再跟vip通信也不用再请求了,这个绑定是静态的,所以它也不会失效,也不会再次发起请求,但是有个前提,我们的路由设备必须有操作权限能够绑定MAC地址,万一这个路由器是运行商操作的,我们没法操作怎么办?第一种方式固然很简便,但未必可行。
第二种方式:在给别主机上(例如:红帽)它们引进的有一种程序arptables,它有点类似于iptables,它肯定是基于arp或基于MAC做访问控制的,很显然我们只需要在每一个real server上定义arptables规则,如果用户arp广播请求的目标地址是本机的vip则不予相应,或者说相应的报文不让出去,很显然网关(gateway)是接受不到的,也就是director相应的报文才能到达gateway,这个也行。第二种方式我们可以基于arptables。
第三种方式:在相对较新的版本中新增了两个内核参数(kernelparameter),第一个是arp_ignore定义接受到ARP请求时的相应级别;第二个是arp_announce定义将自己地址向外通告是的通告级别。【提示:很显然我们现在的系统一般在内核中都是支持这些参数的,我们用参数的方式进行调整更具有朴实性,它还不依赖于额外的条件,像arptables,也不依赖外在路由配置的设置,反而通常我们使用的是第三种配置】
arp_ignore:定义接受到ARP请求时的相应级别
0:只要本地配置的有相应地址,就给予响应。 1:仅在请求的目标地址配置请求到达的接口上的时候,才给予响应(当别人的arp请求过来的时候,如果接收的设备上面没有这个ip,就不响应,默认是0,只要这台机器上面任何一个设备上面有这个ip,就响应arp请求,并发送MAC地址应答。) 2:只回答目标IP地址是来访网络接口本地地址的ARP查询请求,且来访IP必须在该网络接口的子网段内 3:不回应该网络界面的arp请求,而只对设置的唯一和连接地址做出回应 4-7:保留未使用 8:不回应所有(本地地址)的arp查询
arp_announce:定义将自己地址向外通告是的通告级别;
在Real Server1 和Real Server2上做以下配置
[root@localhost ~]# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore [root@localhost ~]# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce [root@localhost ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore [root@localhost ~]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce #以上命令需填加到/etc/rc.local文件中让其开机自动生效 [root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-lo:0 DEVICE=lo:0 IPADDR=192.168.1.229 NETMASK=255.255.255.255 BROADCAST=172.16.100.100 ONBOOT=yes NAME=loopback [root@localhost ~]# ifdown lo:0 [root@localhost ~]# ifup lo:0 [root@localhost ~]# route add -host 192.168.1.229 dev lo:0 [root@localhost ~]# echo "route add -host 192.168.1.229 dev lo:0" >> /etc/rc.local [root@localhost ~]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 192.168.1.229 0.0.0.0 255.255.255.255 UH 0 0 0 lo 192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth0 0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth0
在Director Server上做以下配置
[root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-ens33:0 DEVICE=ens33:0 IPADDR=192.168.1.229 NETMASK=255.255.255.255 BROADCAST=192.168.1.229 ONBOOT=yes
[root@localhost ~]# ifdown ens33:0 [root@localhost ~]# ifup ens33:0 [root@localhost ~]# route add -host 192.168.1.229 dev ens33 [root@localhost ~]# echo "route add -host 192.168.1.229 dev ens33:0" >> /etc/rc.local [root@localhost ~]# echo "1" > /proc/sys/net/ipv4/ip_forward [root@localhost ~]# echo "echo "1" > /proc/sys/net/ipv4/ip_forward" >> /etc/rc.local [root@localhost ~]# ipvsadm -C [root@localhost ~]# ipvsadm -A -t 192.168.1.229:80 -s wlc [root@localhost ~]# ipvsadm -a -t 192.168.1.229:80 -r 192.168.1.202 -g -w 2 [root@localhost ~]# ipvsadm -a -t 192.168.1.229:80 -r 192.168.1.203 -g -w 1
测试
[root@localhost ~]# curl http://192.168.1.229/index.html RS1-web1 Allentuns.com [root@localhost ~]# curl http://192.168.1.229/index.html RS1-web1 Allentuns.com [root@localhost ~]# curl http://192.168.1.229/index.html RS2-web2 Allentuns.com [root@localhost ~]# curl http://192.168.1.229/index.html RS2-web2 Allentuns.com [root@localhost ~]# curl http://192.168.1.229/index.html RS1-web1 Allentuns.com [root@localhost ~]# curl http://192.168.1.229/index.html RS1-web1 Allentuns.com [root@localhost ~]# curl http://192.168.1.229/index.html RS2-web2 Allentuns.com [root@localhost ~]# curl http://192.168.1.229/index.html RS1-web1 Allentuns.com [root@localhost ~]# curl http://192.168.1.229/index.html RS1-web1 Allentuns.com [root@localhost ~]# curl http://192.168.1.229/index.html RS2-web2 Allentuns.com
LVS-TUN:隧道
工作方式:
TUN的工作机制跟DR一样,只不过在转发的时候,它需要重新包装IP报文。这里的real server(图中为RIP)离得都比较远。
用户请求以后,到director上的VIP上,它跟DR模型一样,每个realserver上既有RIP又有VIP,Director就挑选一个real server进行响应,但director和real server并不在同一个网络上,这时候就用到隧道了,Director进行转发的时候,一定要记得CIP和VIP不能动。
我们转发是这样的,让它的CIP和VIP不动,在它上面再加一个IP首部,再加的IP首部源地址是DIP,目标地址的RIP的IP地址。收到报文的RIP,拆掉报文以后发现了里面还有一个封装,它就知道了,这就是隧道。
其实数据转发原理和DR是一样的,不过这个我个人认为主要是位于不同位置(不同机房);LB是通过隧道进行了信息传输,虽然增加了负载,可是因为地理位置不同的优势,还是可以参考的一种方案;
优点:负载均衡器只负责将请求包分发给物理服务器,而物理服务器将应答包直接发给用户。所以,负载均衡器能处理很巨大的请求量,这种方式,一台负载均衡能为超过100台的物理服务器服务,负载均衡器不再是系统的瓶颈。 使用VS-TUN方式,如果你的负载均衡器拥有100M的全双工网卡的话,就能使得整个Virtual Server能达到1G的吞吐量。 不足:但是,这种方式需要所有的服务器支持"IP Tunneling"(IP Encapsulation)协议;
LVS的健康状态检查
在LVS模型中,director不负责检查RS的健康状况,这就使得当有的RS出故障了,director还会将服务请求派发至此服务器,这种情况对用户、企业都是很不爽的,哪个用户倒霉说不定就遇到类似了。
为了让Director更人性化、可靠还要给director提供健康检查功能;如何实现?Director没有自带检查工具,只有手动编写脚本给director实现健康状态检查功能!
#!/bin/bash # VIP=172.16.100.100 CPORT=80 FAIL_BACK=127.0.0.1 RS=("172.16.100.10" "172.16.100.11") declare -a RSSTATUS RW=("2" "1") RPORT=80 TYPE=g CHKLOOP=3 LOG=/var/log/ipvsmonitor.log addrs() { ipvsadm -a -t $VIP:$CPORT -r $1:$RPORT -$TYPE -w $2 [ $? -eq 0 ] && return 0 || return 1 } delrs() { ipvsadm -d -t $VIP:$CPORT -r $1:$RPORT [ $? -eq 0 ] && return 0 || return 1 } checkrs() { local I=1 while [ $I -le $CHKLOOP ]; do if curl --connect-timeout 1 http://$1 &> /dev/null; then return 0 fi let I++ done return 1 } initstatus() { local I local COUNT=0; for I in ${RS[*]}; do if ipvsadm -L -n | grep "$I:$RPORT" && > /dev/null ; then RSSTATUS[$COUNT]=1 else RSSTATUS[$COUNT]=0 A++ Dir[0]=$A fi let COUNT++ done } initstatus while :; do let COUNT=0 for I in ${RS[*]}; do if checkrs $I; then if [ ${RSSTATUS[$COUNT]} -eq 0 ]; then addrs $I ${RW[$COUNT]} [ $? -eq 0 ] && RSSTATUS[$COUNT]=1 && echo "`date +'%F %H:%M:%S'`, $I is back." >> $LOG fi else if [ ${RSSTATUS[$COUNT]} -eq 1 ]; then delrs $I [ $? -eq 0 ] && RSSTATUS[$COUNT]=0 && echo "`date +'%F %H:%M:%S'`, $I is gone." >> $LOG fi fi let COUNT++ done sleep 5 done check-lvs-health.sh check-lvs-health.sh
来源:https://www.cnblogs.com/liujunjun/p/12013526.html