当数据从客户端出来时,经过cdn再经过四层负载均衡,这里就说说四层负载均衡。
负载均衡可以由硬件提供(F5负载均衡),也可以时由软件提供(lvs haproxy varnish nginx httpd)
从工作协议来说:
传输层(四层)负载均衡均衡一般由lvs haproxy(TCP协议)来做。针对ip地址划分。
应用层(七层)负载均衡一般由nginx,haproxy(可以做读写分离,动静分离)。针对应用给划分。
f5硬件负载均衡加格昂贵,性能强,常被用于超大型企业。
LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统。
LVS集群采用IP负载均衡技术和基于内容请求分发技术(cdn)。调度器具有很好的吞吐率,将请求均衡地转移到不同的服务器上执行,且调度器自动屏蔽掉服务器的故障,从而将一组服务器构成一个高性能的、高可用的虚拟服务器。整个服务器集群的结构对客户是透明的,而且无需修改客户端和服务器端的程序。为此,在设计时需要考虑系统的透明性、可伸缩性、高可用性和易管理性。
lvs工作在防火墙的input链.
lvs四种模式:
DR模式(最常用),NAT模式,TUNNLE(隧道)模式,FULLNAT模式(已经很久没有更新)
lvs的两个组件:ipvs和ipvsadm
ipvs是真正起作用的组件(内核空间的一段代码),是lvs的核心!
ipvsadm是调度策略的编写工具。
ipvs工作在input链上!当客户端的数据请求到达调度服务器,数据首先进入内核空间,preruting链会判断确定访问的ip是否为本机,确定访问目标是本机后将请求交给input链(ipvs),
ipvs会把用户的请求和定义好的真实服务器集群进行比对,若用户请求就是所定义的后端服务,ipvs就会强行修改数据包的目的IP地址,端口等,对数据包进行更新,再发往postroting链,postroting链检查到目标ip为后端服务器,再将请求转发给后端服务器。
首先安装ipvsadm(lvs策略编辑工具)
和防火墙类似,可以使用ipvsadm -l
(ipvsadm -ln
不解析)列出当前存在的规则:
当前没有任何规则。
可以 使用命令lsmod来显示已经加载到内核总的模块的状态信息:
配置文件:/etc/sysconfig/ipvsadm-config
重启时报错:
查看日志:
缺少/etc/sysconfig/ipvsadm文件,手动建立此文件后再次重启:
重启成功!
使用 ipvsadm -h
查看编辑策略的方法:
编辑策略:
添加虚拟服务器:
-A表示添加虚拟服务 -t指定虚拟服务器地址,-s指定调度算法 ,rr为轮询。
虚拟服务器也就是公网ip,客户可通过此ip找到服务器,相当与一个入口,不提供真实服务,当客户端数据到达时,会通过调度算法将客户端请求转发给后端真实服务器来处理客户请求。
添加真实服务器(两台):
-a 添加真实服务器,-r 指定真实服务器地址,-g 表示使用DR(直接路由模式)
DR模式的数据走向:
客户端发出请求到达调度器,请求的数据包到达调度器的内核空间,再到preruting链(此时的客户端请求报文为cip:vip),preruting链检查请求目的地是否为本机,如果是本机,将数据包发送到input链,此时工作在input链上的ipvs生效,ipvs对比请求的数据包的服务是否为后端定义的服务集群,如果是,将请求报文中的源mac地址修改为调度器的mac地址,将目标mac地址修改为后端服务器的mac地址(cmac:dmac------>dmac:rmac)
再将数据包发送到postruting链(此时源ip和目的地ip并没有做修改,为cip:vip),又因为调度服务器和真实服务器处在同一网络中,(DR模式的要求)通过二层进行传输,postruting链检查到mac地址为dmac:rmac,数据包发送到真实服务器,真实服务器检查到请求报文中的目的地mac地址为自己的mac地址,对数据包进行接受并处理,处理完成后再通过本机的回环接口lo将数据包发送给出口网卡设备(ens33),网卡设备将数据包发出(此时的ip为vip:cip),客户端进行接受(自始至终没有修改ip),
策略编辑完后,重启ipvsadm,使之保存到/etc/sysconfig/ipvsadm中(配置过):
此时策略就编写完成了,对于我们指定的虚拟ip,我们要将其加到调度器的网卡设备上(localhost),使之能够被访问。
ip addr add 192.160.0.90/24 dev ens33 给调度器localhost添加虚拟ip
此时若是进行访问测试可以发现以下问题:
客户端访问虚拟ip,但无返回数据,调度成功:
访问时,会卡在这里。
查看ipvsadm策略:
可以看到调度是成功的!
没那么问题出在哪里?
其实,客户访问调度器是没有问题的,调度器将请求调度给真实服务器也是没有问题的,问题出在真实服务器返回结果给客户端。
lvm的DR模式数据走向:
数据由客户端发出—>数据到达虚拟服务器经调度算法调度—>数据被调度到真实厚点服务器进行请求处理----->请求处理完成后由后端真实服务器直接返回给客户端---->数据回到客户端
所以,客户端访问的服务器地址为虚拟服务器ip,再由虚拟服务器的ip去转发给真实客户端。而数据的返回是由真实服务器直接返回给客户端。当真实主机进行数据返回时,将数据返回给虚拟ip:192.168.0.90,此时真实主机发现此ip并不是客户端ip,所以就卡在那里,获取不到返回的结果信息。
用户能够接收到虚拟ip(公网ip)的数据包,不能直接接受真实服务器(内网ip)的数据包。所以可以将公网ip(192.168.0.90
)同样加在真实服务器上进行请求结果的返回:
再次访问,问题即得到解决:
但是又有新的问题,可以看到,我们访问时,并没有轮询去访问两台服务器。
在客户端使用arp -an | grep 90
命令显示访问的i虚拟ip对应的MAC地址。使用arp -d 192.168.0.90
可以清除对此ip的mac地址的缓存可以看到每次缓存的并不固定,在真实在服务器和虚拟主机之间切换
导致这个问题的原因是什么呢?可以发现,此时我们的虚拟ip同时存在真实后端服务器和虚拟服务器上,当我们对虚拟ip进行访问时,根本无法确定是否访问到真实后端服务器或者访问到的时虚拟服务器。而直接访问到后端真实服务器是不被允许的,且是非常危险的。所以必须使客户端的数据经过调度器到达真实服务器,真实服务器上的vip对于请求不做响应。
对于此问题,两种解决方法:
配置内核参数和设置火墙L:
使用配置火墙来实现:
因为是根据IP地址获取到mac地址,所以这里使用的是地址解析协议Address Resolution Protocal(ARP)
在后端服务器上安装arptables对策略进行编辑:
对arptables进行规则的配置:
server1:
arptables -A INPUT -d 192.168.0.90 -j DROP ##当外部访问vip时不做处理
arptables -A INPUT -s 192.168.0.90 -j mangle --mangle-ip-s 192.168.0.11 ##给客户端返回结果时使用vip并告知自己真实ip
arptables-save
server2:
arptables -A INPUT -d 192.168.0.90 -j DROP
arptables -A INPUT -s 192.168.0.90 -j mangle --mangle-ip-s 192.168.0.12
arptables-save
此时可以看到vip所定义应的mac地址为调度器上网卡的mac地址
在进行访问时,成功实现调度(轮询算法):
调度器工作正常:
LVS的DR模式配置完成。
tunnle模式的数据流向:
客户端发出数据到达调度器,数据包首先到达调度器的内核空间,此时报文中的ip为:cip:vip,数据到达preruting链,经preruting链检查此数据包是否访问的为本机,如果是访问本机,将数据发送到input链,没工作在input链上的ipvs对数据包进行检查,若数据包中请求的服务为后端定义的服务,在ip的首部封装一层报文([dip:rip]cip:vip),将此数据包发送到postruting链。
此时源ip为dip,目的地ip为rip。postruting链根据封装好的报文将数据包发送到后端真实服务器上,后端服务器接受数据包后,对数据包的外层封装进行拆卸,拆卸完成后的目的地IP为vip(tunnle0上的ip),再对数据包进行处理,处理结果由本机回环接口发送给网卡设备再向外发送(此时源ip为vip,目的地ip为cip),最终客户端进行接收。
隧道模式使用的模块:ipip
对ipip模块进行添加(后端服务器和调度器):
modeprobe ipip ##添加该模块
modeprobe -r ipip ##移除该模块
可发现,添加ipip模块后,使用ip a
看到多出一个tunl0的设备,
目前状态为关闭状态(DOWN)。
给tunl0上添加虚拟ip(调度服务器和后端服务器):
ip addr add 192.168.0.90/24 dev tunl0
ipvsadm编写规则,给其添加虚拟ip入口:
ipvsadm -A -t 192.168.0.90:80 -s rr
ipvsadm -a -t 192.168.0.90:80 -r 192.168.0.11:80 -i
ipvsadm -a -t 192.168.0.90:80 -r 192.168.0.12:80 -i
激活tunl0:
ip link set up tunl0
最后关闭反向过滤规则:
若系统开启反向过滤规则,系统会对流入的数据包进行反向路径校验,若是不符合单项过滤规则,则将此数据包做丢弃处理。
将其中所有为1的选项置为0(调度服务器和后端服务器):
到此,TUNNLE模式就搭建好了。
那如果我们定义的后端的服务器集群的某一台设备出现故障(down),那么会出现什么情况?
这里我们还是用DR模式的轮询调度算法:
此时在客户端进行访问测试:
可以看到,客户端在进行访问时,会轮询访问后端的两台服务器,当一台服务器挂掉之后,对此服务器就不能进行正常访问,客户访问结果时而正常时而不正常,会给客户造成非常差的体验。
所以我们必须要完成一项工作,那就是自动检查后端的服务是否正常运行,如果检测到不正常运行,呢那就将其剔出我们定义的后端服务器集群,当期恢复正常时,在自动将其拉回服务器集群。
完成这个工作的为后端健康检查,有两种方式:
使用第三方插件或者akeeplived
安装ldirector:
下载好ldirector的rpm包,使用yum进行安装,报错:
解决此问题,须将系统镜像中的高可用的包添加进yum源:
配置完成后,保存退出。
对yum源进行列出:
yum repolist
成功列出!
再次安装ldirector:
安装成功,解决非常多的依赖性。
配置文件:/usr/share/doc/ldirectord-3.9.5/ldirectord.cf
配置目录:/etc/ha.d
将配置文件拷贝到配置目录中:
cp /usr/share/doc/ldirectord-3.9.5/ldirectord.cf /etc/ha.d/
配置完成后,保存退出。
使用systemctl start ldirectord的方式进行启动:
测试:
后端服务器server1,server2都正常:
访问测试:
可以实现轮询访问。
当其中一台后端服务器server1停止工作:
此时,使用ipvsadm查看后端服务器:
后端服务器只剩下server2,不工作的server1自动被移除!
访问测试:
只能访问server2,连续访问能正常进行,呵护的访问请求不受其中一台服务器down的影响。
可以看到,恢复正常的server1被自动拉回到后端服务器集群!
当后端服务器意外故障,恢复正常等动作发生后,实现后端服务器意外down机客户端无感知!
解决完后端意外down掉的情况后,还有一个问题就是如果调度器这个节点down掉(入口没了)会怎么样?
可想而知,调度器down后是无法访问后端服务器!
keepalive对后端的健康检查在下面(高可用)会说到,这里就不再说。
为解决此问题,可以使用软件keepalive来实现:
当调度器意外down掉之后,需要有另外一台调度器来接替其完成调度工作。
keepalived是一款保障集群高可用的软件,防止单点故障。保证在个别节点down掉的情况下,整个网络可以不间断的运行。
同时,keepalive还有对LVS下家电的健康检查功能,所以,在使用keepalived的情况下可以不使用ldirector。
在keepalived官网下载好keepalived源码包,对其解压,进入解压后的目录:
查看预编译的参数:
./configure --help
这里需要添加–with-init= systemd 参数,这是因为在rhel6中管理服务使用的是SYSV的方式,在rhel7及以上使用的是高集成的systemd的方式。
预编译:
./configure --prefix=/usr/local/keepalived --with-init=systemd
报错:缺少openssl组件
对openssl-devel进行安装:
yum install -y openssl-devel
注意:在编译时遇到缺少组件报错,一般安装xxx-devel 的开发包!
安装完openssl-devel后再次预编译:
预编译成功!要注意的是:Use IPVS Framework 必须是 Yes才能正常使用,不然无法使用(须使用arp协议)
接下来进行编译安装:
make && make install
安装成功!
首先删除虚拟ip(keepalived会自动添加)
ip addr del 192.168.0.90 dev ens39
将安装在/usr/local下的keepalived软连接到/etc:
ln -s /usr/local/keepalived/etc/keepalived/ /etc/
在etc目录中对keepalive进行配置:
配置文件:
keepalived.conf
提醒邮件的配置:
当节点服务器down后会一般给管理员发邮件
配置完成后,保存退出。
在备用虚拟服务器上同样安装keepalived,软链接到/etc下,
对配置文件进行配置:
都这里,两台虚拟服务器上的keepalived就配置完成!
此时,虚拟服务器主服务器上的网卡ens39上自动添加了指定的虚拟ip192.168.0.90:
访问测试:
客户端轮询访问正常!
此时手动down掉server1:
再次使用客户端进行访问:
后端服务器server1成功被剔出服务集群!
此时开启server1:
再次进行访问:
调度访问又恢复正常!
恢复正常的server1成功被自动拉回后端服务器集群!
后端健康检查功能正常!
测试高可用:
此时主服务器上的虚拟ip被自动移除到辅服务器的网卡上:
访问测试:
在主服务器down掉后,轮询访问正常!
再次打开主服务器上的keepalived:
此时辅服务器的日志:
当主服务器启动后,检测到优先级低于主服务器优先级,进入backup状态,并移除vip…
此时vip又加到了主服务器的网卡上,成功实现vip的漂移!
轮询访问正常,客户端全程无感知!成功实现高可用!
vrrp(Virtual Router Redundancy Protocol)为虚拟路由器冗余协议,是由IETF提出的解决局域网中配置静态网关出现单点失效现象的路由协议,1998年已推出正式的RFC2338协议标准。VRRP广泛应用在边缘网络中,它的设计目标是支持特定情况下IP数据流量失败转移不会引起混乱,允许主机使用单路由器,以及即使在实际第一跳路由器使用失败的情形下仍能够维护路由器间的连通性。
也就是keepalived工作协议。keepalived工作原理为:
我么这里定义的虚拟服务器集群为一主一从,也可以定义为一主多从,主服务器master会一直向辅服务器backup发送组播,当backup接收不到master发送的报文时,会认为主服务器已经挂掉,此时会根据vrrp的优先级来选举一个backup来晋升为master来保证服务的高可用。
故障切换原理:
正常工作时,主节点master会向备节点backup发送心跳检测,当master出现故障时,就不能向backup节点发送心跳检测。备节点不能检测到主节点发送的心跳信息,此时备节点会调动自己的监管程序,来接管主节点所有的ip资源和服务。当主节点恢复正常时,因为优先级低于主节点优先级,备节点会释放自己的资源重新成为backup