一、关于

LVS 是一种预装在 Linux 系统中,基于四层、具有强大性能的反向代理服务器。ipvsadm 是 LVS 的命令行管理工具。

Keepalived 是一个基于 VRRP 协议来实现的服务高可用方案,可以利用其来避免 IP 单点故障,一般与其它负载均衡技术(如 LVS 、HAProxy 、Nginx)一起工作来达到集群的高可用。Keepalived 是 LVS 的扩展项目, 因此它们之间具备良好的兼容性,可直接通过 Keepalived 的配置文件来配置 LVS。

涉及到的一些术语:

  • LB (Load Balancer 负载均衡)
  • HA (High Available 高可用)
  • Failover (失败切换)
  • Cluster (集群)
  • LVS (Linux Virtual Server Linux 虚拟服务器)
  • DS (Director Server),指的是前端负载均衡器节点
  • RS (Real Server),后端真实的工作服务器
  • VIP (Virtual IP),虚拟的 IP 地址,向外部直接面向用户请求,作为用户请求的目标的 IP 地址
  • DIP (Director IP),主要用于和内部主机通讯的 IP 地址
  • RIP (Real Server IP),后端服务器的 IP 地址
  • CIP (Client IP),访问客户端的 IP 地址

二、 负载均衡类型

主要有三种模型:NAT、TUN 、DR

2.1 LVS/NAT

客户端发送的请求到达Director后,Director根据负载均衡算法改写目标地址为后端某个RIP(web服务器池中主机之一)并转发给该后端主机,就像NAT(网络地址转换)一样

当后端主机处理完请求后,后端主机将响应数据交给Director,并由director改写源地址为VIP后传输给客户端。大多数商品化的IP负载均衡硬件都是使用此方法,如Cisco的LocalDirector、F5的Big/IP。

这种模式下:

RIP和DIP一般处于同一私有网段中。但并非必须,只要它们能通信即可。
各RealServer的网关指向DIP,这样能保证将响应数据交给Director。
VS/NAT模式的最大缺点是Director负责所有进出数据:不仅处理客户端发起的请求,还负责将响应传输给客户端。而响应数据一般比请求数据大得多,调度器Director容易出现瓶颈。(也就是像7层负载的处理方式一样,但却没有7层负载那么”多功能”)
这种模式配置起来最简单。

2.2 LVS/TUN

采用NAT技术时,由于请求和响应报文都必须经过调度器地址重写,当客户请求越来越多时,调度器的处理能力将成为瓶颈。

为了解决这个问题,调度器把请求报文通过IP隧道转发至真实服务器,而真实服务器将响应直接返回给客户,所以调度器只处理请求报文。由于一般网络服务响应报文比请求报文大许多,采用VS/TUN技术后,调度器得到极大的解放,集群系统的最大吞吐量可以提高10倍。

VS/TUN模式的工作原理:

(1)IP隧道技术又称为IP封装技术,它可以将带有源和目标IP地址的数据报文使用新的源和目标IP进行第二次封装,这样这个报文就可以发送到一个指定的目标主机上;
(2)VS/TUN模式下,调度器和后端服务器组之间使用IP隧道技术。当客户端发送的请求(CIP–>VIP)被director接收后,director修改该报文,加上IP隧道两端的IP地址作为新的源和目标地址,并将请求转发给后端被选中的一个目标;
(3)当后端服务器接收到报文后,首先解封报文得到原有的CIP–>VIP,该后端服务器发现自身的tun接口上配置了VIP,因此接受该数据包。
(4)当请求处理完成后,结果将不会重新交给director,而是直接返回给客户端。此时响应数据包的源IP为VIP,目标IP为CIP。

采用VS/TUN模式时的基本属性和要求:

RealServer的RIP和director的DIP不用处于同一物理网络中,且RIP必须可以和公网通信。也就是说集群节点可以跨互联网实现。
realserver的tun接口上需要配置VIP地址,以便接收director转发过来的数据包,以及作为响应报文的源IP。
director转发给realserver时需要借助隧道,隧道外层的IP头部的源IP是DIP,目标IP是RIP (DIP——>RIP)
而realsever响应给客户端的IP头部是根据隧道内层的IP头分析得到的,源IP是VIP,目标IP是CIP(VIP——>CIP)。这样客户端就无法区分这个VIP到底是director的还是RS组中的。
director只处理入站请求,响应请求由realserver自己完成。

2.3 LVS/DR

VS/TUN模式下,调度器对数据包的处理是使用IP隧道技术进行二次封装。VS/DR模式和VS/TUN模式很类似,只不过调度器对数据包的处理是改写数据帧的目标MAC地址,通过链路层来负载均衡。

