1. 简介

1.1 LVS简介

      LVS(Linux Virtual Server),也就是Linux虚拟服务器, 是一个由章文嵩博士发起的自由软件项目。使用LVS技术要达到的目标是:通过LVS提供的负载均衡技术和Linux操作系统实现一个高性能、高可用的服务器群集,它具有良好可靠性、可扩展性和可操作性。从而以低廉的成本实现最优的服务性能。

      LVS主要用来做四层负载均衡。


1.2 Keepalived简介

      Keepalived是分布式部署系统解决系统高可用的软件,结合LVS(Linux Virtual Server)使用,其功能类似于heartbeat,解决单机宕机的问题。
      Keepalived是以VRRP协议为实现基础的,VRRP全称Virtual Router Redundancy Protocol,即虚拟路由冗余协议。通过VRRP协议结合LVS,对组群服务器监控情况,若master出现宕机情况,则将VIP漂移到backup机上。实现了分布式系统高可用。可以理解为:keepalived是LVS的管理软件,根据监控情况,将宕机服务器从ipvsadm移除掉。
      Keepalived的诞生最初是为LVS ipvs(director)提供高可用性的,后来发展一个多功能、通用的轻量级高可用组件,可以为ipvs、nginx、haproxy等诸多服务提供高可用功能,主要应用在负载均衡调度器上,同时也可以检查后端各realserver的健康状态。


1.3 Nginx简介

      Nginx(发音同engine x)是一个网页服务器,它能反向代理HTTP, HTTPS, SMTP, POP3, IMAP的协议链接,以及一个负载均衡器和一个HTTP缓存。

      Nginx主要用来做七层负载均衡。


1.4 负载均衡

      四层负载均衡工作在OSI模型的传输层,由于在传输层,只有TCP/UDP协议,这两种协议中除了包含源IP、目标IP以外,还包含源端口号及目的端口号。四层负载均衡服务器在接受到客户端请求后,以后通过修改数据包的地址信息(IP+端口号)将流量转发到应用服务器。

      七层负载均衡工作在OSI模型的应用层,应用层协议较多,常用http、radius、dns等。七层负载就可以基于这些协议来负载。这些应用层协议中会包含很多有意义的内容。比如同一个Web服务器的负载均衡,除了根据IP加端口进行负载外,还可根据七层的URL、浏览器类别、语言来决定是否要进行负载均衡。

      四层通过虚拟 IP + 端口接收请求,然后再分配到真实的服务器,七层通过虚拟的 URL 或主机名接收请求,然后再分配到真实的服务器。所谓的四到七层负载均衡,就是在对后台的服务器进行负载均衡时,依据四层的信息或七层的信息来决定怎么样转发流量。


1.5 LVS和Nginx区别

1.lvs工作在第4层,负载能力强,逻辑简单,能对几乎所有应用进行负载,包括web和数据库;nginx工作在第7层,适用场合远多于lvs,负载能力相对较差。
2.lvs对网络稳定性依赖比较大;Nginx对网络的依赖比较小,理论上只要Ping得通,网页访问正常就能连通。
3.Nginx可以通过服务器处理网页返回的状态码、超时等来检测服务器内部的故障,并会把返回错误的请求重新发送到另一个节点;目前LVS和LDirectd 也支持对服务器内部情况的监控,但不能重新发送请求。
4.Nginx安装和配置比较简单,测试起来比较方便,它基本能把错误用日志打印出来;LVS的配置、测试耗时较长。
5.每日PV1000万以下或并发请求1万以下都可以考虑用Nginx;构建大型网站或者提供重要服务且机器较多时,可多加考虑利用LVS。


2. 搭建过程及测试

2.1 架构图

 lvs-nginx.jpg


2.2 主机配置

