Just Do IT !

HA高可用与负载均衡入门到实战(七)---- 基于Docker配置KeepAlive-LVS负载均衡

字数统计: 4.8k阅读时长: 19 min
2020/05/05 Share

实验要求

1、 安装配置LVS负载均衡
2、 安装配置LVS高可用负载均衡

拓扑图:
在这里插入图片描述

LVS介绍

负载均衡工作模式

1. NAT模式

Virtualserver via Network address translation(VS/NAT) 这个是通过网络地址转换的方法来实现调度的。

首先调度器(LB)接收到客户的请求数据包时(请求的目的IP为VIP),根据调度算法决定将请求发送给哪个后端的真实服务器(RS)。然后调度就把客户端发送的请求数据包的目标IP地址及端口改成后端真实服务器的IP地址(RIP),这样真实服务器(RS)就能够接收到客户的请求数据包了。真实服务器响应完请求后,查看默认路由(NAT模式下我们需要把RS的默认路由设置为LB服务器。)把响应后的数据包发送给LB,LB再接收到响应包后,把包的源地址改成虚拟地址(VIP)然后发送回给客户端。

调度过程IP包详细图:
在这里插入图片描述
原理图简述:

  1. 客户端请求数据,目标IP为VIP

  2. 请求数据到达LB服务器,LB根据调度算法将目的地址修改为RIP地址及对应端口(此RIP地址是根据调度算法得出的。)并在连接HASH表中记录下这个连接。

  3. 数据包从LB服务器到达RS服务器webserver,然后webserver进行响应。Webserver的网关必须是LB,然后将数据返回给LB服务器。
  4. 收到RS的返回后的数据,根据连接HASH表修改源地址VIP&目标地址CIP,及对应端口80.然后数据就从LB出发到达客户端。
  5. 客户端收到的就只能看到VIP\DIP信息。

    NAT模式优缺点:

  • NAT技术将请求的报文和响应的报文都需要通过LB进行地址改写,因此网站访问量比较大的时候LB负载均衡调度器有比较大的瓶颈,一般要求最多只能10-20台节点
  • 只需要在LB上配置一个公网IP地址就可以
  • 每台内部的节点服务器的网关地址必须是调度器LB的内网地址
  • NAT模式支持对IP地址和端口进行转换。即用户请求的端口和真实服务器的端口可以不一致

在这里插入图片描述

  1. 客户端将请求发往前端的负载均衡器,请求报文源地址是CIP(客户端IP),后面统称为CIP),目标地址为VIP(负载均衡器前端地址,后面统称为VIP)

  2. 负载均衡器收到报文后,发现请求的是在规则里面存在的地址,那么它将客户端请求报文的目标地址改为了后端服务器的RIP地址并将报文根据算法发送出去

  3. 报文送到Real Server后,由于报文的目标地址是自己,所以会响应该请求,并将响应报文返还给LVS。

  4. 然后lvs将此报文的源地址修改为本机并发送给客户端。

优点: 集群中的物理服务器可以使用任何支持TCP/IP操作系统,只有负载均衡器需要一个合法的IP地址。
缺点: 扩展性有限。当服务器节点(普通PC服务器)增长过多时,负载均衡器将成为整个系统的瓶颈,因为所有的请求包和应答包的流向都经过负载均衡器。当服务器节点过多时,大量的数据包都交汇在负载均衡器那,速度就会变慢

2. TUN(隧道)模式

virtual server via ip tunneling模式:采用NAT模式时,由于请求和响应的报文必须通过调度器地址重写,当客户请求越来越多时,调度器处理能力将成为瓶颈。为了解决这个问题,调度器把请求的报文通过IP隧道转发到真实的服务器。真实的服务器将响应处理后的数据直接返回给客户端。这样调度器就只处理请求入站报文,由于一般网络服务应答数据比请求报文大很多,采用VS/TUN模式后,集群系统的最大吞吐量可以提高10倍。 VS/TUN的工作流程图如下所示,它和NAT模式不同的是,它在LB和RS之间的传输不用改写IP地址。而是把客户请求包封装在一个IP tunnel里面,然后发送给RS节点服务器,节点服务器接收到之后解开IP tunnel后,进行响应处理。并且直接把包通过自己的外网地址发送给客户不用经过LB服务器。