VS/DR通过改写请求报文的目标MAC地址,将请求发送到真实服务器,而真实服务器将响应直接返回给客户。同VS/TUN技术一样,VS/DR技术可极大地提高集群系统的伸缩性。这种方法没有IP隧道的开销,对集群中的真实服务器也没有必须支持IP隧道协议的要求,但是要求调度器与真实服务器都有一块网卡连在同一物理网段上,以便使用MAC地址通信转发数据包。

VS/DR模式的工作原理:

(1)客户端发送的请求被director接收后,director根据负载均衡算法,改写数据帧的目标MAC地址为后端某RS的MAC地址,并将该数据包转发给该RS(实际上是往整个局域网发送,但只有该MAC地址的RS才不会丢弃)。
(2)RS接收到数据包后,发现数据包的目标IP地址为VIP,而RS本身已经将VIP配置在了自身的某个接口上,因此RS会接收下这个数据包并进行处理。
(3)处理完毕后,RS直接将响应报文响应给客户端。此时数据包源IP为VIP,目标IP为CIP。

采用VS/DR模式时的基本属性和要求:

RealServer的RIP和director的DIP必须处于同一网段中,以便使用MAC地址进行通信。
realserver上必须配置VIP地址,以便接收director转发过来的数据包,以及作为响应报文的源IP。
realsever响应给客户端的数据包的源和目标IP为VIP–>CIP。
director只处理入站请求,响应请求由realserver完成(这一点类似VS/TUN)。

2.4 比较

在性能上,VS/DR和VS/TUN远高于VS/NAT,因为调度器只处于从客户到服务器的半连接中,按照半连接的TCP有限状态机进行状态迁移,极大程度上减轻了调度器的压力(真正建立TCP连接的是RS和Client)。VS/DR性能又稍高于VS/TUN,因为少了隧道的开销。

但是,VS/DR和VS/TUN的主要区别是VS/TUN可以跨网络实现后端服务器负载均衡(也可以局域网内),而VS/DR只能和director在局域网内进行负载均衡。

性能:VS/DR > VS/TUN > VS/NAT

https://blog.csdn.net/weixin_42221657/article/details/102468488

三、负载均衡算法

(1)轮询调度算法
轮询调度(Round Robin 简称’RR’)算法就是按依次循环的方式将请求调度到不同的服务器上
该算法最大的特点就是实现简单
轮询算法假设所有的服务器处理请求的能力都一样的,调度器会将所有的请求平均分配给每个真实服务器
俗话说:你一个,我一个(web1接收一个访问,web2接收一个访问,这样轮询)

(2)加权轮询调度算法
加权轮询(Weight Round Robin 简称’WRR’)算法主要是对轮询算法的一种优化与补充,LVS会考虑每台服务器的性能
并给每台服务器添加一个权值,如果服务器A的权值为1,服务器B的权值为2
则调度器调度到服务器B的请求会是服务器A的两倍,权值越高的服务器,处理的请求越多
俗话说:拿钱多的干的活就多(哪个服务器性能好哪个服务器就多接受客户的请求)

(3)最小连接调度算法
最小连接调度(Least Connections 简称’LC’)算法是把新的连接请求分配到当前连接数最小的服务器
最小连接调度是一种动态的调度算法,它通过服务器当前活跃的连接数来估计服务器的情况
调度器需要记录各个服务器已建立连接的数目,当一个请求被调度到某台服务器,其连接数加1;当连接中断或者超时,其连接数减1。
俗话说:谁比较闲就让谁干活
集群系统的真实服务器具有相近的系统性能,采用最小连接调度算法可以比较好地均衡负载

(4)加权最小连接调度算法
加权最少连接(Weight Least Connections 简称’WLC’)算法是最小连接调度的超集,各个服务器相应的权值表示其处理性能
服务器的缺省权值为1,系统管理员可以动态地设置服务器的权值
加权最小连接调度在调度新连接时尽可能使服务器的已建立连接数和其权值成比例
调度器可以自动问询真实服务器的负载情况,并动态地调整其权值
俗话说:根据实际情况给后端服务器分配任务

(5)基于局部的最少连接算法
基于局部的最少连接调度(Locality-Based Least Connections 简称’LBLC’)算法是针对请求报文的目标IP地址的负载均衡调度
目前主要用于Cache集群系统,因为在Cache集群客户请求报文的目标IP地址是变化的
这里假设任何后端服务器都可以处理任一请求,算法的设计目标是在服务器的负载基本平衡情况下
将相同目标IP地址的请求调度到同一台服务器,来提高各台服务器的访问局部性和Cache命中率,从而提升整个集群系统的处理能力
LBLC调度算法先根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若该服务器是可用的且没有超载,将请求发送到该服务器
若服务器不存在或该服务器超载且有服务器处于一半的工作负载,则使用’最少连接’的原则选出一个可用的服务器,将请求发送到服务器