主机名
ip
操作系统
软件
端口
lvs01
172.27.9.7
CentOS 7.3.1611lvs  keepalived
81
lvs02
172.27.9.8
CentOS 7.3.1611lvs keepalived
81
nginx01
172.27.9.91
CentOS 7.3.1611nginx
81
nginx02
172.27.9.92
CentOS 7.3.1611nginx
81


2.3 搭建准备

2.3.1 关闭防火墙

关闭4台服务器防火墙

[root@lvs01 ~]# firewall-cmd --state
running
[root@lvs01 ~]# systemctl stop firewalld.service
[root@lvs01 ~]# firewall-cmd --state
not running
[root@lvs01 ~]# systemctl disable firewalld.service


2.3.2 关闭防selinux

闭4台服务器selinux,修改/etc/selinux/config,将SELINUX由enforcing设置为disabled,重启服务器。

查看selinux状态:

[root@lvs01 ~]# sestatus -v
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   enforcing
Mode from config file:          enforcing
Policy MLS status:              enabled
Policy deny_unknown status:     allowed



更改selinux状态:

[root@lvs01 ~]# sed -i 's/^ *SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config


2.4 ipvs安装

LVS无需安装,安装的是管理工具,第一种叫ipvsadm,第二种叫keepalive。ipvsadm是通过命令行管理,而keepalive读取配置文件管理。

分别在lvs01和lvs02执行如下操作:

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

把ipvsadm模块加载进系统

[root@lvs01 ~]# ipvsadm
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
[root@lvs01 ~]# lsmod | grep ip_vs
ip_vs                 141092  0 
nf_conntrack          111302  1 ip_vs
libcrc32c              12644  2 xfs,ip_vs


2.5 keepalived安装

分别在lvs01和lvs02执行如下操作:

[root@lvs01 ~]# yum -y install keepalived

2.6 keepalived配置

lvs01配置如下:

[root@lvs01 ~]# more /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
   router_id lvs01          #router_id 机器标识,通常为hostname,但不一定非得是hostname。故障发生时,邮件通知会用到。
}
vrrp_instance VI_1 {            #vrrp实例定义部分
    state MASTER               #设置lvs的状态,MASTER和BACKUP两种,必须大写 
    interface ens33               #设置对外服务的接口
    virtual_router_id 100        #设置虚拟路由标示,这个标示是一个数字,同一个vrrp实例使用唯一标示 
    priority 100               #定义优先级,数字越大优先级越高,在一个vrrp——instance下,master的优先级必须大于backup
    advert_int 1              #设定master与backup负载均衡器之间同步检查的时间间隔,单位是秒
    authentication {           #设置验证类型和密码
        auth_type PASS         #主要有PASS和AH两种
        auth_pass 1111         #验证密码,同一个vrrp_instance下MASTER和BACKUP密码必须相同
    }
    virtual_ipaddress {         #设置虚拟ip地址,可以设置多个,每行一个
        172.27.9.100 
    }
}
virtual_server 172.27.9.100 81 {       #设置虚拟服务器,需要指定虚拟ip和服务端口
    delay_loop 6                 #健康检查时间间隔
    lb_algo wrr                  #负载均衡调度算法
    lb_kind DR                   #负载均衡转发规则
    persistence_timeout 50        #设置会话保持时间,对动态网页非常有用
    protocol TCP               #指定转发协议类型,有TCP和UDP两种
    real_server 172.27.9.91 81 {    #配置服务器节点1,需要指定real server的真实IP地址和端口
    weight 1               #设置权重,数字越大权重越高
    TCP_CHECK {              #realserver的状态监测设置部分单位秒
       connect_timeout 10       #连接超时为10秒
       retry 3             #重连次数
       delay_before_retry 3        #重试间隔
       connect_port 81         #连接端口为81,要和上面的保持一致
       }
    }
     real_server 172.27.9.92 81 {    #配置服务器节点1,需要指定real server的真实IP地址和端口
     weight 1                  #设置权重,数字越大权重越高
     TCP_CHECK {               #realserver的状态监测设置部分单位秒
       connect_timeout 10         #连接超时为10秒
       retry 3               #重连次数
       delay_before_retry 3        #重试间隔
       connect_port 81          #连接端口为81,要和上面的保持一致
       }
     }
}

