集群之LVS(负载均衡)详解

时间:2022-04-23 02:50:37

 提高服务器响应能力的方法

scale on  在原有服务器的基础上进行升级或者直接换一台新的性能更高的服务器。

scale out  横向扩展,将多台服务器并发向外响应客户端的请求。优点:成本低,扩展架构比较简单。

集群(Cluster),通俗地讲就是按照某种组织方式将几台电脑组织起来完成某种特定任务的这样一种架构。

三种集群类型:

LB,Load Balancing 负载均衡:在一定程度上能够实现高可用的目的。

HA,High Availability 高可用:实时在线,能够及时响应客户端请求,企业应用要求达到

     7*24小时,99.999%时间在线。

HP,High Performance 高性能 提供大量超级运算能力的集群。

LB 负载均衡架构:

Director(dispatcher):负责接收客户端请求,并将请求按照某种算法分发到后台真正提供服务的服务器上。既可以基于硬件(F5)来实现,也可以基于软件来实现。基于软件实现的又分为四层交换:基于IP地址和端口号组合起来对服务做重定向(LVS)。七层交换:通常指的是反向代理(proxy),例如:squid。

LVS:Linux Virtual  Server

类似于iptables的架构,在内核中有一段代码用于实时监听数据包来源的请求,当数据包到达端口时做一次重定向。这一系列的工作必须在内核中实现。在内核中实现数据包请求处理的代码叫做ipvs。ipvs仅仅提供了功能框架,还需要自己手动定义是数据对哪个服务的请求,

而这种定义需要通过写规则来实现,写规则的工具就称为ipvsadm。

应用场景

高吞吐量(higher throughput)

冗余    (redundancy)

适应性  (adaptability)   

集群之LVS(负载均衡)详解

                                LVS负载均衡架构 

Virtual IP(VIP)address:Director用来向客户端提供服务的IP地址

Real IP (RIP) address:集群节点(后台真正提供服务的服务器)所使用的IP地址

Director's IP (DIP) address:Director用来和D/RIP 进行联系的地址

Client computer's IP (CIP) address:公网IP,客户端使用的IP。

根据前端Director和后台Real Server的通信方式将LVS分为三类:

Network Address Translation(LVS-NAT)

集群之LVS(负载均衡)详解

目标地址转换 所有客户端的请求都被Director根据访问请求和算法被定向到后台的Real Server 上。

数据包地址转换过程:

S:CIP D:VIP------->Director------>S:CIP D:RIP------>Real Server------>

----->S:RIP  D:CIP----->Director----->S:VIP  D:CIP                                      

Director和Real Server必须在同一个网段中;

一般情况下,RIP是私有地址,只用于集群内部节点间通信;

Director 会响应所有的请求在客户端和Real Server之间,所承担的负载较大;

所有的Real IP 网关必须指向DIP以响应客户端请求;

Director可以重映射网络端口,即前端使用标准端口,后端可以使用非标准端口;

后台的Real Server可以使用任何操作系统;

Director可能会成为系统瓶颈。

Director routing (LVS-DR )

集群之LVS(负载均衡)详解

直接路由 客户端请求经过Director,Real Server直接回应客户端

数据包地址转换过程:

S:CIP D:VIP----->Director--->S:CIP D:RIP -----> Real Server---> S:VIP D:CIP

Real Server 上必须配置VIP切需要隐藏起来,只有在响应客户端请求时才使用VIP作为源地址,除此之外并不使用此VIP。

集群节点和Director必须在同一个网络中;

RIP不要求为私有地址;

Director仅处理所有进来的请求;

Real Server 不能以DIP作为网关,而是以公网上的某台路由器作为网关;

Director 不能再使用端口重映射;

大多数操作系统可以被用来作为Real Server,windows除外;

LVS-DR模式可以处理比LVS-NAT更多的请求。

实际生产环境中最常用的一种方式,优点:

RIP 为公网地址,管理员可以远程连接Real Server来查看工作状态;

一旦Director 宕机,可以通过修改DNS记录将A记录指向RIP 继续向外提供服务;

IP tunneling (LVS-TUN )

集群之LVS(负载均衡)详解

与DR的网络结构一样,但Director和Real Server可以在不同的网络当中,可以实现异地容灾的功能。DIP----->VIP 基于隧道来传输,在数据包外层额外封装了S:DIP D :RIP 的地址。

Director和Real Server 必须在同一个物理网络中;