(6)带复制的基于局部性的最少连接算法
带复制的基于局部性的最少连接(Locality-Based Least Connections with Replication 简称’LBLCR’)算法也是针对目标IP地址的负载均衡
目前主要用于Cache集群系统,它与LBLC算法不同之处是它要维护从一个目标IP地址到一组服务器的映射
而LBLC算法维护从一个目标IP地址到一台服务器的映射。按’最小连接’原则从该服务器组中选出一一台服务器
若服务器没有超载,将请求发送到该服务器;若服务器超载,则按’最小连接’原则从整个集群中选出一台服务器
将该服务器加入到这个服务器组中,将请求发送到该服务器
同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度

(7)目标地址散列调度算法
目标地址散列调度(Destination Hashing 简称’DH’)算法先根据请求的目标IP地址
作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若服务器是可用的且并未超载,将请求发送到该服务器,否则返回空

(8)源地址散列调度算法
源地址散列调度(Source Hashing 简称’SH’)算法先根据请求的源IP地址
作为散列键(Hash Key)从静态分配的散列表找出对应的服务器
若该服务器是可用的且并未超载,将请求发送到该服务器,否则返回空
它采用的散列函数与目标地址散列调度算法的相同,它的算法流程与目标地址散列调度算法的基本相似

(9)最短的期望的延迟算法
最短的期望的延迟调度(Shortest Expected Delay 简称’SED’)算法基于WLC算法
举个例子吧,ABC三台服务器的权重分别为1、2、3
那么如果使用WLC算法的话一个新请求进入时它可能会分给ABC中的任意一个,使用SED算法后会进行一个运算
A:(1+1)/1=2 B:(1+2)/2=3/2 C:(1+3)/3=4/3 就把请求交给得出运算结果最小的服务器

(10)最少队列调度
最少队列调度(Never Queue 简称’NQ’)算法,无需队列
如果有realserver的连接数等于0就直接分配过去,不需要在进行SED运算

三、搭建

1、环境准备

需要准备四台机器,我这里使用四台centos7虚拟机进行测试,如下:

DS1: 192.168.18.51
DS2: 192.168.18.52
RS1: 192.168.18.53
RS2: 192.168.18.54

同时192.168.18.50作为VIP对外提供服务

所有机器关闭防火墙

systemctl stop firewalld

所有机器关闭selinux,修改/etc/selinux/config文件

vi /etc/selinux/config

将SELINUX=enforcing改为SELINUX=disabled

2、配置DS1

2.1 安装keepalived以及ipvsadm

yum -y install keepalived ipvsadm

2.2 配置keepalived

编辑keepalived.conf文件

vi /etc/keepalived/keepalived.conf

DS1作为主节点MASTER,配置如下:

! Configuration File for keepalived
global_defs {
   router_id LVS_DEVEL
}

vrrp_instance VI_1 {
    state MASTER            # 两个 DS,一个为 MASTER 一个为 BACKUP
    interface ens33         # 当前 IP 对应的网络接口,通过 ifconfig 查询
    virtual_router_id 62    # 虚拟路由 ID(0-255),在一个 VRRP 实例中主备服务器 ID 必须一样
    priority 200            # 优先级值设定:MASTER 要比 BACKUP 的值大
    advert_int 1            # 通告时间间隔:单位秒,主备要一致
    authentication {        # 认证机制,主从节点保持一致即可
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.18.50       # VIP,可配置多个
    }
}

# LB 配置
virtual_server 192.168.18.50 80  {
    delay_loop 3                    # 设置健康状态检查时间
    lb_algo rr                      # 调度算法,这里用了 rr 轮询算法
    lb_kind DR                      # 这里测试用了 Direct Route 模式
    #nat_mask 255.255.255.0
    persistence_timeout 0           # 持久连接超时时间
    protocol TCP
    real_server 192.168.18.53 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 10   
        }
    }
    real_server 192.168.18.54 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 10
        }
    }
}

配置完成后重启keepalived

systemctl restart keepalived

2.3 确认配置

查看VIP是否配置成功

[root@localhost wlh]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:50:56:24:37:52 brd ff:ff:ff:ff:ff:ff
    inet 192.168.18.51/24 brd 192.168.18.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 192.168.18.50/32 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::7ed1:1303:1410:2d92/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

查看转发是否配置成功

[root@localhost ~]# ipvsadm -l
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  localhost.localdomain:http rr
  -> 192.168.18.53:http           Route   1      0          0
  -> 192.168.18.54:http           Route   1      0          0

2.4 开启数据包转发

echo "net.ipv4.ip_forward = 1">>/etc/sysctl.conf
sysctl –p

3、配置DS2

参照DS1配置步骤,其中keepalived.conf中state以及priority需要调整,如下:

! Configuration File for keepalived
global_defs {
   router_id LVS_DEVEL
}