lvs02配置如下:

[root@lvs02 ~]# more /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
   router_id lvs02          #router_id 机器标识,通常为hostname,但不一定非得是hostname。故障发生时,邮件通知会用到。
}
vrrp_instance VI_1 {            #vrrp实例定义部分
    state BACKUP              #设置lvs的状态,MASTER和BACKUP两种,必须大写 
    interface ens33           #设置对外服务的接口
    virtual_router_id 100         #设置虚拟路由标示,这个标示是一个数字,同一个vrrp实例使用唯一标示 
    priority 99             #定义优先级,数字越大优先级越高,在一个vrrp——instance下,master的优先级必须大于backup
    advert_int 1              #设定master与backup负载均衡器之间同步检查的时间间隔,单位是秒
    authentication {            #设置验证类型和密码
        auth_type PASS         #主要有PASS和AH两种
        auth_pass 1111         #验证密码,同一个vrrp_instance下MASTER和BACKUP密码必须相同
    }
    virtual_ipaddress {         #设置虚拟ip地址,可以设置多个,每行一个
        172.27.9.100 
    }
}
virtual_server 172.27.9.100 81 {      #设置虚拟服务器,需要指定虚拟ip和服务端口
    delay_loop 6             #健康检查时间间隔
    lb_algo wrr              #负载均衡调度算法
    lb_kind DR               #负载均衡转发规则
    persistence_timeout 50          #设置会话保持时间,对动态网页非常有用
    protocol TCP              #指定转发协议类型,有TCP和UDP两种
    real_server 172.27.9.91 81 {       #配置服务器节点1,需要指定real server的真实IP地址和端口
    weight 1                #设置权重,数字越大权重越高
    TCP_CHECK {              #realserver的状态监测设置部分单位秒
       connect_timeout 10         #连接超时为10秒
       retry 3                #重连次数
       delay_before_retry 3       #重试间隔
       connect_port 81           #连接端口为81,要和上面的保持一致
       }
    }
     real_server 172.27.9.92 81 {   #配置服务器节点1,需要指定real server的真实IP地址和端口
     weight 1                #设置权重,数字越大权重越高
     TCP_CHECK {              #realserver的状态监测设置部分单位秒
       connect_timeout 10          #连接超时为10秒
       retry 3             #重连次数
       delay_before_retry 3        #重试间隔
       connect_port 81         #连接端口为81,要和上面的保持一致
       }
     }
}


2.7 参数说明

IPVS三种IP负载均衡技术:

VS/NAT 即(Virtual Server via Network Address Translation)
也就是网络地址翻译技术实现虚拟服务器,当用户请求到达调度器时,调度器将请求报文的目标地址(即虚拟IP地址)改写成选定的Real Server地址,同时报文的目标端口也改成选定的Real Server的相应端口,最后将报文请求发送到选定的Real Server。在服务器端得到数据后,Real Server返回数据给用户时,需要再次经过负载调度器将报文的源地址和源端口改成虚拟IP地址和相应端口,然后把数据发送给用户,完成整个负载调度过程。
可以看出,在NAT方式下,用户请求和响应报文都必须经过Director Server地址重写,当用户请求越来越多时,调度器的处理能力将称为瓶颈。

VS/TUN即(Virtual Server via IP Tunneling)
也就是IP隧道技术实现虚拟服务器。它的连接调度和管理与VS/NAT方式一样,只是它的报文转发方法不同,VS/TUN方式中,调度器采用IP隧道技术将用户请求转发到某个Real Server,而这个Real Server将直接响应用户的请求,不再经过前端调度器,此外,对Real Server的地域位置没有要求,可以和Director Server位于同一个网段,也可以是独立的一个网络。因此,在TUN方式中,调度器将只处理用户的报文请求,集群系统的吞吐量大大提高。