Tunnel原理流程图:
在这里插入图片描述
原理图过程简述:

  1. 客户请求数据包,目标地址VIP发送到LB上。
  2. LB接收到客户请求包,进行IP Tunnel封装。即在原有的包头加上IP Tunnel的包头。然后发送出去。
  3. RS节点服务器根据IP Tunnel包头信息(此时就又一种逻辑上的隐形隧道,只有LB和RS之间懂)收到请求包,然后解开IP Tunnel包头信息,得到客户的请求包并进行响应处理。
  4. 响应处理完毕之后,RS服务器使用自己的出公网的线路,将这个响应数据包发送给客户端。源IP地址还是VIP地址

在这里插入图片描述

  1. 客户端将请求发往前端的负载均衡器,请求报文源地址是CIP,目标地址为VIP。
  2. 负载均衡器收到报文后,发现请求的是在规则里面存在的地址,那么它将在客户端请求报文的首部再封装一层IP报文,将源地址改为DIP,目标地址改为RIP,并将此包发送给RS。
  3. RS收到请求报文后,会首先拆开第一层封装,然后发现里面还有一层IP首部的目标地址是自己lo接口上的VIP,所以会处理次请求报文,并将响应报文通过lo接口送给eth0网卡直接发送给客户端。

注意: 需要设置lo接口的VIP不能在共网上出现。

总结:

  1. TUNNEL 模式必须在所有的 realserver 机器上面绑定 VIP 的 IP 地址
  2. TUNNEL 模式的 vip ——>realserver 的包通信通过 TUNNEL 模式,不管是内网和外网都能通信,所以不需要 lvs vip 跟 realserver 在同一个网段内
  3. TUNNEL 模式 realserver 会把 packet 直接发给 client 不会给 lvs 了
  4. TUNNEL 模式走的隧道模式,所以运维起来比较难,所以一般不用。

优点: 负载均衡器只负责将请求包分发给后端节点服务器,而RS将应答包直接发给用户。所以,减少了负载均衡器的大量数据流动,负载均衡器不再是系统的瓶颈,就能处理很巨大的请求量,这种方式,一台负载均衡器能够为很多RS进行分发。而且跑在公网上就能进行不同地域的分发。

缺点: 隧道模式的RS节点需要合法IP,这种方式需要所有的服务器支持”IP Tunneling”(IP Encapsulation)协议,服务器可能只局限在部分Linux系统上。

3. DR模式(直接路由模式)

Virtual server via direct routing (vs/dr) DR模式是通过改写请求报文的目标MAC地址,将请求发给真实服务器的,而真实服务器响应后的处理结果直接返回给客户端用户。同TUN模式一样,DR模式可以极大的提高集群系统的伸缩性。而且DR模式没有IP隧道的开销,对集群中的真实服务器也没有必要必须支持IP隧道协议的要求。但是要求调度器LB与真实服务器RS都有一块网卡连接到同一物理网段上,必须在同一个局域网环境。 DR模式是互联网使用比较多的一种模式。

DR模式原理图:
在这里插入图片描述
DR模式原理过程简述:

VS/DR模式的工作流程图如上图所示,它的连接调度和管理与NAT和TUN中的一样,它的报文转发方法和前两种不同。DR模式将报文直接路由给目标真实服务器。在DR模式中,调度器根据各个真实服务器的负载情况,连接数多少等,动态地选择一台服务器,不修改目标IP地址和目标端口,也不封装IP报文,而是将请求报文的数据帧的目标MAC地址改为真实服务器的MAC地址。然后再将修改的数据帧在服务器组的局域网上发送。因为数据帧的MAC地址是真实服务器的MAC地址,并且又在同一个局域网。那么根据局域网的通讯原理,真实复位是一定能够收到由LB发出的数据包。真实服务器接收到请求数据包的时候,解开IP包头查看到的目标IP是VIP。(此时只有自己的IP符合目标IP才会接收进来,所以我们需要在本地的回环借口上面配置VIP。

另:由于网络接口都会进行ARP广播响应,但集群的其他机器都有这个VIP的lo接口,都响应就会冲突。所以我们需要把真实服务器的lo接口的ARP响应关闭掉。)然后真实服务器做成请求响应,之后根据自己的路由信息将这个响应数据包发送回给客户,并且源IP地址还是VIP。