vrrp_instance VI_1 {
    state BACKUP            # 两个 DS,一个为 MASTER 一个为 BACKUP
    interface ens33        # 当前 IP 对应的网络接口,通过 ifconfig 查询
    virtual_router_id 62    # 虚拟路由 ID(0-255),在一个 VRRP 实例中主备服务器 ID 必须一样
    priority 100            # 优先级值设定:MASTER 要比 BACKUP 的值大
    advert_int 1            # 通告时间间隔:单位秒,主备要一致
    authentication {        # 认证机制,主从节点保持一致即可
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.18.50       # VIP,可配置多个
    }
}

# LB 配置
virtual_server 192.168.18.50 80  {
    delay_loop 3                    # 设置健康状态检查时间
    lb_algo rr                      # 调度算法,这里用了 rr 轮询算法
    lb_kind DR                      # 这里测试用了 Direct Route 模式
    nat_mask 255.255.255.0
    persistence_timeout 0           # 持久连接超时时间
    protocol TCP
    real_server 192.168.18.53 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 10   
        }
    }
    real_server 192.168.18.54 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 10
        }
    }
}

4、配置RS1

4.1 安装nginx

# 添加源
rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
# 安装nginx
yum install -y nginx

4.2 配置nginx

编辑nginx.conf文件

vim /etc/nginx/conf.d/nginx.conf

配置一个静态页面服务器,同时方便测试效果设置keepalive_timeout为0,如下:

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  0;

    #gzip  on;

    server {
        listen       80;
        server_name  localhost;
        # access_log  /var/log/nginx/host.access.log  main;
        location / {
            add_header Cache-Control no-store;
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }
}

编辑页面

vim /usr/share/nginx/html/index.html

设置其内容,显示页面所在主机,方便测试

<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<h1>Welcome to RS1@192.168.18.53!</h1>
</body>
</html>

4.3 启动nginx

systemctl start nginx

4.4 验证nginx

浏览器访问http://192.168.18.53 ,页面输出Welcome to RS1@192.168.18.53!

4.5 配置arp抑制

4.5.1 安装net-tools

yum install -y net-tools

4.5.2 创建arp抑制脚本

创建一个脚本文件

vim /usr/local/test/rs_arp.sh

内容如下

#!/bin/bash
#description: Config realserver
VIP=192.168.18.50
/etc/rc.d/init.d/functions
case "$1" in
start)
       /sbin/ifconfig lo:0 $VIP netmask 255.255.255.255 broadcast $VIP
       /sbin/route add -host $VIP dev 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
       sysctl -p >/dev/null 2>&1
       echo "RealServer Start OK"
       ;;
stop)
       /sbin/ifconfig lo:0 down
       /sbin/route del $VIP >/dev/null 2>&1
       echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore
       echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce
       echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore
       echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce
       echo "RealServer Stoped"
       ;;
*)
       echo "Usage: $0 {start|stop}"
       exit 1
esac
exit 0

4.5.2 启动arp抑制

添加脚本执行权限

chmod +x /root/real_server.sh

启动

/usr/local/test/rs_arp.sh start

验证

[root@localhost arp]# ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.18.53  netmask 255.255.255.0  broadcast 192.168.18.255
        inet6 fe80::7ed1:1303:1410:2d92  prefixlen 64  scopeid 0x20<link>
        inet6 fe80::d9bf:14b0:82d2:8cea  prefixlen 64  scopeid 0x20<link>
        inet6 fe80::b63a:1dd1:875e:8f4e  prefixlen 64  scopeid 0x20<link>
        ether 00:50:56:2d:81:c5  txqueuelen 1000  (Ethernet)
        RX packets 447405  bytes 147467769 (140.6 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 162134  bytes 33892165 (32.3 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 118  bytes 10208 (9.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 118  bytes 10208 (9.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo:0: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 192.168.18.50  netmask 255.255.255.255
        loop  txqueuelen 1000  (Local Loopback)

5、配置DS2

参照DS1配置,nginx代理页面/usr/share/nginx/html/index.html改为:

<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<h1>Welcome to RS1@192.168.18.54!</h1>
</body>
</html>

6、测试

四台机器均正常启动配置情况下,确认是否可以通过VIP访问到应用,其负载均衡策略是否生效

关闭DS1机器,确认DS2是否绑定了VIP,是否可以通过VIP正常访问应用

重启DS1机器,VIP是否重新绑定到DS1上,是否可以通过VIP正常访问应用

关闭RS1机器,通过VIP访问应用,是否剔除RS1代理页面

重启RS1机器,通过VIP访问应用,是否可以重新加载出RS1代理页面

参考

http://www.chenyongning.com/centos7%e6%90%ad%e5%bb%balvskeepalive%e8%b4%9f%e8%bd%bd%e5%9d%87%e8%a1%a1%e9%9b%86%e7%be%a4/