RIP一定不能是私有地址;

Director只负责处理进来的数据包;

Real Server直接将数据包返回给客户端,所以Real Server默认网关不能是DIP,必须是公网上某个路由器的地址;

Director不能做端口重映射;

只有支持隧道协议的操作系统才能作为Real Server。

分发时所采用的算法

固定调度算法:按照某种既定的算法,不考虑实时的连接数予以分配。

Round-robin(RR)轮询:当新请求到达时候,从服务列表中选择一个Real Server,将请求重定向给这台Real Server。

Weighted round-robin(WRR)加权轮询:给每台Real Server分配一个权重/位列,权重越大,分到的请求数越多。

Destination hashing (DH)目标散列:来自于同一个IP地址的请求都被重定向到同一台Real Server上(保证目标地址不变)。

Source hashing(SH)源地址散列:Director必须确保响应的数据包必须通过请求数据包所经过的路由器或者防火墙(保证原地址不变)。

动态调度算法:通过检查服务器上当前连接的活动状态来重新决定下一步调度方式该如何实现。

Lease Connection (LC) 最少连接  哪一个Real Server上的连接数少就将下一个连接请求定向到那台Real Server上去。 【算法:连接数=活动连接数*256+非活动连接数】

Weight Least-Connection(WLC) 加权最少连接  在最少连接的基础上给每台Real Server分配一个权重。 【算法:连接数=(活动连接数*256+非活动连接数)÷权重】 一种比较理想的算法。

Shortest Expected Delay (SED)  最短期望延迟 不再考虑非活动连接数

             【算法:连接数=(活动连接数+1) *256 ÷权重】

Never Queue (NQ) 永不排队算法,对SED的改进,当新请求过来的时候不仅要取决于SED算法所得到的值,还要取决于Real Server上是否有活动连接。

Locality-Based Least-Connection  (LBLC) 基于本地状态的最少连接,在DH算法的基础上还要考虑服务器上的活动连接数。

Locality-Based Least-Connection  with  Replication  Scheduling  (LBLCR) 带复制的基于本地的最少连接  LBLC算法的改进

下面我们就来做一个基于LVS-NAT的负载均衡实验:

集群之LVS(负载均衡)详解

实验环境搭建:

Director :VIP192.168.0.127 桥接  

          DIP192.168.10.1 仅主机

Real Server 1:RIP 192.168.10.2   仅主机   网关指向:192.168.10.1

Real Server 2:RIP 192.168.10.3   仅主机   网关指向:192.168.10.1

Client:192.168.0.1   物理机

每台Real Server上分别安装有http服务。我们这里为了演示效果,每个http服务的页面不同。

Real Server 1

[root@station39 html]# ifconfig eth0 192.168.10.2

[root@station39 html]# route add default gw 192.168.10.1

Real Server 2

[root@station26 html]# ifconfig eth0 192.168.10.3

[root@station26 html]# route add default gw 192.168.10.1

Director :

[root@server27 ~]# ifconfig eth1 192.168.10.1

打开内核路由功能