VS/DR: 即(Virtual Server via Direct Routing)
也就是用直接路由技术实现虚拟服务器。它的连接调度和管理与VS/NAT和VS/TUN中的一样,但它的报文转发方法又有不同,VS/DR通过改写请求报文的MAC地址,将请求发送到Real Server,而Real Server将响应直接返回给客户,免去了VS/TUN中的IP隧道开销。这种方式是三种负载调度机制中性能最高最好的,但是必须要求Director Server与Real Server都有一块网卡连在同一物理网段上,且真实服务器网络设备或设备别名不作 ARP 响应


IPVS调度器实现了如下八种负载调度算法:

轮叫(Round Robin)
调度器通过"轮叫"调度算法将外部请求按顺序轮流分配到集群中的真实服务器上,它均等地对待每一台服务器,而不管服务器上实际的连接数和系统负载。

加权轮叫(Weighted Round Robin)
调度器通过"加权轮叫"调度算法根据真实服务器的不同处理能力来调度访问请求。这样可以保证处理能力强的服务器处理更多的访问流量。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。

最少链接(Least Connections)
调度器通过"最少连接"调度算法动态地将网络请求调度到已建立的链接数最少的服务器上。如果集群系统的真实服务器具有相近的系统性能,采用"最小连接"调度算法可以较好地均衡负载。

加权最少链接(Weighted Least Connections)
在集群系统中的服务器性能差异较大的情况下,调度器采用"加权最少链接"调度算法优化负载均衡性能,具有较高权值的服务器将承受较大比例的活动连接负载。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。

基于局部性的最少链接(Locality-Based Least Connections)
"基于局部性的最少链接" 调度算法是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。该算法根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若该服务器 是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则用"最少链接"的原则选出一个可用的服务 器,将请求发送到该服务器。

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

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

源地址散列(Source Hashing)
"源地址散列"调度算法根据请求的源IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。


本例中采用DR负载均衡和wrr负载调度算法


2.8 nginx搭建

nginx搭建详见Centos7安装nginx。nginx默认端口已修改为81。


2.9 realserver.sh配置

打开Nginx所在服务器的“路由”功能、关闭“ARP查询”功能并设置回环ip,nginx01和nginx02配置如下:

[root@nginx01 init.d]# more /etc/rc.d/init.d/realserver.sh 
#!/bin/bash
    SNS_VIP=172.27.9.100
    /etc/rc.d/init.d/functions
    case "$1" in
    start)
        ifconfig lo:0 $SNS_VIP netmask 255.255.255.255 broadcast $SNS_VIP
        /sbin/route add -host $SNS_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)
        ifconfig lo:0 down
        route del $SNS_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

此脚本用于节点服务器绑定 VIP ,并抑制响应 VIP 的 ARP 请求。这样做的目的是为了不让关于 VIP 的 ARP 广播时,节点服务器应答( 因为节点服务器都绑定了 VIP ,如果不做设置它们会应答,就会乱套 )。


给realserver.sh脚本授予执行权限:

[root@nginx01 init.d]# chmod u+x realserver.sh


3. 负载均衡及高可用测试

3.1 启动Keepalived

lvs01和lvs02分别执行:


[root@lvs01 ~]# service keepalived start

查看ip,lvs01上有vip172.27.9.100,lvs02没有:

图片.png

图片.png



3.2 启动nginx

如果nginx未运行则在nginx01和nginx02执行:

[root@nginx01 ~]# nginx


3.3 运行realserver.sh脚本

在nginx01和nginx02执行realserver.sh脚本:

[root@nginx01 ~]# /etc/rc.d/init.d/realserver.sh start


3.4 修改nginx默认首页

nginx01和nginx02上分别修改index.html:

[root@nginx01 html]# view /usr/local/nginx/html/index.html

新增内容如图:

图片.png图片.png


3.5 页面访问