DR模式小结:

  1. 通过在调度器LB上修改数据包的目的MAC地址实现转发。注意源地址仍然是CIP,目的地址仍然是VIP地址。
  2. 请求的报文经过调度器,而RS响应处理后的报文无需经过调度器LB,因此并发访问量大时使用效率很高(和NAT模式比)
  3. 因为DR模式是通过MAC地址改写机制实现转发,因此所有RS节点和调度器LB只能在一个局域网里面
  4. RS主机需要绑定VIP地址在LO接口上,并且需要配置ARP抑制。
  5. RS节点的默认网关不需要配置成LB,而是直接配置为上级路由的网关,能让RS直接出网就可以。
  6. 由于DR模式的调度器仅做MAC地址的改写,所以调度器LB就不能改写目标端口,那么RS服务器就得使用和VIP相同的端口提供服务

在这里插入图片描述

  1. 客户端将请求发往前端的负载均衡器,请求报文源地址是CIP,目标地址为VIP。
  2. 负载均衡器收到报文后,发现请求的是在规则里面存在的地址,那么它将客户端请求报文的源MAC地址改为自己DIP的MAC地址,目标MAC改为了RIP的MAC地址,并将此包发送给RS。
  3. RS发现请求报文中的目的MAC是自己,就会将次报文接收下来,处理完请求报文后,将响应报文通过lo接口送给eth0网卡直接发送给客户端。

注意: 需要设置lo接口的VIP不能响应本地网络内的arp请求。

总结:

  1. 通过在调度器 LB 上修改数据包的目的 MAC 地址实现转发。注意源地址仍然是 CIP,目的地址仍然是 VIP 地址。
  2. 请求的报文经过调度器,而 RS 响应处理后的报文无需经过调度器 LB,因此并发访问量大时使用效率很高(和 NAT 模式比)
  3. 因为 DR 模式是通过 MAC 地址改写机制实现转发,因此所有 RS 节点和调度器 LB 只能在一个局域网里面
  4. RS 主机需要绑定 VIP 地址在 LO 接口(掩码32 位)上,并且需要配置 ARP 抑制。
  5. RS 节点的默认网关不需要配置成 LB,而是直接配置为上级路由的网关,能让 RS 直接出网就可以。
  6. 由于 DR 模式的调度器仅做 MAC 地址的改写,所以调度器 LB 就不能改写目标端口,那么 RS 服务器就得使用和 VIP 相同的端口提供服务。
  7. 直接对外的业务比如WEB等,RS 的IP最好是使用公网IP。对外的服务,比如数据库等最好使用内网IP。

优点:
和TUN(隧道模式)一样,负载均衡器也只是分发请求,应答包通过单独的路由方法返回给客户端。与VS-TUN相比,VS-DR这种实现方式不需要隧道结构,因此可以使用大多数操作系统做为物理服务器。 DR模式的效率很高,但是配置稍微复杂一点,因此对于访问量不是特别大的公司可以用haproxy/nginx取代。日1000-2000W PV或者并发请求1万一下都可以考虑用haproxy/nginx。

缺点: 所有 RS 节点和调度器 LB 只能在一个局域网里面。

在LVS1配置LVS负载均衡

1. 使用centos镜像生成lvs-keep镜像

  1. 启动centos容器并进入
    docker run -d --privileged centos:v1 /usr/sbin/init
    2) 在centos容器中使用yum方式安装lvs和keepalived
    1
    2
    yum install ipvsadm
    yum install keepalived

3) 保存容器为镜像
docker commit 容器ID lvs-keep

2. 使用nginx镜像启动nginx1和nginx2两个容器

1) 创建docker网络
docker network create --subnet=172.18.0.0/16 cluster
2) 查看宿主机上的docker网络类型种类
docker network ls
3) 启动容器nginx1,nginx2 设定地址为172.18.0.11, 172.18.0.12
docker run -d --privileged --net cluster --ip 172.18.0.11 --name nginx1 nginx /usr/sbin/init
docker run -d --privileged --net cluster --ip 172.18.0.12 --name nginx2 nginx /usr/sbin/init