[root@server27 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward

确保永久有效:

[root@server27 ~]# vim /etc/sysctl.conf

# Controls IP packet forwarding

net.ipv4.ip_forward = 1

[root@server27 ~]# sysctl -p

net.ipv4.ip_forward = 1

net.ipv4.conf.default.rp_filter = 1

net.ipv4.conf.default.accept_source_route = 0

kernel.sysrq = 0

kernel.core_uses_pid = 1

net.ipv4.tcp_syncookies = 1

kernel.msgmnb = 65536

kernel.msgmax = 65536

kernel.shmmax = 4294967295

kernel.shmall = 268435456

OK,准备工作已经就绪,下面开始实验的关键步骤:

[root@server27 ~]# yum install ipvsadm -y

使用步骤:1.定义服务 2 .为服务定义Real Server

[root@server27 ~]# ipvsadm -A -t 192.168.0.127:80 -s rr

[root@server27 ~]# 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.0.127:80 rr

[root@server27 ~]# ipvsadm -a -t 192.168.0.127:80 -r 192.168.10.2 -m -w 2

[root@server27 ~]# ipvsadm -a -t 192.168.0.127:80 -r 192.168.10.3 -m -w 5

-g,  --gatewaying      Use gatewaying (direct routing). This is the  default.

-i,   --ipip           Use ipip encapsulation (tunneling).

-m,  --masquerading   Use masquerading  (network  access  transla-tion, or NAT).

PS:在这里设定的权重对于RR算法来说并没有什么意义,我们只是为后面的实验而设定的。

[root@server27 ~]# 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.0.127:80 rr

  -> 192.168.10.3:80              Masq    5      0          16       

  -> 192.168.10.2:80              Masq    2      0          15  

此时,我们使用物理机访问192.168.0.127就会发现页面交替变化,这是由RR算法的特性决定的。

我们改变为WRR算法试试:

[root@server27 ~]# ipvsadm -E -t 192.168.0.127:80 -s wrr

[root@server27 ~]# 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.0.127:80 wrr

  -> 192.168.10.3:80              Masq    5      0          86       

  -> 192.168.10.2:80              Masq    2      0          43

改变为LBLC算法试试:

LBLC:基于本地状态的最少连接,在DH算法的基础上还要考虑服务器上的活动连接数。

[root@server27 ~]# ipvsadm -E -t 192.168.0.127:80 -s lblc

[root@server27 ~]# 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.0.127:80 lblc

  -> 192.168.10.3:80              Masq    5      0          112      

  -> 192.168.10.2:80              Masq    2      0          41    

此时无论客户端怎么刷新,访问页面都不会改变。

保存规则:

ipvsadm -S >>/etc/sysconfig/ipvs-config  ==  ipvsadm-save

ipvsadm -R < /etc/sysconfig/ipvs-config == ipvsadm-restore

Director routing (LVS-DR )

PS:Director分发到Real Server的过程中,数据包的源地址和目标地址都没有发生改变,Director仅仅是将目标mac地址转换成某台Real Server的mac地址,源mac地址改为Director内网网卡的mac地址。

两个技术难题

1  Real Server要避免对客户端发来的对VIP的arp地址解析请求;

   解决方法

1)  修改内核的两个参数:arp_announce, arp_ignore。

arp_announce :定义不同级别:当ARP请求通过某个端口进来是否利用这个接口来回应。

         0 - (default) Use any local address, configured on any interface.

          利用本地的任何地址,不管配置在哪个接口上去响应ARP请求;

         1 - Try to avoid local addresses that are not in the target's subnet for this interface.

           避免使用另外一个接口上的mac地址去响应ARP请求;

         2 - Always use the best local address for this target.

           尽可能使用能够匹配到ARP请求的最佳地址。

arp_ignore:当ARP请求发过来后发现自己正是请求的地址是否响应;

     0 - (default): reply for any local target IP address, configured on any interface

       利用本地的任何地址,不管配置在哪个接口上去响应ARP请求;

     1 - reply only if the target IP address is local address configured on the incoming   

       interface.

      哪个接口上接受ARP请求,就从哪个端口上回应。

PS:对linux来说IP地址属于系统而不属于某个接口。

2)  Red Hat 提供了arptables工具,利用arp防火墙也可以实现。

2  当Real Server内网网卡响应客户端请求时,要以VIP作为源地址,不能以RIP作为源地址。

解决方法

添加一条路由:route add -host 192.168.0.127 dev lo:0使客户端访问VIP,就让VIP来响应客户端。这样避免了使用RIP作为源地址。

Director:VIP:响应客户端请求;

         DIP:与RIP彼此间实现arp解析,并将客户端的请求转发给Real Server。

集群之LVS(负载均衡)详解

实验环境搭建:

Director :eth0:0  VIP192.168.0.127  

          eth0    DIP192.168.0.10 桥接

Real Server 1: eth0  RIP 192.168.0.12   桥接

              lo:0  VIP 192.168.0.127 

Real Server 2: eth0  RIP 192.168.0.13   桥接

              lo:0  VIP 192.168.0.127

Client:192.168.0.1   物理机

Real Server 1

[root@station39 ~]# vim /etc/sysctl.conf

net.ipv4.conf.lo.arp_ignore = 1

net.ipv4.conf.all.arp_ignore = 1

net.ipv4.conf.lo.arp_announce = 2

net.ipv4.conf.all.arp_announce = 2

[root@station39 ~]# sysctl -p

[root@station39 ~]# ifconfig eth0 192.168.0.12/24

[root@station39 ~]# ifconfig lo:0 192.168.0.127 broadcast 192.168.0.127 netmask  255.255.255.255

[root@station39 ~]# route add -host 192.168.0.127 dev lo:0

Real Server 2

[root@station26 ~]# vim /etc/sysctl.conf

