负载均衡集群是 load balance 集群的简写,翻译成中文就是负载均衡集群。LB集群的架构和原理很简单,就是当用户的请求过来时,会直接分发到Director Server上,然后它把用户的请求根据设置好的调度算法,智能均衡地分发到后端真正服务器(real server)上。为了避免不同机器上用户请求得到的数据不一样,需要用到了共享存储,这样保证所有用户请求的数据是一样的。
常用的负载均衡开源软件有nginx、lvs、haproxy,商业的硬件负载均衡设备F5、Netscale。这里主要是学习 LVS。
LVS(Linux Virtual Server)即Linux虚拟服务器,是由章文嵩博士主导的开源负载均衡项目,目前LVS已经被集成到Linux内核模块中。它其实是一种集群(Cluster)技术,采用IP负载均衡技术和基于内容请求分发技术。调度器具有很好的吞吐率,将请求均衡地转移到不同的服务器上执行,且调度器自动屏蔽掉服务器的故障,从而将一组服务器构成一个高性能的、高可用的虚拟服务器。整个服务器集群的结构对客户是透明的,而且无需修改客户端和服务器端的程序。
LVS主要组成部分
负载调度器(load balancer/ Director),它是整个集群对外面的前端机,负责将客户的请求发送到一组服务器上执行,而客户认为服务是来自一个IP地址(我们可称之为虚拟IP地址)上的。
服务器池(server pool/ Realserver),是一组真正执行客户请求的服务器,执行的服务一般有WEB、MAIL、FTP和DNS等。
共享存储(shared storage),它为服务器池提供一个共享的存储区,这样很容易使得服务器池拥有相同的内容,提供相同的服务。
LVS的基本工作原理
1. 当用户向负载均衡调度器(Director Server)发起请求,调度器将请求发往至内核空间
2. PREROUTING链首先会接收到用户请求,判断目标IP确定是本机IP,将数据包发往INPUT链
3. IPVS是工作在INPUT链上的,当用户请求到达INPUT时,IPVS会将用户请求和自己已定义好的集群服务进行比对,如果用户请求的就是定义的集群服务,那么此时IPVS会强行修改数据包里的目标IP地址及端口,并将新的数据包发往POSTROUTING链
4. POSTROUTING链接收数据包后发现目标IP地址刚好是自己的后端服务器,那么此时通过选路,将数据包最终发送给后端的服务器
LVS相关术语
1. DS:Director Server。指的是前端负载均衡器节点。
2. RS:Real Server。后端真实的工作服务器。
3. VIP:虚拟IP,向外部直接面向用户请求,给远程客户端提供服务的外部IP。
4. DIP:Director Server IP,主要用于和内部主机通讯的IP地址。在NAT模式中是后端realserver的gateway,在DR和Tune中如果使用heartbeat或者keepalived,用来探测使用
5. RIP:Real Server IP,后端服务器的IP地址。
6. CIP:Client IP,访问客户端的IP地址。
LVS 的实现由2部分代码组成,包括 ipvs 和 ipvsadm。
1.ipvs(ip virtual server):一段代码工作在内核空间,叫ipvs,是真正生效实现调度的代码。
2. ipvsadm:另外一段是工作在用户空间,叫ipvsadm,负责为ipvs内核框架编写规则,定义谁是集群服务,而谁是后端真实的服务器(Real Server)
IPVS 是 lvs 的第一部分负载调度器(load balancer)的实现 ,也就是最核心的部分,用来进行负载均衡,所以 IPVS主要实现了四种IP负载均衡技术 + 十种调度算法 来实现lvs的负载均衡功能。
<1>IP负载均衡技术
NAT工作模式,简单来说就是传统的NAT,进出流量都需要经过调度器,调度器会选择一个目的服务器,将进入流量的目标IP改写为负载均衡到的目标服务器,同时源IP地址也会改为调度器IP地址。机制简单,但限制大,IPVS需要维护每个映射关系,而且进出入流量都需要经过调度器,实际上这个会成为瓶颈。
TUN工作模式,即IP Tunneling模式。这种模式中,调度器将进入的包重新包成一个IP包,然后发送给选定的目的服务器,目的服务器处理后,直接将应答发送给客户(当然该重新封装的报文的源IP地址还是要填成调度器的)。
DR工作模式,即Direct Routing模式。这种模式中,调度器直接重写进入包的mac地址,将其改为选定的目标服务器的mac地址,这样就可以到达服务器。但这样的话需要要求IPVS服务器需要和真实服务器在同一局域网内,且真实服务器必须有真实网卡(这样重写了mac地址的报文才可以才可以到达该服务器)
FULLNAT工作模式
<2>调度算法
IPVS在内核中的负载均衡调度是以连接为粒度的。在HTTP协议(非持久)中,每个对象从WEB服务器上获取都需要建立一个TCP连接,同一用户的不同请求会被调度到不同的服务器上,所以这种细粒度的调度在一定程度上可以避免单个用户访问的突发性引起服务器间的负载不平衡。
在内核中的连接调度算法上,IPVS已实现了以下十种调度算法:
LVS的三种工作模式
DR(直接路由)
NAT(网络地址转换)
Tune (隧道)
Virtual Server via Direct Routing
VS/DR方式是通过改写请求报文中的MAC地址部分来实现的。Director和RealServer必需在物理上有一个网卡通过不间断的局域网相连。 RealServer上绑定的VIP配置在各自Non-ARP的网络设备上(如lo或tunl),Director的VIP地址对外可见,而RealServer的VIP对外是不可见的。RealServer的地址即可以是内部地址,也可以是真实地址。
实现原理:重将请求报文的目标MAC地址设定为挑选出的RS的MAC地址
实现流程:
(a) 当用户请求到达Director Server,此时请求的数据报文会先到内核空间的PREROUTING链。 此时报文的源IP为CIP,目标IP为VIP
(b) PREROUTING检查发现数据包的目标IP是本机,将数据包送至INPUT链
(c) IPVS 比对数据包请求的服务是否为集群服务,若是,将请求报文中的源MAC地址修改为DIP的MAC地址,将目标MAC地址修改RIP的MAC地址,然后将数据 包发至POSTROUTING链。 此时的源IP和目的IP均未修改,仅修改了源MAC地址为DIP的MAC地址,目标MAC地址为RIP的MAC地址
(d) 由于DS和RS在同一个网络中,所以是通过二层来传输。POSTROUTING链检查目标MAC地址为RIP的MAC地址,那么此时数据包将会发至Real Server。
(e) RS发现请求报文的MAC地址是自己的MAC地址,就接收此报文。处理完成之后,将响应报文通过lo接口传送给eth0网卡然后向外发出。 此时的源IP地址为VIP,目标IP为CIP
(f) 响应报文最终送达至客户端
LVS-DR模式的特性
特点1:保证前端路由将目标地址为VIP报文统统发给Director Server,而不是RS
RS可以使用私有地址;也可以是公网地址,如果使用公网地址,此时可以通过互联网对RIP进行直接访问
RS跟Director Server必须在同一个物理网络中
所有的请求报文经由Director Server,但响应报文必须不能进过Director Server
不支持地址转换,也不支持端口映射
RS可以是大多数常见的操作系统
RS的网关绝不允许指向DIP(因为我们不允许他经过director)
RS上的lo接口配置VIP的IP地址
缺陷:RS和DS必须在同一机房中
实验环境:
本次实验所有主机均为rhel6.5,并且selinux为disabled、防火墙为关闭状态;
主机 角色 IP
server1 LB(调度器) 172.25.81.1
server2 RS(真实后端服务器) 172.25.81.2
server3 RS(真实后端服务器) 172.25.81.3
物理机 客户端测试 172.25.81.250
实验过程:
server1调度器配置
<1>扩展yum源
[root@server1 ~]# vim /etc/yum.repos.d/rhel-source.repo
[rhel-source]
name=Red Hat Enterprise Linux $releasever - $basearch - Source
baseurl=http://172.25.81.250/rhel6.5
enabled=1
gpgcheck=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release[LoadBalancer] ##负载均衡
name=LoadBalancer
baseurl=http://172.25.81.250/rhel6.5/LoadBalancer
gpgcheck=0[HighAvailability] ##高可用
name=HighAvailability
baseurl=http://172.25.81.250/rhel6.5/HighAvailability
gpgcheck=0[ResilientStorage] ##分布式存储
name=ResilientStorage
baseurl=http://172.25.81.250/rhel6.5/ResilientStorage
gpgcheck=0[ScalableFileSystem] ##大文件系统支持
name=ScalableFileSystem
baseurl=http://172.25.81.250/rhel6.5/ScalableFileSystem
gpgcheck=0[root@server1 ~]# yum clean all
[root@server1 ~]# yum repolist
<2>安装管理集群服务ipvsadm
[root@server1 ~]# yum install ipvsadm -y
<3>给调度器添加虚拟IP(即客户端访问的IP)
[root@server1 ~]# ip addr add 172.25.81.100/24 dev eth0
[root@server1 ~]# ip addr show
<4>添加策略
[root@server1 ~]# ipvsadm -A -t 172.25.81.100:80 -s rr ## -t:TCP,-s:sheduler rr:表示论询算法,
##vip添加RS地址,并设置为DR模式
[root@server1 ~]# ipvsadm -a -t 172.25.81.100:80 -r 172.25.81.2:80 -g ## -r:RS地址,-g:DR模式
[root@server1 ~]# ipvsadm -a -t 172.25.81.100:80 -r 172.25.81.3:80 -g##保存ipvsadm设置策略 ,保存地址为/etc/sysconfig/ipvsadm
[root@server1 ~]# /etc/init.d/ipvsadm save
查询ipvsadm状态:
[root@server1 ~]# ipvsadm -l ##解析ip
[root@server1 ~]# ipvsadm -ln ##不解析ip
Server2配置:
<1>修改Apache服务测试页内容,并开启httpd服务
[root@server2 ~]# vim /var/www/html/index.html
[root@server2 ~]# /etc/init.d/httpd start
<2>Realserver2同样添加虚拟ip地址,与调度器虚拟ip地址一致
Server3配置:
<1>修改Apache服务测试页内容,并开启httpd服务
[root@server3 ~]# vim /var/www/html/index.html
[root@server3 ~]# /etc/init.d/httpd start
<2>Realserver3同样添加虚拟ip地址,与调度器虚拟ip地址一致
客户端进行测试:
ARP是一个重要的TCP/IP协议,并且用于确定对应IP地址的网卡物理地址。
可以看到这里的100的IP地址指向的并不是指向调度器(即server1),而是server3(后端真实服务器);
[root@foundation81 ~]# arp -d 172.25.81.100
重新curl 172.25.45.100,再次查看这个100的IP指向的主机为server1:
可以看出,访问100这个IP时,后端真实服务器也可以直接响应,并不能唯一指定调度器,且具有随机性;为了让100这个IP地址唯一地指向调度器(即server1),即可以采用两种方法:
arptables:在arp的层次上实现在ARP解析时做防火墙规则,过滤RS响应ARP请求。这是由iptables提供的
修改RS上内核参数(arp_ignore和arp_announce)将RS上的VIP配置在lo接口的别名上,并限制其不能响应对VIP地址解析请求。
这里我们采用第一种方法对真实服务器server2和server3进行arp抑制
server2:
<1>安装arp防火墙
arp防火墙用来屏蔽数据包,拦截ip冲突,因为虚拟机与real server的地址一致,所以进入real server时需要把虚拟ip DROP掉,即拦截real server的虚拟ip
[root@server2 ~]# yum install arptables_jf -y
<2>设置arp抑制
[root@server2 ~]# arptables -A IN -d 172.25.81.100 -j DROP ##拒绝客户端访问realserver的虚拟ip,只要输入进来直接DROP掉
[root@server2 ~]# arptables -A OUT -s 172.25.81.100 -j mangle --mangle-ip-s 172.25.81.2
##由于tcp三次握手,出去时仍要以vip地址形式才会握手,而真正将数据传输给客户端的就是realserver,mangle参数就是这个功能
[root@server2 ~]# /etc/init.d/arptables_jf save ##保存策略在/etc/sysconfig/arptables中
<3>查看arp防火墙状态
[root@server2 ~]# arptables -L
server3:
<1>安装arp防火墙
arp防火墙用来屏蔽数据包,拦截ip冲突,因为虚拟机与real server的地址一致,所以进入real server时需要把虚拟ip DROP掉,即拦截real server的虚拟ip
[root@server3 ~]# yum install arptables_jf -y
<2>设置arp抑制
[root@server3 ~]# arptables -A IN -d 172.25.81.100 -j DROP ##拒绝客户端访问realserver的虚拟ip,只要输入进来直接DROP掉
[root@server3 ~]# arptables -A OUT -s 172.25.81.100 -j mangle --mangle-ip-s 172.25.81.3
##由于tcp三次握手,出去时仍要以vip地址形式才会握手,而真正将数据传输给客户端的就是realserver,mangle参数就是这个功能
[root@server2 ~]# /etc/init.d/arptables_jf save ##保存策略在/etc/sysconfig/arptables中
<3>查看arp防火墙状态
[root@server3 ~]# arptables -L
客户端测试:
查看arp缓冲区中的条目,arp缓冲区中MAC地址与server1的MAC地址相同
server1查看ipvsadm状态,server2、3负载均衡
用ldirectord实现健康检查
<1>下载软件ldirectord-3.9.5-3.1.x86_64.rpm ,并安装;
<2>查找配置文件
[root@server1 ~]# rpm -ql ldirectord-3.9.5-3.1.x86_64
<3>修改配置文件
[root@server1 ~]# cd /etc/ha.d/
[root@server1 ha.d]# cp /usr/share/doc/ldirectord-3.9.5/ldirectord.cf .
[root@server1 ha.d]# vim ldirectord.cf
virtual=172.25.81.100:80
real=172.25.81.2:80 gate
real=172.25.81.3:80 gate
fallback=127.0.0.1:80 gate ##server2和server3服务同时down后,访问本机80端口
service=http
scheduler=rr ##调度算法:轮询
#persistent=600
#netmask=255.255.255.255
protocol=tcp
checktype=negotiate
checkport=80
request="index.html"
#receive="Test Page" ##注释该行
#virtualhost=www.x.y.z ##注释该行[root@server1 ha.d]# /etc/init.d/ldirectord start ##开启服务
<4>编辑Apache服务测试页内容
注意: 当安装 php 模块后,默认优先读取 index.php,应将index.php删除,才可读取Index.html.
修改Apache监听端口为80
[root@server1 html]# vim /etc/httpd/conf/httpd.conf
重启httpd服务
测试本机的apache测试页
<5>测试:
(1)关闭server2的httpd
客户端测试:
调度器查看调度情况:
发现只有server3被调度了
(2)同时关闭server2和server3的httpd
客户端测试:
调度器查看调度情况:
keepalived实现高可用集群
主从两台机器,我们需要绑定域名到指定的IP,如果绑定在主上面。如果主宕机,我们就无法提供服务,所以Vitrual IP就起到了关键性作用。默认配置在主服务器上面,但是一旦宕机,从服务器就会立即启动,并且把这个IP绑定在从上面从而不会影响业务的状态!
实验环境:
server1 LB(主调度器)
server2 RS
server3 RS
server4 LB (从调度器;当主调度器在工作时,它是处于休眠状态,一旦原来的master挂掉,立马成为新的主master)
部署过程:
server1 LB(主调度器):
<1>停止 ldirectord 服务并设置开机不自启
<2>删除上个实验的虚拟ip
<3>下载并安装keepalived
[root@server1 ~]# tar zxf keepalived-2.0.6.tar.gz ##解压
[root@server1 ~]# yum install openssl-devel -y ##解决源码编译时的依赖性, 安装 openssl-devel
[root@server1 ~]# cd keepalived-2.0.6
[root@server1 keepalived-2.0.6]# ./configure --prefix=/usr/local/keepalived --with-init=SYSV ##检测安装环境
[root@server1 keepalived-2.0.6]# make && make install ##编译并安装
<4>创建软链接
[root@server1 init.d]# chmod +x /usr/local/keepalived/etc/rc.d/init.d/keepalived
[root@server1 init.d]# ln -s /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/
[root@server1 init.d]# ln -s /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
[root@server1 init.d]# ln -s /usr/local/keepalived/etc/keepalived/ /etc/
[root@server1 init.d]# ln -s /usr/local/keepalived/sbin/keepalived /sbin/
<5>修改keepalived配置文件
[root@server1 ~]# 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.1
smtp_connect_timeout 30
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
#vrrp_strict ##注释此行,防止修改防火墙规则
vrrp_garp_interval 0
vrrp_gna_interval 0
}vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 81 ##id避免冲突
priority 100 ##数值越大优先级越高
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.81.100 ##LVS的vip,服务启动生效时自动添加
}
}virtual_server 172.25.81.100 80 {
delay_loop 6
lb_algo rr
lb_kind DR ##模式改为DR
#persistence_timeout 50 ##注释此行,此行表示持续连接
protocol TCPreal_server 172.25.81.2 80 {
TCP_CHECK {
weight 1
connect_timeout 3
retry 3
delay_before_retry 3
}
}
real_server 172.25.81.3 80 {
TCP_CHECK {
weight 1
connect_timeout 3
retry 3
delay_before_retry 3
}
}
}[root@server1 ~]# /etc/init.d/keepalived start ##开启服务
<6>将配置好的keepalived传给从调度器server4
[root@server1 ~]# scp -r /usr/local/keepalived/ root@server4:/usr/local
server4(从调度器):
<1>扩展yum源(同server1)
<2>安装服务ipvsadm
[root@server4 ~]# yum install ipvsadm -y
<3>为keepalived服务创建软链接
<4>修改keepalived配置文件
[root@server4 ~]# vim /etc/keepalived/keepalived.conf ##只需在server1配置文件的基础上改两处
vrrp_instance VI_1 {
state BACKUP ##将状态改为备用
interface eth0
virtual_router_id 81
priority 50 ##修改此处的优先级
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.81.100
}
}[root@server4 ~]# /etc/init.d/keepalived start ##开启服务
server2与server3(真实服务器):
开启httpd服务
测试:
实验时,可删除vip,停止keepalived服务,停止网络服务,刷掉内核来达到使keepalived服务宕掉的目的
注意:手动删除vip时,keepalived服务失效
<1>负载均衡
<2>健康检查
只将server3的httpd服务关闭后,测试:
两个真实主机的httpd服务都关闭后,测试:
<3>server1主机keepalived服务开启时: (server1优先级高,主用,显示server1的Mac地址)
且此时虚拟ip处于server1上
<4>server1主机keepalived服务关闭时: (server4主机执行调度的工作,备用,显示server4的Mac地址)
且此时虚拟ip处于server1上