1
2
3
4
5
[root@localhost ~]# docker run -d --privileged --net cluster --ip 172.18.0.11 --name nginx1 nginx  /usr/sbin/init
8deb9befa966726e16bee8fb4a8eb63ef0c47d66f507092b3bad63e11a348ffd
[root@localhost ~]# docker run -d --privileged --net cluster --ip 172.18.0.12 --name nginx2 nginx /usr/sbin/init
f2fbc74a948461060345899ffd5d0e4e82b7012e2fff793daca3aa78fa4e90b9
[root@localhost ~]#

3. 使用lvs-keep镜像启用LVS1容器,配置LVS负载均衡

在宿主机上安装ipvsadm yum install ipvsadm # modprobe ip_vs //装入ip_vs模块
1) 启动容器LVS1,设定地址为172.18.0.8
docker run -d --privileged --net cluster --ip 172.18.0.8 --name LVS1 lvs-keep /usr/sbin/init
2) 进入LVS1容器
lsmod |grep ip_vs 列出装载的模块

1
2
3
4
[root@58a00cfe8c9d /]# lsmod | grep ip_vs
ip_vs 145497 0
nf_conntrack 139224 7 ip_vs,nf_nat,nf_nat_ipv4,xt_conntrack,nf_nat_masquerade_ipv4,nf_conntrack_netlink,nf_conntrack_ipv4
libcrc32c 12644 4 xfs,ip_vs,nf_nat,nf_conntrack

3) 在LVS1创建VIP调度地址
ifconfig eth0:0 172.18.0.10 netmask 255.255.255.255
4) 在LVS1创建虚拟服务器,使用轮询方式:
ipvsadm -At 172.18.0.10:80 -s rr
5) 在LVS1添加nginx1和nginx2两台服务器节点,采用DR直接路由模式
ipvsadm -at 172.18.0.10:80 -r 172.18.0.11:80 -g
ipvsadm -at 172.18.0.10:80 -r 172.18.0.12:80 -g

1
2
3
4
5
6
7
8
9
10
11
12
[root@58a00cfe8c9d /]# ifconfig eth0:0 172.18.0.10  netmask 255.255.255.255
[root@58a00cfe8c9d /]# ipvsadm -At 172.18.0.10:80 -s rr
[root@58a00cfe8c9d /]# ipvsadm -at 172.18.0.10:80 -r 172.18.0.11:80 -g
[root@58a00cfe8c9d /]# ipvsadm -at 172.18.0.10:80 -r 172.18.0.12:80 -g
[root@58a00cfe8c9d /]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.18.0.10:80 rr
-> 172.18.0.11:80 Route 1 0 0
-> 172.18.0.12:80 Route 1 0 0
[root@58a00cfe8c9d /]#

6) 在nginx1和nginx2两台服务器节点,创建VIP应答地址
ifconfig lo:0 172.18.0.10 netmask 255.255.255.255
7) 在nginx1和nginx2两台服务器节点,屏蔽ARP请求

1
2
3
4
echo "1" > /proc/sys/net/ipv4/conf/lo/arp_ignore 
echo "1" > /proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" > /proc/sys/net/ipv4/conf/lo/arp_announce
echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce

8) 在LVS1中,ipvsadm -L 检查配置情况

1
2
3
4
5
6
7
8
[root@58a00cfe8c9d /]# ipvsadm -L                                       
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 58a00cfe8c9d:http rr
-> nginx1.cluster:http Route 1 0 0
-> nginx2.cluster:http Route 1 0 0
[root@58a00cfe8c9d /]#

9) 在宿主机中访问http://172.18.0.10,刷新时轮流访问两台节点服务器

1
2
3
4
5
[root@localhost ~]# curl 172.18.0.10
nginx2
[root@localhost ~]# curl 172.18.0.10
nginx1
[root@localhost ~]#

使用KeepAlive配置LVS高可用

在两台LVS服务器安装配置KeepAlive,使得两台服务器互为备份并支持负载均衡
保持任务一中nginx1和nginx2两台服务器节点不变,重新启动容器LVS1和LVS2

1. 使用lvs-keep镜像启用LVS1和LVS2容器,配置LVS负载均衡

