LVS 负载均衡集群
LVS 负载均衡集群
1.1 LVS介绍
LVS 是 Linux Virtual Server 的简写,即 Linux 虚拟服务器,是一个虚拟的服务器集群系统。此项目在 1998 年 5 月由章文嵩博士成立,是国内最早出现的自由软件项目之一,是根据 iptables 的实现来开发的,所以使用的时候会和 iptables 相类似
LVS三种模式介绍
- NAT模式(网络地址映射)
- IP TUN模式(IP Tunneling IP隧道)
- DR模式(Direct Routing 直接路由)
不同的转发模式决定了不同的的网络结构
NAT模式
NAT 模式(即:网络地址映射)其工作原理是:客户端访问LVS时,LVS通过重写请求报文的目标地址,且根据预设的调度算法,将请求分派给后端真实服务器,真实服务器接收到请求处理后,发出响应报文也需要通过LVS返回,返回时需要修改报文的源地址,然后返回给客户,完成整个负载调度过程
- DNAT:目标地址转换,改变的是目标地址
- SNAT:源地址转换,改变的是源地址
NAT 模式就是使用 SNAT 和 DNAT 技术完成报的转发,NAT 方式可支持任何的操作系统,以及私有网络,并且只需一个 Internet IP 地址,非常节省成本,但是整个系统的性能受到限制。因为执行 NAT 每次需要重写数据包,有一定的延迟,另外,大部分应用有 80%的数据是从服务器流向客户机,也就是用户的请求非常短,而服务器的回应非常大,对LVS形成很大压力,容易成为瓶颈
IP TUN模式
IP TUN(IP Tunneling 即 IP隧道)当 LVS 分配请求到不同的 real server,real server 处理请求后直接回应给用户,这样 LVS 仅处理客户机与服务器的一半连接。IP TUN 技术极大地提高了 LVS 的调度处理能力,同时也极大地提高了系统能容纳的最大节点数,可以超过 100 个节点。real server 可以在任何 LAN 或 WAN 上运行,这意味着允许地理上的分布,这在灾难恢复中有重要意义。但此模式要求所有服务器必须支持 IP 隧道协议,因此只能在 linux 下使用,在 windows 无法使用
DR模式
DR(即 Direct Routing 直接路由)与 IP TUN 类似,负载均衡器仅处理一半的连接,避免了新的性能瓶颈,同样增加了系统的可伸缩性,DR 与 IP TUN 相比,没有 IP 封装的开销,但由于采用物理层(修改 MAC地址)技术,所有服务器都必须在同一个局域网
DR 和 IP TUN 的区别:
DR 与 IP TUN 相比,没有 IP 封装的开销,但由于采用数据链路层(修改 MAC地址)技术,所有服务器都必须在一个物理网段
三种模式对比
NAT模式 | IP TUN模式 | DR模式 | |
---|---|---|---|
对服务器要求 | 任何操作系统均支持 | 必须支持IP隧道协议,目前只有Linux支持 | 支持虚拟网卡,且可以禁用ARP响应 |
网络要求 | 局域网 | 局域网或广域网 | 局域网 |
支持的节点数 | 10~20个,视Director处理能力而定 | 可以支持到100个节点 | 可以支持到100个节点 |
安全性 | 较高,可隐藏real server | 较差,real server 容易暴露 | 较差,real server 容易暴露 |
IP要求 | 仅需要一个合法IP地址作为VIP | 除VIP外,每个服务器需要拥有合法IP地址可以直接路由至客户端 | 除VIP外,每个服务器需要拥有合法IP地址可以直接路由至客户端 |
拓展性 | 差 | 很好 | 好 |
特点 | 地址转换 | 封装IP | 修改MAC地址 |
引用自 lvs详解 - 胡杨的文章 - 知乎 https://zhuanlan.zhihu.com/p/445202915
1.2 LVS的调度算法
调度器把客户端发来的请求均衡地分发给后端的真实服务器,这是依靠预先设定好的调度算法实现的,在LVS中支持的调度算法主要有以下8种。
1. 轮询调度 (Round-Robin)
非常简单的一种调度算法。就是按顺序把请求依次发送给后端的服务器,它不管后端服务器的处理速度和响应时间怎样。当后端服务器性能不一致时,用这种调度算法就不合适了。
2. 带权重的轮询调度 (Weighted Round-Robin)
比第一种算法多了一个权重的设置,权重越高的服务器被分配到的请求就越多,这样后端服务器性能不一致时,就可以给配置低的服务器较小的权重。
3. 最小连接调度 (Least-Connection)
这种算法会根据各真实服务器上的连接数来决定把新的请求分配给谁,连接数少说明服务器是空闲的,这样把新的请求分配到空闲服务器上才更加合理。
4. 带权重最小连接调度 (Weight Least-Connection)
在最小连接调度的基础上再增加一个权重设置。这样就可以人为地去控制哪些服务器上多分配请求,哪些少分配请求。
5. 基于局部性的最少链接调度 (Locality-Based Least Connection)
这种算法简称LBLC,是针对请求报文的目标IP地址的负载均衡调度,目前主要用于Cache集群系统,因为在Cache集群中客户请求报文的目标IP地址是变化的。算法的设计目标是在服务器的负载基本平衡的情况下,将相同目标IP地址的请求调度到同一台服务器,来提高各台服务器的访问局部性和主存Cache命中率。
6. 带复制的基于局部性最少链接调度 (Locality-Based Least Connections with Replication)
该算法简称LBLCR,也是针对目标IP地址的负载均衡,它与LBLC算法的不同之处是:它要维护从一个目标IP地址到一组服务器的映射,面LBLC算法是维护从一个目标IP地址到一台服务器的映射。 LBLCR算法先根据请求的目标IP地址找出该目标IP地址对应的服务器组。按“最小连接”原则从该服务器组中选出一台服务器,若服务器没有超载,则将请求发送到该服务器;若服务器超载,则按“最小连接”原则从整个集群中选出一台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度。
7. 目标地址散列调度 (Destination Hashing)
该算法也是针对目标IP地址的负载均衡的,但它是一种静态映射算法,通过一个散列(hash)函数将一个目标IP地址映射到一台服务器。目标地址散列调度算法先根据请求的目标IP地址。作为散列键(hash key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。
8. 源地址散列调度 (Source Hashing)
该算法正好与目标地址散列调度算法相反,它根据请求的源IP地址,作为散列键从静态分配的散表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。它的算法流程与目标地址散列调度算法的基本相似,只不过将请求的目标IP地址换成请求的源IP地址。
对于以上8种调度算法前4种用得最多,也最容易理解,它们基本上能满足绝大多数的应用场景。
1.3 NAT模式LVS搭建
NET模式下,调度器需要有两个IP,一个公网IP一个内网IP,真实服务器只需要内网IP。此架构需要准备三台虚拟机。三台虚拟机的IP分配如下:
调度器dir:192.168.170.135(内网IP,vmware为NAT模式),192.168.13.128(公网IP,vmware仅主机模式)。
真实服务器rs1:192.168.170.143(内网IP)
真实服务器rs2:192.168.170.144(内网IP)
其中调度器上有两块网卡,作为内网的这块网卡使用的是NAT的网络,而作为“公网”的网卡使用的是仅主机网络。需要注意,所谓的公网其实仅仅是模拟的,并不是真正意义上的公网。在配置LVS之前,需要做一些准备工作。首先,真实服务器rs1(192.168.170.143)和rs2(192.168.170.144)上要把内网的网关设置为dir的内网IP(192.168.170.135),否则实验无法成功。然后,把三台服务器上的iptables规则清空并保存,命令如下:
1
2
|
iptables -F;iptables -t nat -F;service iptables save
|
1
|
yum install -y ipvsadm
|
继续在dir上编写一个脚本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
[root@dir ~]# vim /usr/local/sbin/lvs_nat.sh
#! /bin/bash
# director 服务器上开启路由转发功能
echo 1 > /proc/sys/net/ipv4/ip_forward
# 关闭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/ens33/send_redirects
echo 0 > /proc/sys/net/ipv4/conf/ens37/send_redirects
# director 设置nat防火墙
iptables -t nat -F
iptables -t nat -X
iptables -t nat -A POSTROUTING -s 192.168.170.0/24 -j MASQUERADE
# director设置ipvsadm
IPVSADM='/usr/sbin/ipvsadm'
$IPVSADM -C
$IPVSADM -A -t 192.168.13.128:80 -s wlc -p 300
$IPVSADM -a -t 192.168.13.128:80 -r 192.168.170.143:80 -m -w 1
$IPVSADM -a -t 192.168.13.128:80 -r 192.168.170.144:80 -m -w 1
|
脚本编写完成后,直接执行,命令如下:
1
|
[root@dir ~]# bash /usr/local/sbin/lvs_nat.sh
|
下面测试LVS的效果,如果dir上有Nginx服务器,需要先把它关闭,否则会影响实验效果
1
|
[root@dir ~]# killall nginx
|
为了更容易方便区分,分别需要给143、144设置一个默认主页,命令如下:
1
2
3
|
[root@rs1 ~]# echo "rs1" > /usr/share/nginx/html/index.html //143上执行
[root@rs2 ~]# echo "rs2" > /usr/local/nginx/html/index.html //144上执行
|
在dir上分别访问两个rs,如下所示:
1
2
3
4
|
[root@dir ~]# curl 192.168.170.143
rs1
[root@dir ~]# curl 192.168.170.144
rs2
|
运行结果如下图所示:
这样就区分了rs1和rs2,然后直接在dir上访问dir的外网(192.168.147.144),结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
[root@dir ~]# curl 192.168.147.144
rs2
[root@dir ~]# curl 192.168.147.144
rs2
[root@dir ~]# curl 192.168.147.144
rs2
[root@dir ~]# curl 192.168.147.144
rs2
[root@dir ~]# curl 192.168.147.144
rs2
[root@dir ~]# curl 192.168.147.144
rs2
[root@dir ~]# curl 192.168.147.144
rs2
|
连续多次访问,一直请求在rs2上,是因为脚本中有设置-p参数,理论上在300秒内会一直请求在rs2上。重新编辑/usr/local/sbin/lvs_nat.sh脚本把-p参数删除,然后再次测试,结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
[root@dir ~]# curl 192.168.147.144
rs2
[root@dir ~]# curl 192.168.147.144
rs1
[root@dir ~]# curl 192.168.147.144
rs2
[root@dir ~]# curl 192.168.147.144
rs1
[root@dir ~]# curl 192.168.147.144
rs2
[root@dir ~]# curl 192.168.147.144
rs1
|
运行结果如下图所示:
这样就做到了均衡访问。这样就做到
1.4 DR模式LVS搭建
DR模式需要三台虚拟机,三台虚拟机只需要有“公网”IP,但在这种模式下又多了一个VIP。对应的机器和IP如下:DR模式需要三台虚拟机:
调度器dir:192.168.170.135
真实服务器rs1:192.168.170.143
真实服务器rs2:192.168.170.144
VIP:192.168.170.110
首先把两台rs的网关改成原始网关,不能继续设置为dir的IP地址了。然后我们需要在dir上编写一个shell脚本,脚本内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
[root@dir ~]# vim /usr/local/sbin/lvs_dr.sh
#! /bin/bash
echo 1 > /proc/sys/net/ipv4/ip_forward
ipv=/usr/sbin/ipvsadm
vip=192.168.170.110
rs1=192.168.170.131
rs2=192.168.170.132
#注意这里的网卡名字
ifconfig ens33:2 $vip broadcast $vip netmask 255.255.255.255 up
route add -host $vip dev ens33:2
$ipv -C
$ipv -A -t $vip:80 -s wrr
$ipv -a -t $vip:80 -r $rs1:80 -g -w 1
$ipv -a -t $vip:80 -r $rs2:80 -g -w 1
|
两台rs上也需要编写脚本,脚本内容如下:
1
2
3
4
5
6
7
8
9
10
11
|
[root@rs1 ~]# vim /usr/local/sbin/lvs_rs.sh //两台rs上添加的内容一致
#/bin/bash
vip=192.168.170.110
#把vip绑定在lo上,是为了实现rs直接把结果返回给客户端
ifconfig lo:0 $vip broadcast $vip netmask 255.255.255.255 up
route add -host $vip lo:0
#以下操作为更改arp内核参数,目的是为了让rs顺利发送mac地址给客户端
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
|
分别在三台机器上执行各自脚本;
1
2
3
4
|
[root@dir ~]# bash /usr/local/sbin/lvs_dr.sh
[root@rs1 ~]# bash /usr/local/sbin/lvs_rs.sh
[root@rs2 ~]# bash /usr/local/sbin/lvs_rs.sh
|
执行完三个脚本后,就可以测试了。但这次不可以直接在dir上用curl命令直接测试了,因为VIP在三台机器上都有设置。所以只能用浏览器来测试结果
1.5 keepalived + LVS
LVS架构中,不管是NAT模式还是DR模式,当后端的RS宕掉时,调度器依然会把请求转发到宕掉的RS上,这样的结果并不是我们想要的。其实,keepalived就可以解决该问题,它不仅仅有高可用的功能,还有负载均衡的功能。在调度器上只要安装了keepalived,就不用再安装ipvsadm了,也不用去编写LVS相关的脚本了,也就是说keepalived已经嵌人了LVS功能。完整的keepalived+LVS架构需要有两台调度器实现高可用,提供调度服务的只需要一台,另外一台作为备用。
为了节省资源,我们只设置一台主keepalived,备用的暂时就省略掉了。下面为各机器的角色和IP。
主keepalived(调度器):192.168.170.135
真实服务器rs1:192.168.170.131
真实服务器rs2:192.168.170.132
VIP:192.168.200.110
如果你的机器上还未安装过keepalived,则需要先安装,直接yum
install -y keepalived即可。下面编辑keepalived的配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
[root@dir ~]# > /etc/keepalived/keepalived.conf //清空配置文件
[root@dir ~]# vim /etc/keepalived/keepalived.conf //添加内容如下
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.170.110
}
}
virtual_server 192.168.170.110 80 { #VIP
delay_loop 10 #每隔10秒查询realserver状态
lb_algo wlc #lvs算法
lb_kind DR #DR模式
persistence_timeout 60 #(同一IP的连接60秒内被分配到同一台realserver)
protocol TCP #用TCP协议检查realserver状态
real_server 192.168.171.143 80 { #真实服务器ip
weight 100 #权重
TCP_CHECK {
connect_timeout 10 # 10秒无响应超时(连接超时时间)
nb_get_retry 3 #失败重试次数
delay_before_retry 3 #失败重试的间隔时间
connect_port 80 #连接的后端端口
}
}
real_server 192.168.170.144 80 {
weight 100
TCP_CHECK {
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
}
|
由于上一节刚刚执行过LVS的脚本,所以需要做一些操作:
1
2
3
|
[root@dir ~]# ipvsadm -C //把之前的ipvsadm规则清空
[root@dir ~]# systemctl restart network //可以把之前设置的VIP删除掉
|
因为我们在keepalived的配置文件中定义的LVS模式为DR模式,所以还需要在两台rs上执行lvs_rs.sh脚本,这个脚本就是上一节设置的脚本。
1
2
|
[root@rs1 ~]# sh /usr/local/sbin/lvs_rs.sh
[root@rs2 ~]# sh /usr/local/sbin/lvs_rs.sh
|
做完准备工作后,在130上启动keepalived服务:
1
2
3
4
5
6
7
|
[root@dir ~]# systemctl start keepalived
[root@dir ~]# ps aux |grep keepalived
root 14062 0.0 0.1 118684 1388 ? Ss 15:26 0:00 /usr/sbin/keepalived -D
root 14063 0.0 0.2 122884 2388 ? S 15:26 0:00 /usr/sbin/keepalived -D
root 14064 0.0 0.2 122884 2412 ? S 15:26 0:00 /usr/sbin/keepalived -D
root 14066 0.0 0.0 112720 984 pts/1 R+ 15:26 0:00 grep --color=auto keepalived
|
检验是否成功的方法也很简单,需要在浏览器直接访问vip192.168.170.110,然后故意把其中一台 rs的Nginx服务关掉,比如说关闭143的;然后再刷新浏览器看结果,刷新的时候需要使用组合键(Ctrl+F5)强制刷新浏览器,这样就不会有缓存数据了。同时,也可以在调度器(135)上执行命令ipvsadm
-ln查看连接数:
1
2
3
4
5
6
7
|
[root@dir ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.170.110:80 wrr
-> 192.168.170.143:80 Route 1 0 0
|
对应的rs只有一台143,然后再把144的Nginx服务启动,再来查看:
1
2
3
4
5
6
7
|
[root@dir ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.170.110:80 wrr
-> 192.168.170.143:80 Route 1 0 0
-> 192.168.170.144:80 Route 100 0
|