负载均衡集群
负载均衡集群指使用多台提供相同服务的服务器组成集群系统,提高服务的并发处理能力。负载均衡集群的前端使用一个调度器,将客户端请求平均分配到后端的服务器中,同时调度器可能还具有后端服务器状态检测的功能,将故障的服务器自动下线,使得集群具有一定的容错能力。
使用负载均衡集群能够有效的扩展服务的并发能力,负载均衡集群中的主机间应该尽量的「低耦合」,最好是「无状态」的,这样就能够方便的增加主机实现扩展。
常见的负载均衡器
根据工作在的协议层划分可划分为:
- 四层负载均衡:根据请求报文中的目标地址和端口进行调度
- 七层负载均衡:根据请求报文的内容进行调度,这种调度属于「代理」的方式
根据软硬件划分:
- 硬件负载均衡:
- F5 的 BIG-IP
- Citrix 的 NetScaler
- 这类硬件负载均衡器通常能同时提供四层和七层负载均衡,但同时也价格不菲
- 软件负载均衡:
- TCP 层:LVS,HaProxy,Nginx
- 基于 HTTP 协议:Haproxy,Nginx,ATS(Apache Traffic Server),squid,varnish
- 基于 MySQL 协议:mysql-proxy
LVS
LVS 是一个工作在四层的负载均衡器,它的实现和 iptables/netfilter 类似,工作在内核空间的 TCP/IP 协议栈上,LVS 工作在 INPUT Hook Funtion 上,并在 INPUT 设置附加规则,一旦客户端请求的是集群服务,LVS 会强行修改请求报文,将报文发往 POSTROUTING,转发至后端的主机。
和 iptables/netfilter 类似,LVS 也是两段式的:
ipvsadm
:工作在用户空间,负责定义和管理集群服务的规则ipvs
:工作在内核中,在 2.4.23 之前,必须向内核打补丁,并重新编译内核。在 2.4.23 和 2.6 之后的版本,ipvs
直接内置在内核中。
LVS 集群的设备地址命名
- VIP:Virtual IP,LVS 面向用户请求的 IP 地址
- RIP:Real server IP,后端服务器用于和 LVS 通信的 IP 地址
- DIP:Director IP,LVS 用户和后端服务器通信的 IP 地址
- CIP:Client IP,客户端 IP 地址
LVS 的工作模型
LVS-NAT
LVS-NAT 模型类似于 DNAT,工作机制与 DNAT 一样,当客户端请求的是集群服务时,LVS 修改请求报文的目标地址为 RIP,转发至后端的 RealServer,并修改后端响应报文的源地址为 VIP,响应至客户端。
在 LVS-NAT 模型下,Director 进出请求报文都经过 Director,因此 Director 的压力是比较大的。
LVS-NAT 的特性:
- 集群节点跟 Director 必须在同一个 IP 网络中
- RIP 通常是私有地址,仅用于各集群节点间的通信
- Director 位于 client 和 Realserver 之间,负责处理进出的所有报文
- Realserver 必须将网关指向 DIP
- 支持端口映射
- 较大规模应用场景中,Director 易成为系统瓶颈(bottleneck)
LVS-DR
DR 值 Direct Routing,直接路由,DR 模型中,Director 和 Realserver 处在同一网络中,对于 Director,VIP 用于接受客户端请求,DIP 用于和 Realserver 通信。对于 Realserver,每个 Realserver 都配有和 Director 相同的 VIP(此 VIP 隐藏,关闭对 ARP 请求的响应),仅用户响应客户端的请求,RIP 用于和 Director 通信。
当客户端请求集群服务时,请求报文发送至 Director 的 VIP(Realserver的 VIP 不会响应 ARP 请求),Director 将客户端报文的源和目标 MAC 地址进行重新封装,将报文转发至 Realserver,Realserver 接收转发的报文。此时报文的源 IP 和目标 IP 都没有被修改,因此 Realserver 接受到的请求报文的目标 IP 地址为本机配置的 VIP,它将使用自己的 VIP 直接响应客户端。
LVS-DR 模型中,客户端的响应报文不会经过 Director,因此 Director 的并发能力有很大提升。
LVS-DR 模型的特性:
- 保证前端路由器将目标地址为 VIP 的报文通过 ARP 解析后送往 Director。
- 静态绑定:在前端路由将 VIP 对应的目标 MAC 地址静态配置为Director VIP 接口的 MAC 地址。
- arptables:在各 Realserver 上,通过 arptables 规则拒绝其响应对 VIP 的 ARP 广播请求
- 修改内核参数:在 Realserver 上修改内核参数,并结合地址的配置方式实现拒绝响应对 VIP 的 ARP 广播请求
- 各RIP 必须与 DIP 在同一个物理网络中
- RS 的 RIP 可以使用私有地址,也可以使用公网地址,以方便配置
- Director 仅负责处理入站请求,响应报文由 Realserver 直接发往客户端
- Realserver 不能将网关指向 DIP,而直接使用前端网关
- 不支持端口映射
LVS-TUN
和 DR 模型类似,Realserver 都配有不可见的 VIP,Realserver 的 RIP 是公网地址,且可能和 DIP 不再同一网络中。当请求到达 Director 后,Director 不修改请求报文的源 IP 和目标 IP 地址,而是使用 IP 隧道技术,使用 DIP 作为源 IP,RIP 作为目标 IP 再次封装此请求报文,转发至 RIP 的 Realserver 上,Realserver 解析报文后仍然使用 VIP 作为源地址响应客户端。
LVS-TUN 的特性: - 集群节点和可以跨越 Internet - RIP,DIP,VIP 都是公网地址 - Director 仅负责处理入站请求,响应报文由 Realserver 直接发往客户端 - Realserver 使用自己的网关而不是 Director - Realserver 只能使用支持隧道功能的操作系统 - 不支持端口映射
LVS-FULLNAT
FULLNAT 由淘宝研发,目前还没有加入至 CentOS 可用的内核中,使用时需要向内核打补丁。
类似于 DNAT,它修改请求报文的源地址为 DIP,目标地址为 RIP 来实现转发。对于响应报文,源地址修改为 VIP,目标地址修改为 CIP 来实现转发。
特点:
- RIP,DIP 可以使用私有地址
- RIP 和 DIP 可以不再同一网络中,且 RIP 的网关不需要指向 DIP
- 支持端口映射
- 请求和响应报文都经由 Director
LVS 的调度算法
当 LVS 接受到一个客户端对集群服务的请求后,它需要进行决策将请求调度至某一台后端主机进行响应。LVS 的调度算法共有 10 种,按类别可以分为动态和静态两种类型。
静态调度算法
静态调度算法调度时不会考虑后端服务器的状态
rr:round robin,轮询,即简单在各主机间轮流调度
wrr:weighted round robin,加权轮询,根据各主机的权重进行轮询
sh:source hash,源地址哈希,对客户端地址进行哈希计算,保存在 Director 的哈希表中,在一段时间内,同一个客户端 IP 地址的请求会被调度至相同的 Realserver。sh 算法的目的是实现 session affinity(会话绑定),但是它也在一定程度上损害了负载均衡的效果。如果集群本身有 session sharing 机制或者没有 session 信息,那么不需要使用 sh 算法
dh:destination hash,和 sh 类似,dh 将请求的目标地址进行哈希,将相同 IP 的请求发送至同一主机,dh 机制的目的是,当 Realserver 为透明代理缓存服务器时,提高缓存的命中率。
动态调度算法
动态调度算法在调度时,会根据后端 Realserver 的负载状态来决定调度选择,Realserver 的负载状态通常由活动链接(active),非活动链接(inactive)和权重来计算。
lc:least connted,最少连接,LVS 根据 overhead = active*256 + inactive
计算服务器的负载状态,每次选择 overhead 最小的服务器
wlc:weighted lc,加权最少连接,LVS 根据 overhead = (active*256+inactive)/weight
来计算服务器负载,每次选择 overhead 最小的服务器,它是 LVS 的默认调度算法
sed:shortest expected delay,最短期望延迟,它不对 inactive 状态的连接进行计算,根据overhead = (active+1)*256/weight
计算服务器负载,选择 overhead 最小的服务器进行调度
nq:never queue,当有空闲服务器时,直接调度至空闲服务器,当没有空闲服务器时,使用 SED 算法进行调度
LBLC:locality based least connection,基于本地的最少连接,相当于 dh + wlc,正常请求下使用 dh 算法进行调度,如果服务器超载,则使用 wlc 算法调度至其他服务器
LBLCR:locality based least connection with replication,基于本地的带复制功能的最少连接,与 LBLC 不同的是 LVS 将请求 IP 映射至一个服务池中,使用 dh 算法调度请求至对应的服务池中,使用 lc 算法选择服务池中的节点,当服务池中的所有节点超载,使用 lc 算法从所有后端 Realserver 中选择一个添加至服务吃中。
ipvsadm
ipvsadm 用于配置 LVS 的调度规则,管理集群服务和 Realserver
管理集群服务
添加:-A -t|u|f service-address [-s scheduler] -t: TCP协议的集群 -u: UDP协议的集群 service-address: IP:PORT -f: FWM: 防火墙标记 service-address: Mark Number 修改:-E 删除:-D -t|u|f service-address 例如: # ipvsadm -A -t 10.10.0.1:80 -s rr
管理集群服务中的 RS
添加:-a -t|u|f service-address -r server-address [-g|i|m] [-w weight] -t|u|f service-address:事先定义好的某集群服务 -r server-address: 某RS的地址,在NAT模型中,可使用IP:PORT实现端口映射; [-g|i|m]: LVS类型 -g: DR -i: TUN -m: NAT [-w weight]: 定义服务器权重 修改:-e 删除:-d -t|u|f service-address -r server-address 例如: # ipvsadm -a -t 10.10.0.2:80 -r 192.168.10.8 -m # ipvsadm -a -t 10.10.0.3:80 -r 192.168.10.9 -m
查看规则
-L|-l -n:数字格式显式主机地址和端口 --stats:统计数据 --rate: 速率 --timeout: 显示tcp、tcpfin和udp的会话超时时长 -c: 显示当前的ipvs连接状况
删除所有集群服务
-C:清空 ipvs 规则
保存规则
-S 如: # ipvsadm -S > /path/to/somefile
载入保存的规则
-R 如: # ipvsadm -R < /path/from/somefile
DR 模型的配置
DR 模型的 Realserver 禁止 ARP 响应
对于 Linux 来说,地址是属于主机的,Linux 主机在开机时会通告连接所有网络内的所有其他主机自己的所有 ip 地址和 mac 地址。
可以利用 Linux 的特性,将VIP配置在 Realserver 的本地回环接口上作为别名,并使用 arp_ignore
和arp_annouce
内核参数。
禁止 ARP 响应的方式
arptables:红帽系类系统上提供的程序
修改内核参数:
arp_ignore
:定义接收到 ARP 请i去时的响应级别- 0:只要本地配置有响应地址,就给与响应
- 1:仅在请求的目标地址配置请i去到达的接口上的时候,才进行响应
arp_announce
:定义主机将自己的地址想外通告时的通告级别- 0:将本地任何接口上的任何地址向外通告
- 1:向目标网络通告与其网络匹配的地址
- 2:仅向本地接口上匹配的网络进行通告
添加特殊的路由条目 Linux 主机在使用某一接口发出报文时,默认会使用此接口的 IP 作为源 IP 地址。
当请求 Realserver 时,Realserver 的 VIP 是 lo 接口的别名,而 VIP 对外的通信实际需要使用的却是 eth0 接口,因此需要添加路由条目,让主机在使用 VIP 向外通信时,强制使用 lo 端口,因而它会使用 lo 端口的地址作为源 IP 进行响应,并最终由 lo 接口转发至 eth0 接口发出报文。
实验以web服务为例
LVS-NAT 模式
三台机器,一台Driector Server,两台Real Server。
ip地址分别是:
driector外网:10.0.2.5
driector内网:192.168.1.6
real1:192.168.1.12
real2:192.168.1.15
driector内网IP和real的IP地址必须要一个网段,driector必须是Linux系统,real后面可以是Windows系统
首先配置Driector Server
yum -y install ipvsadm
清空iptables规则
iptables -F
关闭SELinux
setenforce 0
开启路由转发功能
echo 1 > /proc/sys/net/ipv4/ip_forward
ipvsadm -A -t 10.0.2.5:80 -s rr ipvsadm -A -t 10.0.2.5:80 -r 192.168.1.12:80 -m ipvsadm -A -t 10.0.2.5:80 -r 192.168.1.15:80 -m
关闭icmp的重定向
echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects echo 0 > /proc/sys/net/ipv4/conf/default/send_redirects echo 0 > /proc/sys/net/ipv4/conf/eth0/send_redirects echo 0 > /proc/sys/net/ipv4/conf/eth1/send_redirects
// 关闭icmp的重定向
两台real分别设置网关为driector的内网IP地址
先删除默认的
route del default
添加新的
route add default gw 192.168.1.6
两台real新建不同的index.html文件便于区分
real1:192.168.1.12
echo "192.168.1.12" > /var/www/html/index.html
real2:192.168.1.15
echo "192.168.1.15" > /var/www/html/index.html
两台real分别关闭SELinux
setenforce 0
分别添加iptables规则放行
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
现在可以找个客户机测试了
浏览器中输入:
http://10.0.2.5
内容不断的发生变化就代表成功了
LVS-DR 模式
三台机器,一个Driector Server,两个Real Server。
ip地址分别是:
driector外网:192.168.1.100
driector内网:192.168.1.6
real1:192.168.1.12
real2:192.168.1.15
现在只需要写两个脚本再执行就可以了
Director上:
vim ~/lvs-dr.sh
#! /bin/bash echo 1 > /proc/sys/net/ipv4/ip_forward // 开启路由转发 ipv=/sbin/ipvsadm vip=192.168.1.100 rs1=192.168.1.12 rs2=192.168.1.15 ifconfig eth0:0 $vip broadcast $vip netmask 255.255.255.255 up route add -host $vip dev eth0:0 $ipv -C $ipv -A -t $vip:80 -s rr $ipv -a -t $vip:80 -r $rs1:80 -g -w 1 $ipv -a -t $vip:80 -r $rs2:80 -g -w 1
保存之后执行
sh ~/lvs-dr.sh
两台real上:
vim ~/lvs_dr_rs.sh
#! /bin/bash vip=192.168.1.100 ifconfig lo:0 $vip broadcast $vip netmask 255.255.255.255 up route add -host $vip lo:0 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
保存之后执行
找一个台客户机用浏览器多访问几次
http://192.168.1.100
如果内容不断的发生变化就可以了
LVS-TUN 模式
driector外网:192.168.1.100
driector内网:192.168.1.6
real1:192.168.1.12
real2:192.168.1.15
现在只需要写两个脚本再执行就可以了
Director上:
vim ~/lvs-tun.sh
#!/bin/bash vip=192.168.1.100 RS1=192.168.1.12 RS2=192.168.1.15 ifconfig tunl0 $vip broadcast $vip netmask 255.255.255.255 route add -host $vip dev tunl0 echo "0" >/proc/sys/net/ipv4/ip_forward echo "1" >/proc/sys/net/ipv4/conf/all/send_redirects echo "1" >/proc/sys/net/ipv4/conf/default/send_redirects echo "1" >/proc/sys/net/ipv4/conf/eth0/send_redirects ipvsadm -C ipvsadm -A -t $vip:80 -s wlc ipvsadm -a -t $vip:80 -r $RS1 -i ipvsadm -a -t $vip:80 -r $RS2 -i
保存之后执行
sh ~/lvs-tun.sh
两台real上:
vim ~/lvs_tun_rs.sh
#!/bin/bash vip=192.168.1.100 ifconfig tunl0 $vip broadcast $vip netmask 255.255.255.255 up echo '0' > /proc/sys/net/ipv4/ip_forward echo '1' > /proc/sys/net/ipv4/conf/tunl0/arp_ignore echo '2' > /proc/sys/net/ipv4/conf/tunl0/arp_announce echo '1' > /proc/sys/net/ipv4/conf/all/arp_ignore echo '2' > /proc/sys/net/ipv4/conf/all/arp_announce echo '0' > /proc/sys/net/ipv4/conf/tunl0/rp_filter echo '0' > /proc/sys/net/ipv4/conf/all/rp_filter
保存之后执行
找一个台客户机用浏览器多访问几次
http://192.168.1.100
如果内容不断的发生变化就可以了
4. LVS/DR + keepalived配置
Keepalived 和 LVS 有一些冲突,因为keepalived的配置文件可以设置ipvsadm规则以及虚拟IP(VIP)所以这里先删除掉以前设置过的ipvsadm规则以及虚拟IP
ipvsadm -C ifconfig tunl0 down && ifconfig eth0:0 down
前面的lvs虽然已经配置成功也实现了负载均衡,但是我们测试的时候发现,当某台real server把httpd进程停掉,那么director照样会把请求转发过去,这样就造成了某些请求不正常。所以需要有一种机制用来检测real server的状态,这就是keepalived。它的作用除了可以检测rs状态外,还可以检测备用director的状态,也就是说keepalived可以实现ha集群的功能,当然了也需要一台备用director,备用director也需要安装一下keepalived软件。
现在起码需要四台机器
IP如下:
主driector外网:192.168.1.100
主driector内网:192.168.1.6
从driector:192.168.1.8
real1:192.168.1.12
real2:192.168.1.15
主从上安装 keepalived
yum install -y keepalived
从上安装 ipvsadm
yum install -y ipvsadm
安装好后,编辑配置文件,清空自带的内容。
vim /etc/keepalived/keepalived.conf //加入如下:
vrrp_instance VI_1 { state MASTER #备用服务器上为 BACKUP interface eth0 virtual_router_id 51 priority 100 #备用服务器上为90 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.100 } } virtual_server 192.168.1.100 80 { delay_loop 6 # 每隔10秒查询realserver状态) lb_algo wlc #(lvs 算法) lb_kind DR #(Direct Route) persistence_timeout 60 #(同一IP的连接60秒内被分配到同一台realserver) protocol TCP #(用TCP协议检查realserver状态) real_server 192.168.1.12 80 { weight 100 #(权重) TCP_CHECK { connect_timeout 10 #(10秒无响应超时) nb_get_retry 3 delay_before_retry 3 connect_port 80 } } real_server 192.168.1.15 80 { weight 100 TCP_CHECK { connect_timeout 10 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } }
以上为主Director的keepalived的配置文件,从Director的配置文件只需要改两个地方
修改
state MASTER
为
state BACKUP
修改
priority 100
为
priority 90 // 比主小就行
配置完keepalived后,需要在主从上开启端口转发:
echo 1 > /proc/sys/net/ipv4/ip_forward
然后,两个real server 上执行 lvs_dr-rs.sh 脚本
最后,两个director上启动keepalived服务(先主后从)
/etc/init.d/keepalived start
另外,需要注意的是,启动keepalived服务会自动生成vip和ipvsadm规则,所以主director和从director上就不需要执行lvs-dr.sh脚本了
参考 & 扩展阅读:
1、http://liaoph.com/lvs/
2、http://outofmemory.cn/wiki/keepalived-configuration
3、http://wangyu.iteye.com/blog/424057
4、http://www.cnblogs.com/hdflzh/p/4057098.html
5、http://www.cnblogs.com/lgfeng/archive/2012/10/16/2726308.html