在说LVS的概念之前,先有必要了解一下集群和分布式的概念。
集群:同一个业务系统,部署在多台服务器上。集群中,每一台服务器实现的功能没有差别,数据和代码都是一样的
分布式:一个业务被拆成多个子业务,或者本身就是不同的业务,部署在多台服务器上。分布式中,每一台服务器实现的功能是有差别的,数据和代码也是不一样的,分布式每台服务器功能加起来,才是完整的业务
分布式是以缩短单个任务的执行时间来提升效率的,而集群则是通过提高单位时间内执行的任务数来提升效率。对于大型网站,访问用户很多,实现一个群集,在前面部署一个负载均衡服务器,后面几台服务器完成同一业务。如果有用户进行相应业务访问时,负载均衡器根据后端哪台服务器的负载情况,决定由给哪一台去完成响应,并且一台服务器垮了,其它的服务器可以顶上来。分布式的每一个节点,都完成不同的业务,如果一个节点垮了,那这个业务可能就会失败,而lvs就能解决上面的负载均衡配置,当然除了lvs,nginx、haproxy也都能实现此功能。
LVS,是Linux Virtual Server的简称,也就是Linux虚拟服务器, 是前阿里开源技术委员会主席章文嵩博士发起的自由软件项目。LVS由用户空间的ipvsadm和内核空间的IPVS组成,ipvsadm用来定义规则,IPVS利用ipvsadm定义的规则工作。目前LVS已经被集成到Linux内核模块中。该项目在Linux内核中实现了基于IP的数据请求负载均衡调度方案,其工作结构如下图1所示:
由上图我们可以得到信息,终端互联网用户从外部访问公司的外部负载均衡服务器,终端用户的Web请求会发送给LVS调度器,调度器根据自己预设的算法决定将该请求发送给后端的某台Web服务器,比如,轮询算法可以将外部的请求平均分发给后端的所有服务器,终端用户访问LVS调度器虽然会被转发到后端真实的服务器,但如果真实服务器连接的是相同的存储,提供的服务也是相同的服务,最终用户不管是访问哪台真实服务器,得到的服务内容都是一样的,整个集群对用户而言都是透明的。最后根据LVS工作模式的不同,真实服务器会选择不同的方式将用户需要的数据发送到终端用户,LVS工作模式分为NAT模式、TUN模式、以及DR模式和FULLNAT模式,其中主要常用的为NAT模式和DR模式,DR模式为LVS默认模式。
通过LVS提供的负载均衡技术和Linux操作系统实现一个高性能、高可用的服务器群集,它具有良好可靠性、可扩展性和可操作性。从而以低廉的成本实现最优的服务性能。LVS的主要特点有以下几个方面:
名称 | 解释 |
---|---|
VS | Virtual Server ,虚拟服务 |
Director, Balancer | 负载均衡器、分发器,往往和VS在同一台机器 |
RS | Real Server 后端请求处理服务 |
CIP | 客户端IP地址 |
VIP | Director Virtual IP,负载均衡器虚拟IP |
DIP | Director IP,负载均衡器另一块网卡IP |
RIP | Real Server IP,后端请求处理服务器真实IP |
如上图所示,简述了一次用户请求流程,当用户访问某网站时,访问的地址往往是网站Virtual Server的VIP,请求通过互联网经路由转发到达VS服务器,而VS服务器大多只是调度分发用户的请求,并不直接提供服务响应,真正提供服务响应的是后端的RS真实服务器。
LVS有两种类型的调度算法,其一就是静态的调度算法,这种算法一经实现,后续就不会发生变化,是既定的规则,后续数据包的流转都会按照这种规则进行按部就班的流转;其二就是动态的调度算法,这种算法是基于网络状况,或者后端服务器的状况,连接的状况等来进行实时的调整,算法的规则会根据实际情况而发生一定的变化
四种静态调度算法:
六种动态调度算法
最小连接调度(Least Connections简称’LC’)算法是把新的连接请求分配到当前连接数最小的服务器。最小连接调度是一种动态的调度算法,它通过服务器当前活跃的连接数来估计服务器的情况。调度器需要记录各个服务器已建立连接的数目,当一个请求被调度到某台服务器,其连接数加1;当连接中断或者超时,其连接数减1。
(集群系统的真实服务器具有相近的系统性能,采用最小连接调度算法可以比较好地均衡负载。)
加权最少连接(Weight Least Connections 简称’WLC’)算法是最小连接调度的超集,各个服务器相应的权值表示其处理性能。服务器的缺省权值为1,系统管理员可以动态地设置服务器的权值。加权最小连接调度在调度新连接时尽可能使服务器的已建立连接数和其权值成比例。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。
基于局部的最少连接调度(Locality-Based Least Connections 简称’LBLC’)算法是针对请求报文的目标IP地址的 负载均衡调度,目前主要用于Cache集群系统,因为在Cache集群客户请求报文的目标IP地址是变化的。这里假设任何后端服务器都可以处理任一请求,算法的设计目标是在服务器的负载基本平衡情况下,将相同目标IP地址的请求调度到同一台服务器,来提高各台服务器的访问局部性和Cache命中率,从而提升整个集群系统的处理能力。LBLC调度算法先根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若该服务器是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则使用’最少连接’的原则选出一个可用的服务器,将请求发送到服务器。
带复制的基于局部性的最少连接(Locality-Based Least Connections with Replication 简称’LBLCR’)算法也是针对目标IP地址的负载均衡,目前主要用于Cache集群系统,它与LBLC算法不同之处是它要维护从一个目标IP地址到一组服务器的映射,而LBLC算法维护从一个目标IP地址到一台服务器的映射。按’最小连接’原则从该服务器组中选出一一台服务器,若服务器没有超载,将请求发送到该服务器;若服务器超载,则按’最小连接’原则从整个集群中选出一台服务器,将该服务器加入到这个服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度。
最短的期望的延迟调度(Shortest Expected Delay 简称’SED’)算法基于WLC算法。举个例子吧,ABC三台服务器的权重分别为1、2、3 。那么如果使用WLC算法的话一个新请求进入时它可能会分给ABC中的任意一个。使用SED算法后会进行一个运算
A:(1+1)/1=2 B:(1+2)/2=3/2 C:(1+3)/3=4/3 就把请求交给得出运算结果最小的服务器。
最少队列调度(Never Queue 简称’NQ’)算法,无需队列。如果有realserver的连接数等于0就直接分配过去,不需要在进行SED运算。
程序包:ipvsadm (yum install ipvsadm)
Unit File: ipvsadm.service
主程序:/usr/sbin/ipvsadm
规则保存工具:/usr/sbin/ipvsadm-save
规则重载工具:/usr/sbin/ipvsadm-restore
配置文件:/etc/sysconfig/ipvsadm-config
ipvsadmin命令:
核心功能:
集群服务管理:增、删、改
集群服务的RS管理:增、删、改
查看
配置Virtual Server命令语法:
#添加|修改一条集群服务
ipvsadm -A|E -t|u|f virutal-service-address:port [-s scheduler] [-p[timeout]] [-M netmask]
#删除一条集群服务记录
ipvsadm -D -t|u|f virtual-service-address
#清楚所有记录
ipvsadm -C
#恢复虚拟服务器规则
ipvsadm -R
#保存虚拟服务器规则
ipvsadm -S [-n]
命令选项解释:
-A:添加一个虚拟集群服务
-t:tcp
-u:udp
-f: firewall make 通常应用于将两个或以上的服务绑定为一个服务进行处理时使用
service-address
-t IP:port
-u ip:port
-f firewall_mark
-s 调度算法,默认为wlc
-p: timeout persistent connection 持久连接,默认360s
-E:修改定义过的集群服务
-D -t|u|f service-address:删除指定的集群服务
-R:载入指定的规则,ipvsadmin-restore
-S:保存已定义的ipvsadm规则,ipvsadm-save
配置Real server命令语法:
ipvsadm -a|e -t|u|f service-address:port -r real-server-address:port [-g|i|m] [-w weight]
-a:向指定的CS中添加RS
-e:修改
-t|-u|-f service-address:指明将RS添加至那个Cluster Service 中
-r:指定RS,可以包含{IP[:port]},只有支持端口映射的LVS类型才允许此处使用跟集群服务中不同的端口
lvs类型:
-g: gateway, dr类型,默认
-i: ipip, tun类型
-m: masquerade, nat类型
-w:--weight weight 真实服务器的权值
ipvsadm -d -t|u|f service-address -r server-address
-d:--delete-server 删除一条虚拟服务器记录中的某条真实服务器记录
ipvsadm -Z [-t|u|f service-address]
-Z --zero 虚拟服务表计数器清零(清空当前的连接数量等)
ipvsadm --set tcp tcpfin udp
--set tcp tcpfin udp 设置连接超时值
ipvsadm --stop-daemon
--start-daemon 启动同步守护进程。他后面可以是master 或backup,用来说明LVS Router 是master 或是backup。在这个功能上也可以采keepalived 的VRRP 功能。
--stop-daemon 停止同步守护进程
查看ipvs规则等
-L [options]
-n 使用数字格式显示IP地址,不反解
-c:查看连接数相关信息
--stats:显示统计数据
--rate:数据传输速率
--timeout:显示tcp会话时长
--daemon:守护进程的信息
--sort:对虚拟服务进行排序,默认为升序
--exact:精确显示,不做单位换
通俗的讲,NAT模式就是把用户请求的目标地址由虚拟服务的VIP替换成真实服务的RIP,而这个功能是在VS服务器上通过ipvsadm规则实现的,PS收到请求并作出服务响应给VS,VS又把收到的响应发送给用户,这就是一次请求与响应的全过程,通过下面的图示能更好的帮助大家理解:
通过上图可以发现,Clients发送请求报文的时候,目标地址VIP通过LVS服务器被替换为RIP,源地址没有变;而当RS发送响应报文经过LVS服务器的时候,源地址又被替换为了VIP,目标地址不变,从而我们可以得出结论,在NET模式中,LVS服务只提供了转发与调度的作用,并没有为用户提供真实的服务响应,真正响应用户请求并提供服务的是后端的Real Server。
说清楚概念,就让我们动手来搭建一个LVS-NET模式的测试环境,如下图:
分别准备四台测试机器:
客户端:Clients,CIP:172.18.6.88
LVS服务器:VS,VIP:172.18.6.88; DIP:192.168.131.8
Real Server:RS1,RIP:192.168.131.18
Real Server:RS2,RIP:192.168.131.28
第一步:搭建好网络环境,注意RS服务器的网关要指向VS的DIP
route add default gw 192.168.131.8
第二步:LVS服务配置,(在VS服务器上安装配置)
yum install -y ipvsadm
ipvsadm -A -t 172.18.6.66:80 -s rr #添加集群服务,端口为80,调度算法rr,即轮询
ipvsadm -a -t 172.18.6.66 -r 192.168.131.18:80 #添加集群服务规则,最后还可以跟 -m 权值,权值大的,优先调度
ipvsadm -a -t 172.18.6.66 -r 192.168.131.28:80
ipvsadm -Ln #查看已定义的规则
开启路由转发:
echo 1 > /proc/sys/net/ipv4/ip_forward
vim /etc/sysctl.conf
net.ipv4.ip_forward=1
sysctl -p #加载生效
第三步:在Clients端测试:
curl http://172.18.6.66
NAT模式特性:
1.RS应该使用私有地址
2.RS的网关必须指向DIP
3.RIP和DIP必须在同一网段内
4.请求和响应的报文都得经过Director,在高负载场景中,Director很可能成为性能瓶颈
5.支持端口映射
6.RS可以使用任意支持集群服务的OS
DR模式是LVS服务默认模式,也是大多数企业使用做多的模式,相比较NET模式较难理解,配置也麻烦一下,但是却是必须掌握的模式,其实只要理解了原理和概念,回头来看就没有想象的那么困难了,其实任何事情都是这样,好了言归正传,大家已经了解就NET模式的工作原理,知道无论是用户的请求报文还是RS的响应报文都需要经过VS服务器,而往往响应用户的报文都是很大的,比如一张图片,一段视频,这样在高并发阶段VS服务器的负载时非常大的,这也是NET模式的瓶颈,而DR模式没有高负载的困扰,因为DR模式下RS响应用的报文不再经过VS服务器,而是直接通过路由转发给用户,这样也就大大减轻了VS服务器的负载。
Virtual Server via Direct Routing(VS-DR):用直接路由技术实现虚拟服务器。当参与集群的计算机和作为控制管理的计算机在同一个网段时可以用此方法,控制管理的计算机接收到请求包时直接送到参与集群的节点。直接路由模式比较特别,很难说和什么方面相似,前种模式基本上都是工作在网络层上(三层),而直接路由模式则应该是工作在数据链路层上(二层)。
如上图所示,Director和REAL SERVER都配置同一个IP(VIP),Director将该IP配置到对外的网卡上,Real server将该IP配置到lo网卡上。配置arp_ignore为1(目的是让数据包发出apr请求时,只有Director会响应该arp请求),所有REAL SERVER对本身这个IP的ARP请求保持静默。而Director收到数据包后根据调度算法,找出对应的 REAL SERVER,把目的MAC地址改为REAL SERVER的MAC并发给这台REAL SERVER。这时REAL SERVER通过网卡eth0收到这个数据包,由于Real Server上的lo网卡配置的也有VIP,所以RS接收该数据包。处理后直接返回给客户端(这里要配置arp_announce=2,目的是修改返回数据包的源ip地址。不修改的话,回答数据包源ip地址为VIP,mac为发送网卡的mac即途中的eth0,那么交换机上更新mac表之后,就会发现VIP对应两条mac记录,一条对应Director的mac地址,一条对应Real Server的mac地址。就会使真正的VIP得不到正确的请求了)。由于DR要对二层包头进行改换,所以DR和REAL SERVER之间必须在一个广播域,也可以简单的理解为在同一台交换机上。
相对于NAT模式来言,DR模式能够较好的解决上述问题,其数据在服务器集群中的流向如上图所示,请求报文经过LVS到达后端真实的WEB服务器,而响应报文,则直接发给客户端,并不需要通过调度器。
内核参数详解
arp_ignore:
0:默认值,表示可使用本地任意接口上配置的任意地址进行响应
1: 仅在请求的目标IP配置在本地主机的接收到请求报文的接口上时,才给予响应
arp_announce:
0:默认值,把本机所有接口的所有信息向每个接口的网络进行通告
1:尽量避免将接口信息向非直接连接网络进行通告
2:必须避免将接口信息向非本网络进行通告
所以这里需要把Real Server上的内核参数arp_ignore改为1,不响应一开始交换机上发出的arp寻址,保证请求报文被正确发往LVS服务器;同时也要改arp_announce为2,即不回应,不宣称,隐藏自己的身份在背后默默干活。
DR模式的特性
1、保证前端路由将目标地址为VIP报文统统发给Director Server,而不是RS
2、RS可以使用私有地址;也可以是公网地址,如果使用公网地址,此时可以通过互联网对RIP进行直接访问
3、RS跟Director Server必须在同一个物理网络中
4、所有的请求报文经由Director Server,但响应报文必须不能进过Director Server
5、不支持地址转换,也不支持端口映射
6、RS可以是大多数常见的操作系统
7、RS的网关绝不允许指向DIP
8、RS上的lo接口配置VIP的IP地址
下面让我们来规划搭建DR模式
mac地址转换表
下面通过两个脚本实现DR配置:
在Virtual Server 上运行ipvsadm配置脚本
vim lvs_dr_vs.sh
#!/bin/bash
vip='192.168.131.100'
iface='lo:1'
mask='255.255.255.255'
port='80'
rs1='192.168.131.28'
rs2='192.168.131.38'
scheduler='rr'
type='-g'
rpm -q ipvsadm &> /dev/null || yum -y install ipvsadm &> /dev/null
case $1 in
start)
ifconfig $iface $vip netmask $mask #broadcast $vip up
iptables -F
ipvsadm -A -t ${vip}:${port} -s $scheduler
ipvsadm -a -t ${vip}:${port} -r ${rs1} $type -w 1
ipvsadm -a -t ${vip}:${port} -r ${rs2} $type -w 1
echo "The VS Server is Ready!"
;;
stop)
ipvsadm -C
ifconfig $iface down
echo "The VS Server is Canceled!"
;;
*)
echo "Usage: $(basename $0) start|stop"
exit 1
;;
esac
bash lvs_dr_vs.sh start #start 开始运行配置,stop 清空配置
在Real Server 分别运行lo网卡和arp内核配置脚本:
vim lvs_dr_rs.sh
#!/bin/bash
vip=192.168.131.100
mask='255.255.255.255'
dev=lo:1
rpm -q httpd &> /dev/null || yum -y install httpd &>/dev/null
service httpd start &> /dev/null && echo "The httpd Server is Ready!"
echo "`hostname`
" > /var/www/html/index.html
case $1 in
start)
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
ifconfig $dev $vip netmask $mask #broadcast $vip up
#route add -host $vip dev $dev
echo "The RS Server is Ready!"
;;
stop)
ifconfig $dev down
echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo "The RS Server is Canceled!"
;;
*)
echo "Usage: $(basename $0) start|stop"
exit 1
;;
esac
bash lvs_dr_rs.sh start #start 开始运行配置,stop 清空配置
#不过不得不记录一下这里的一些坑,当VIP设置的DIP在同一网段是,在LVS服务器上VIP可以绑在lo回环网卡上也可以和DIP绑在同一张网卡上;当DIP和VIP
#不在相同网段是,比如10.0.0.100,在RS上依旧绑定在lo回环网卡上子网掩码为32,在LVS上VIP也可以绑在和DIP相同的网卡上,子网掩码可以是24或32,
#但是绑定在lo回环网卡子网掩码上必须是32。注意LVS服务器上路由必须要指,只要指向和VIP或者DIP相同网段就行,RS1和RS2必须要网关指向r2
这些规则会在服务器重启后丢失,不过可以添加为开机运行:
chmod +x lvs_dr_vs.sh
vim /etc/rc.d/rc.local
/lvs_dr_vs.sh #必须要写绝对路径,RS上设置开机运行和这里一样
在我们搭建的lvs调度web服务的测试中,用户的请求报文必须经过LVS服务器,进而通过设定的IPVS规则再被调度到Real Server上进行处理响应,但是LVS服务器只要一台,一旦宕机用户将无法再发出任何请求,而如果配置两台多台LVS服务,交换机进行ARP寻址到时候会收到两台或多台LVS机器的回应,交换机不知道到底要把用户请求的报文交给谁,导致请求失败超时等问题。
而keepalived技术可以很好的解压上面的问题,我们可以把VIP设置为keepalived的虚拟ip,并配置主从两台LVS服务器,当服务正常运行的时候,vip绑定在masterLVS上,一旦master出现故障不能再提供调度服务,vip将自动绑定到从服务器上,继续提供LVS调度服务,可以很好的解决了单点失败的问题,而且也提供健康性检查服务,如果Real Server全部不能再提高服务,keepalived将向用户道歉,但是只要如果想要在RS都出现故障后有LVS向用户提供服务,LVS服务器的网关要指向路由器,即r2…
下面我们就在测试环境下部署实现:
#主服务MASTER上:
vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.0 #邮箱地址
smtp_connect_timeout 30
router_id ka1
vrrp_mcast_group4 224.88.88.88 #多播地址
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 88 #虚拟路由id,主从必须填写一致,范围0-255
priority 120 #优先级,主必须要比从的大,范围1-254
advert_int 1 #多播通告间隔
authentication {
auth_type PASS
auth_pass abcdef #连接认证,主从必须填写一致,否则无法连接
}
virtual_ipaddress {
192.168.131.100/24 dev ens33 label ens33:1 #vip地址,绑定在某网卡上
}
}
virtual_server 192.168.131.100 80 { #虚拟主机vip设定
delay_loop 6 #检查后端服务器的时间间隔
lb_algo rr #定义调度方法
lb_kind DR #集群的类型
protocol TCP #服务协议,仅支持TCP
sorry_server 127.0.0.1 80 #所有RS故障时,备用服务器地址,一般在道歉服务
real_server 192.168.131.88 80 { #Real Server地址
weight 1
HTTP_GET {
url {
path / #定义要监控的URL
status_code 200 #判断上述检测机制为健康状态的响应码
}
connect_timeout 2 #连接请求的超时时长
nb_get_retry 3 #重试次数
delay_before_retry 3 #重试之前的延迟时长
}
}
real_server 192.168.131.8 80 { #另一台Real Server地址配置
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 2
nb_get_retry 3
delay_before_retry 3
}
}
}
#从服务器BACKUP上:
vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.0
smtp_connect_timeout 30
router_id ka2
vrrp_mcast_group4 224.88.88.88
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 88
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass abcdef
}
virtual_ipaddress {
192.168.131.100/24 dev eth0 label eth0:1
}
}
virtual_server 192.168.131.100 80 {
delay_loop 6
lb_algo rr
lb_kind DR
protocol TCP
sorry_server 127.0.0.1 80
real_server 192.168.131.88 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 2
nb_get_retry 3
delay_before_retry 3
}
}
real_server 192.168.131.8 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 2
nb_get_retry 3
delay_before_retry 3
}
}
}
keepalived服务配置完成后,开启服务:systemctl start keepalived
LVS服务器上不需要再写ipvsadm规则,但是在Real Server上依旧要运行lvs_dr_rs.sh脚本进行配置
由于本人水平有限和时间仓促,本实验还有很多不足和理解不深的步骤和原理,望大佬们多多指出,感激不尽……