3.5.1 访问vip

通过不同浏览器访问http://172.27.9.100:81

图片.png




3.5.2 Master上检查连接情况

lvs01上执行ipvsadm -ln:

图片.png


3.5.3 ipvsadm参数说明

ipvsadm:

-L|-l(–list):显示内核虚拟服务器表

-n–numeric):输出IP 地址和端口的数字形式

输出参数说明:

Forward 转发方式,当前是路由转发
Weight 权重
ActiveConn 当前活跃的连接数
InActConn 当前不活跃的连接数

3.5.4 修改keepalived参数

通过ipvsadm命令发现访问请求都被分配到92(nginx02)这台服务器,没有实现负载均衡。这个和keepalived参数配置persistence_timeout有关,这个参数的意义是保持客户端的请求在这个时间段内全部发到同一个真实服务器。

分别注释lvs01和lvs02的persistence_timeout:

[root@lvs01 keepalived]# cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak
[root@lvs01 keepalived]# view /etc/keepalived/keepalived.conf
#persistence_timeout 50

重启两台lvs服务器keepalived服务:

[root@lvs01 keepalived]# service keepalived restart

再次测试:

图片.png

发现连接均匀的分配到后台两台nginx服务器。


3.5.5 lvs高可用测试

恢复keepalived配置并重启服务。

lvs01宕机前访问页面:

图片.png

停止lvs01的keepalived服务,模拟lvs01宕机:

[root@lvs01 keepalived]# service keepalived stop
Redirecting to /bin/systemctl stop  keepalived.service
[root@lvs01 keepalived]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:ef:97:ad brd ff:ff:ff:ff:ff:ff
    inet 172.27.9.7/24 brd 172.27.9.255 scope global ens33
       valid_lft forever preferred_lft forever
[root@lvs01 keepalived]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

查看lvs01的keepalived日志和状态:

图片.png

查看lvs02情况:

[root@lvs02 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:e3:ea:c1 brd ff:ff:ff:ff:ff:ff
    inet 172.27.9.8/24 brd 172.27.9.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet 172.27.9.100/32 scope global ens33
       valid_lft forever preferred_lft forever

发现vip已飘至lvs02。

http://172.27.9.100:81/,访问正常:

图片.png

恢复lvs01的keepalived服务:

[root@lvs01 keepalived]# service keepalived start
Redirecting to /bin/systemctl start  keepalived.service
[root@lvs01 keepalived]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:ef:97:ad brd ff:ff:ff:ff:ff:ff
    inet 172.27.9.7/24 brd 172.27.9.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet 172.27.9.100/32 scope global ens33
       valid_lft forever preferred_lft forever

发现vip飘回至lvs01,vip页面访问正常


3.5.6 nginx高可用测试

目前通过vip访问的后端nginx服务器为92即nginx02,现在停止92上的nginx服务,模拟nginx02宕机,查看vip页面访问情况:

[root@nginx02 init.d]# ps -ef|grep nginx
root       2216      1  0 4月04 ?       00:00:00 nginx: master process nginx
nobody     2217   2216  0 4月04 ?       00:00:00 nginx: worker process
root       2390   2196  0 00:06 pts/0    00:00:00 grep --color=auto nginx
[root@nginx02 init.d]# kill -9 2216 2217

查看页面访问:

图片.png

发现后端nginx连接转至91即nginx01,在lvs01上查看连接情况:

图片.png



总结:

当 MASTER 服务器无法提供服务时,VIP 会在 MASTER 上自动移除,BACKUP 服务器会提升为 MASTER 状态,绑定 VIP 、接管服务。
当 MASTER 修复加入网络后,会自动抢回 VIP ,成为 MASTER 身份。
当后端提供服务nginx服务挂起时,会自动切换至其它nginx服务器。


本文所有脚本和配置文件已上传,下载地址:https://github.com/loong576/lvs-nginx-keepalived/archive/master.zip