net.ipv4.conf.lo.arp_ignore = 1

net.ipv4.conf.all.arp_ignore = 1

net.ipv4.conf.lo.arp_announce = 2

net.ipv4.conf.all.arp_announce = 2

[root@station26 ~]# sysctl -p

[root@station26 ~]# ifconfig eth0 192.168.0.13/24

[root@station26 ~]# ifconfig lo:0 192.168.0.127 broadcast 192.168.0.127 netmask  255.255.255.255

[root@station26 ~]# route add -host 192.168.0.127 dev lo:0

Director

[root@server27 ~]# ifconfig eth0 192.168.0.10/24

[root@server27 ~]# ifconfig eth0:0 192.168.0.127 broadcast 192.168.0.127 netmask 255.255.255.255

[root@server27 ~]# route add -host 192.168.0.127 dev eth0:0

[root@server27 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward

[root@server27 ~]# ipvsadm -C

[root@server27 ~]# ipvsadm -A -t 192.168.0.127:80 -s wlc

[root@server27 ~]# ipvsadm -a -t 192.168.0.127:80 -r 192.168.0.12 -g -w 5

[root@server27 ~]# ipvsadm -a -t 192.168.0.127:80 -r 192.168.0.13 -g -w 8

[root@server27 ~]# 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.0.127:80 wlc

  -> 192.168.0.13:80              Route   8      0          18       

  -> 192.168.0.12:80              Route   5      0          11

PS:如果要保持访问的页面一致,我们可以另外准备一台服务器专门用来存放网页文件,然后通过NFS共享的方式挂载到Real Server的网页目录下,就可以实现真正的负载均衡了。

实现持久连接:

[root@server27 ~]# ipvsadm -E -t 192.168.0.127:80 -s wlc -p 3600

[root@server27 ~]# 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.0.127:80 wlc persistent 3600

  -> 192.168.0.13:80              Route   8      0          62       

  -> 192.168.0.12:80              Route   5      0          0

此时,你会发现无论访问页面怎么刷新都不会再改变,这就是LVS持久性。

LVS  Persistence 持久性

尽管我们选择了LVS的分发方法,但是大多时候我们要保证返回给客户端的所有响应请求必须来自于同一台Real Server,这里我们就要用到LVS Persistence(持久性)。

当使用SSL会话的时候,我们常常期望只交换一次密钥就可以建立永久连接,因此,LVS持久性在SSL会话中经常被用到。

当使用LVS持久性的时候,Director在内部使用一个连接根据记录称之为“持久连接模板”来确保所有来自同一个客户端的请求被分发到同一台Real Server上。

LVS 持久性类型:PCC  PPC  PNMP  混合类型。

Persistent client connections (PCC), cause all services a client is accessing to persist. (Also called zero port connections.)

来自同一客户端所有服务的请求都被重定向到同一台Real Server上,以IP地址为准。

PCC是一个虚拟服务没有端口号(或者端口号为0),以"-p" 来标识服务。

缺陷:定向所有服务,期望访问不同的Real Server无法实现。

假设一个用户在访问购物网站时同时使用HTTP(80)和HTTPS(443)两种协议,就需要这样定义:

ipvsadm -A  -t  192.168.0.220:0 -s rr -p

ipvsadm -a  -t  192.168.0.220.3:0 -r 192.168.10.11 -m

ipvsadm -a  -t  192.168.0.220:0 -r 192.168.10.11 -m

Persistent port connections (PPC), which cause a single service to persist.

来自同一服务的请求都被重定向到同一台Real Server上,以端口号为准。

例如:client---->LVS(80,22)------>RS1   client----->LVS(23)----->RS2

缺陷:期望访问不同的端口到同一台RS上,无法实现。

Persistent Netfilter Marked Packet persistence, which causes packets that have been marked with the iptables utility to persist.

根据iptables 的规则,将对于某类服务/几个不同端口的访问定义为一类。

先对某一特定类型的数据包打上标记,然后再将基于某一类标记的服务送到后台的Real Server上去,后台的Real Server 并不识别这些标记。

PS:在LVS-NAT的环境下做这个实验,由于前边的DR模型使用了网卡别名,所以并不适合这个实验。

[root@server27 ~]# iptables -t mangle -A PREROUTING -i eth0 -d 192.168.0.127 -p tcp --dport 80 -j MARK --set-mark 2

[root@server27 ~]#  ipvsadm -A -f 2 -s wlc -p 3600

[root@server27 ~]# ipvsadm -a -f 2 -r 192.168.10.2 -m -w 2

[root@server27 ~]# ipvsadm -a -f 2 -r 192.168.10.3 -m -w 5

集群之LVS(负载均衡)详解

将持久和防火墙标记结合起来就能够实现端口姻亲功能,只要是来自某一客户端的对某一特定服务(需要不同的端口)的访问都定义到同一台Real Server上去。

假设这样一种场景:一个用户在访问购物网站时同时使用HTTP(80)和HTTPS(443)两种协议,我们需要将其定义到同一台Real Server上,而其他的服务不受限制,我们可以这样做:

实验基于LVS-NAT的环境。

先做一个自签名的证书

Real Server 1:

[root@station39 ~]# cd /etc/pki/tls/certs/

[root@station39 ~]# cd /etc/pki/tls/certs/

[root@station39 certs]# make httpd.pem

集群之LVS(负载均衡)详解

[root@station39 certs]# mv httpd.pem /etc/httpd/

[root@station39 httpd]# yum install mod_ssl -y

[root@station39 httpd]# cd conf.d/

[root@station39 conf.d]# vim ssl.conf

SSLCertificateFile /etc/httpd/httpd.pem   //** line 112

SSLCertificateKeyFile /etc/httpd/httpd.pem   //** line 119

重启httpd 服务。

[root@station39 ~]# vim /etc/hosts

192.168.10.2    web1.a.com              web1

Real Server 2 :

[root@station26 ~]# yum install mod_ssl -y

[root@station26 certs]# cd /etc/httpd

[root@station26 httpd]# make -C /etc/pki/tls/certs httpd.pem

集群之LVS(负载均衡)详解

[root@station26 httpd]# mv /etc/pki/tls/certs/httpd.pem ./

[root@station26 httpd]# cd conf.d/

[root@station26 conf.d]# vim ssl.conf

SSLCertificateFile /etc/httpd/httpd.pem   //** line 112

SSLCertificateKeyFile /etc/httpd/httpd.pem   //** line 119

重启httpd 服务。

[root@station26 ~]# vim /etc/hosts

192.168.10.3    web2.a.com              web2

Director:

[root@server27 ~]# iptables -t mangle -A PREROUTING -i eth0 -d 192.168.0.127 -p tcp --dport 80 -j MARK --set-mark 5

[root@server27 ~]# iptables -t mangle -A PREROUTING -i eth0 -d 192.168.0.127 -p tcp --dport 443 -j MARK --set-mark 5

[root@server27 ~]# ipvsadm -A -f 5 -s wlc -p

[root@server27 ~]# ipvsadm -a -f 5 -r 192.168.10.2 -m -w 2

[root@server27 ~]# ipvsadm -a -f 5 -r 192.168.10.3 -m -w 5

集群之LVS(负载均衡)详解

OK,修改windows客户端的C:\WINDOWS\system32\drivers\etc\hosts 文件,添加两条名称解析记录:

192.168.0.127 web1.a.com

192.168.0.127 web2.a.com

此时物理机访问192.168.0.127无论是http还是https 服务都会被定义到同一台Real Server上去。

集群之LVS(负载均衡)详解

这里我们是为了演示实验的效果,使用的不同的证书,不同的页面。真实的生产环境中要求这些必须是一致的。

FTP connections (FTP connections require careful handling due to the complex nature of FTP connections).

PS:指定一个范围,将范围内的端口打上标记。然后使VSFTPD在被动模式下不再使用随机端口,而是使用范围内的随机端口,从而实现FTP的负载均衡。

1 Limiting the port range for passive connections, you must also configure the VSFTP server to use a matching port range:

vim  /etc/vsftpd.conf:

pasv_min_port=10000

pasv_max_port=20000

2 You must also control the address that the server displays to the client for passive FTP connections. In a NAT routed LVS system, add the following line to /etc/vsftpd.conf to override the real server IP address to the VIP, which is what the client sees upon connection. For example:

pasv_address=n.n.n.n

3 iptables定义端口姻亲:

iptables -t mangle -A PREROUTING -p tcp -d n.n.n.n/32 --dport 21 -j MARK --set-mark 21

iptables -t mangle -A PREROUTING -p tcp -d n.n.n.n/32 --dport 10000:20000 -j MARK --set-mark 21

Expired persistence, which is used internally by the Director to expire connection tracking entries when the persistent connection template expires.