注意:需要在宿主机安装ipvsadm,# modprobe ip_vs //装入ip_vs模块
1) 启动容器LVS1,设定地址为172.18.0.8
docker run -d --privileged --net cluster --ip 172.18.0.8 --name LVS1 lvs-keep /usr/sbin/init
2) 启动容器LVS2,设定地址为172.18.0.9
docker run -d --privileged --net cluster --ip 172.18.0.9 --name LVS2 lvs-keep /usr/sbin/init
3) 编辑LVS1和LVS2中/etc/ keepalived /keepalived.conf文件

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
45
46
47
48
49
50
51
52
53
! Configuration File for keepalived
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS1
vrrp_skip_check_adv_addr #跳过vrrp报文地址检查
#vrrp_strict #严格遵守vrrp协议
vrrp_garp_interval 3 #在一个网卡上每组gratuitous arp消息之间的延迟时间,默认为0
vrrp_gna_interval 3 #在一个网卡上每组na消息之间的延迟时间,默认为0
}
vrrp_instance VI_1 {
state MASTER #LVS2设置为BACKUP
interface eth0
virtual_router_id 51
priority 100 #L 设置权重
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.18.0.10
}
}
virtual_server 172.18.0.10 80 { #配置虚拟服务器
delay_loop 6 #设置健康检查时间,单位是秒
lb_algo rr #设置负载调度算法,默认为rr即轮询算法
lb_kind DR #设置LVS实现LB机制,有NAT、TUNN和DR三个模式可选
persistence_timeout 0 #会话保持时间,单位为秒,设为0可以看到刷新效果
protocol TCP #指定转发协议类型,有TCP和UDP两种
real_server 172.18.0.11 80 { #配置服务器节点
weight 1
TCP_CHECK { #配置节点权值,数字越大权值越高
connect_timeout 3 #超时时间
retry 3 #重试次数
delay_before_retry 3 #重试间隔
}
}
real_server 172.18.0.12 80 {
weight 1
TCP_CHECK {
connect_timeout 3
retry 3
delay_before_retry 3
}
}
}

2. 验证KeepAlive配置LVS高可用集群

1) 在两台服务器重启keepalived服务,ipvsadm -L检查配置情况

1
2
3
4
5
6
7
8
[root@ef99a927fc2d /]# ipvsadm  -L
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.18.0.10:http rr
-> nginx1.cluster:http Route 1 0 0
-> nginx2.cluster:http Route 1 0 0
[root@ef99a927fc2d /]#

1
2
3
4
5
6
7
[root@a033e26a1fd8 /]# ipvsadm  -L
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP a033e26a1fd8:http rr
-> nginx1.cluster:http Route 1 0 0
-> nginx2.cluster:http Route 1 0 0

2) 在宿主机中访问http://172.18.0.10,刷新时轮流访问两台节点服务器

1
2
3
4
5
[root@localhost ~]# curl 172.18.0.10
nginx2
[root@localhost ~]# curl 172.18.0.10
nginx1
[root@localhost ~]#

3) 在LVS1服务器#ifconfig eth0 down //当掉服务器网卡

4) 在宿主机中访问http://172.18.0.10,刷新时轮流访问两台节点服务器

5) 在LVS2中,#ipvsadm -L //检查配置和连接情况
lvs2中可以看到InActConn增加

因为lvs1将eth0关闭以后, 有lvs2接管服务

1
2
3
4
5
6
7
8
[root@ef99a927fc2d /]# ipvsadm  -L
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP ef99a927fc2d:http rr
-> nginx1.cluster:http Route 1 0 3
-> nginx2.cluster:http Route 1 0 3
[root@ef99a927fc2d /]#

CATALOG
  1. 1. 实验要求
  2. 2. LVS介绍
    1. 2.1. 负载均衡工作模式
      1. 2.1.1. 1. NAT模式
      2. 2.1.2. 2. TUN(隧道)模式
      3. 2.1.3. 3. DR模式(直接路由模式)
  3. 3. 在LVS1配置LVS负载均衡
    1. 3.1. 1. 使用centos镜像生成lvs-keep镜像
    2. 3.2. 2. 使用nginx镜像启动nginx1和nginx2两个容器
    3. 3.3. 3. 使用lvs-keep镜像启用LVS1容器,配置LVS负载均衡
  4. 4. 使用KeepAlive配置LVS高可用
    1. 4.1. 1. 使用lvs-keep镜像启用LVS1和LVS2容器,配置LVS负载均衡
    2. 4.2. 2. 验证KeepAlive配置LVS高可用集群