lvs+keepalived实现web集群高可用性


负载均衡集群的概念

负载均衡是设计分布式系统架构必须要考虑的因素之一,它指的是通过调度分发的方式尽可能将“请求”、“访问”的压力负载平均分摊到集群中的各个节点,避免有些节点负载太高导致访问延迟,而有些节点负载很小导致资源浪费。这样,每个节点都可以承担一定的访问请求负载压力,并且可以实现访问请求在各节点之间的动态分配,以实现负载均衡,从而为企业提供更高性能,更加稳定的系统架构解决方案。


高可用集群的概念

高可用是指以减少服务中断时间或者避免服务中断为目标的技术,它也是分布式系统架构中必须要考虑的因素之一。集群中节点之间进行心跳检查,可以实现对整个集群中的节点健康状态的检测,如果某个节点失效,它的备节点将在几秒钟的时间内接管它的工作。因此对于用户而言,服务总是可以访问的。


一点点概念

1,directory server    负载均衡器(DR)

2,real server    提供服务的真实服务器

3,VIP   虚拟IP

4,CIP   客户端的IP

5,DIP   directory server的IP

6,RIP    real server的IP


什么是lvs?

lvs全称是linux virtual server,基于IP负载均衡技术和基于内容请求分发技术。它通过一个资源调度器将请求均衡地分发到不同的服务器上,从而将一组服务器构成一个高性能的、高可用的虚拟服务器。


lvs有三种类型:


      ①lvs-nat模型:请求报文到达调度器(DR)的时候,DR将目的IP(VIP)转换成真正的服务器地址再根据调度算法,将请求转发给后端真实的服务器;真实服务器的响应报文通过调度器时,报文的源地址被转换成(RIP),再返回给客户端,完成整个负载调度过程。由于请求报文和回应报文都必须经过DR,所以DR会成为性能的瓶颈。这种模型的VIP和RIP可以在不同的网段,值得注意的是:真实服务器的网关必须指向DR。

      ②lvs-dr模型:DR模型是通过把请求报文的MAC地址改写成真实服务器的MAC地址直接把请求发送给真实服务器,而真实服务器将响应直接返回给客户端。对于DR模型,由于请求报文是通过广播的方式在LAN传输,所以VIP和RIP必须在同一个网段,否则广播后所有的请求报文都会丢失。

      ③lvs-tun模型:调度器会把请求报文通过IP隧道转发到真实服务器,而真实服务器将响应直接返回给客户端,所以调度器只处理请求报文,不处理响应报文。这种模型的lvs需要在所有的真实服务器上绑定VIP,VIP和RIP可以不在同一个网段。


keepalived又是什么?

keepalived是一款轻量级的高可用软件,它只能实现对IP资源的高可用。主要通过虚拟路由冗余协议(VRRP)实现高可用的功能。在非双主keepalived集群中,会依靠优先级选举出一个主节点,IP资源会优先绑定到主节点,其他节点成为备节点,主节点与备节点之间会通过检查心跳线来检测对方的存活,一旦主节点宕机,备用节点就抢占IP资源,当主节点恢复正常,备节点又会释放IP资源给主节点。



实验:lvs+keepalived

主机名 角色 IP

lvs-master 主调度器 172.16.1.136/24

lvs-backup 备调度器 172.16.1.133/24

web1 真实服务器 172.16.1.140/24

web2 真实服务器 172.16.1.137/24


client
客户端



vip 172.16.1.111/24


//所有的服务器都要同步时间

ntpdate time.nist.gov

crontab -l

*/10 * * * * ntpdate time.nist.gov



real server的配置

 

关闭防火墙和selinux

[root@web1 ~]#systemctl stop firewalld

[root@web1 ~]#systemctl disable firewalld

[root@web1 ~]#vim /etc/selinux/config

SELINUX=disabled


配置web服务

[root@web1 ~]#yum -y install httpd

[root@web1 ~]#echo web1 > /var/www/html/index.html

[root@web1 ~]#systemctl start  httpd


----------------------web2同web1,略



lvs-master的配置

 

关闭防火墙还有selinux

[root@lvs-master~]# systemctl stop firewalld

[root@lvs-master~]# systemctl disable firewalld

[root@lvs-master~]# vim /etc/selinux/config

SELINUX=disabled

 

配置lvs

[root@lvs-master~]# yum -y install ipvsadm    #下载工具

[root@lvs-master~]# vim lvs.sh      #通过脚本配置lvs

#!/bin/bash

VIP=172.16.1.111

RIP1=172.16.1.140

RIP2=172.16.1.137

PORT=80


start() {

     echo 1 > /proc/sys/net/ipv4/ip_forward

     ipvsadm -A -t $VIP:$PORT -s rr

     ipvsadm -a -t $VIP:$PORT -r $RIP1:$PORT -g

     ipvsadm -a -t $VIP:$PORT -r $RIP2:$PORT -g

        }

stop()  {

     ipvsadm -D -t $VIP:$PORT

     echo 0 > /proc/sys/net/ipv4/ip_forward

        }

case $1 in

     start)

       start;;

      stop)

       stop;;

         *)

      echo "/root/lvs.sh start|stop";;

esac


由于lvs不能对后端服务器进行健康检测,所以需要写一个检查后端服务健康状态的脚本

[root@lvs-master~]# vim lvs_healcheck.sh

#!/bin/bash

VIP=172.16.1.111

RIP1=172.16.1.140

RIP2=172.16.1.137

PORT=80

for i in $RIP1$RIP2

do

   /usr/sbin/ipvsadm -a -t $VIP:$PORT  -r $i:$PORT -g &> /dev/null

if ["$?" -ne "0" ];then

   curl http://$i &> /dev/null

   if [ "$?" == "0" ];then

      echo "real server in `date +%F-%T`is ok" >> /tmp/healcheresult

   else

    /usr/sbin/ipvsadm -d -t $VIP:$PORT -r $i:$PORT

   fi

else

   curl http://$i &> /dev/null

   if [ "$?" == "0" ];then

    echo "real server in `date +%F-%T` comme on" >> /tmp/nok

   else

    /usr/sbin/ipvsadm -d -t $VIP:$PORT -r $i:$PORT

   fi

fi

done

 

编写计划任务,每时每刻执行健康检查脚本

[root@lvs-master~]# crontab -l

* * * * */usr/bin/sh  /root/lvs_healcheck.sh


配置keepalived

[root@lvs-master~]# yum -y install keepalived

[root@lvs-master~]# vim /etc/keepalived/keepalived.conf

! ConfigurationFile for keepalived

//全局配置

global_defs {

   notification_email {

     root@localhost    #报警邮件的地址

   }

   notification_email_from keepalived@localhost     #邮件的发送地址

 smtp_server 127.0.0.1       #smtp服务器的地址

   smtp_connect_timeout 30      #连接smtp服务器的超时时间

   router_id LVS_M          #keepalived服务器的一个标识

}

//实例配置

vrrp_instanceVI_1 {

    state MASTER           #指定keepalived的角色,MASTER|BACKUP

    interface eno16777736      #实例绑定的网卡,配置VIP必须在已有的网卡添加

    virtual_router_id 51       #相同的VRID为一组,决定多播的MAC地址

    priority 100        #优先级

    advert_int 3        #设定MASTER与BACKUP负载均衡器之间同步检查的时间间隔,单位是秒

    authentication {

        auth_type PASS        #认证类型 PASS|AH

                auth_pass redhat       #验证密码,在同一个实例,MASTER与BACKUP的密码必须保持一致才可以正常通信

    }

    virtual_ipaddress {

        172.16.1.111      #VIP

    }

}

virtual_server 172.16.1.111 80 {

    delay_loop 6     #运行情况检查时间,单位是秒

    lb_algo rr       #负载均衡算法,wlc为最小加权算法,rr为轮询

    lb_kind DR        #使用DR模式

    net_mask 255.255.255.0

   persistence_timeout 50

     protocol TCP        #使用TCP协议检查realserver状态,指定转发协议类型,有TCP和UDP两种

 

real_server172.16.1.140 80

    {

        weight 1         #节点权重值

        TCP_CHECK       #健康检查方式

        {

        connect_port 80        #连接端口

        connect_timeout 5       #连接超时

        nb_get_retry 3           #重试次数

        delay_before_retry 3       #重试间隔

         }

    }

real_server172.16.1.137 80

       {

        weight 1

        TCP_CHECK {

        connect_port 80

        connect_timeout 5

        nb_get_retry 3

        delay_before_retry 3

                  }

       }

}

 

重启服务,设置服务开机自动启动

[root@lvs-master~]# touch /etc/sysconfig/ipvsadm

[root@lvs-master~]# systemctl restart ipvsadm

[root@lvs-master~]# systemctl restart keepalived.service

[root@lvs-master~]# systemctl enable ipvsadm

[root@lvs-master~]# systemctl enable keepalived.service

 

验证是否有vip

[root@lvs-master~]# ip add show|grep 172.16.1.111

inet172.16.1.111/32 scope global eno16777736  




lvs-backup的配置

 

关闭防火墙和selinux

[root@lvs-backup~]# systemctl stop firewalld

[root@lvs-backup~]# systemctl disable firewalld

[root@lvs-backup~]# vim /etc/selinux/config

SELINUX=disabled

 

配置lvs

[root@lvs-backup~]# yum -y install ipvsadm

[root@lvs-master~]# scp lvs.sh [email protected]:/root/

[root@lvs-master~]# scp lvs_healcheck.sh [email protected]:/root/

[root@lvs-backup~]# chmod +x lvs.sh

[root@lvs-backup~]# chmod +x lvs_healcheck.sh

[root@lvs-backup~]# crontab -l

* * * * */usr/bin/sh /root/lvs_healcheck.sh


配置keepalived

[root@lvs-backup~]# yum -y install keepalived

[root@lvs-master ~]# scp /etc/keepalived/[email protected]:/etc/keepalived/

[root@lvs-backup~]# vim /etc/keepalived/keepalived.conf

! ConfigurationFile for keepalived

 

global_defs {

   notification_email {

     root@localhost

   }

   notification_email_from keepalived@localhost

   smtp_server 127.0.0.1

   smtp_connect_timeout 30

   router_id LVS_S       #修改router_id

}

 

vrrp_instanceVI_1 {

    state BACKUP       #修改keepalived角色

    interface eno16777736

    virtual_router_id 51

    priority 99         #修改优先级

    advert_int 3

    authentication {

        auth_type PASS

        auth_pass redhat

    }

    virtual_ipaddress {

        172.16.1.111

    }

}

 

virtual_server172.16.1.111 80 {

    delay_loop 6

    lb_algo rr

    lb_kind DR

    nat_mask 255.255.255.0

    persistence_timeout 50

    protocol TCP

 

      real_server 172.16.1.140 80

       {

        weight 1

        TCP_CHECK {

        connect_port 80

        connect_timeout 5

       nb_get_retry 3 

        delay_before_retry 3

                  }

       real_server 172.16.1.137 80

       {

        weight 1

        TCP_CHECK {

        connect_port 80

        connect_timeout 5

        nb_get_retry 3

        delay_before_retry 3

                  }

       }

}

 

重启服务,设置服务开机自动启动

[root@lvs-backup~]# touch /etc/sysconfig/ipvsadm

[root@lvs-backup~]# systemctl restart ipvsadm

[root@lvs-backup~]# systemctl restart keepalived.service

[root@lvs-backup~]# systemctl enable ipvsadm

[root@lvs-backup~]# systemctl enable keepalived.service 


在lvs-master和lvs-backup上创建集群服务

[root@lvs-master~]# ./lvs.sh start

[root@lvs-master~]# ipvsadm -L -n

IP VirtualServer version 1.2.1 (size=4096)

ProtLocalAddress:Port Scheduler Flags

  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

TCP  172.16.1.111:80 rr

  -> 172.16.1.137:80              Route   1     0          0        

  -> 172.16.1.140:80              Route   1     0          0 

[root@lvs-backup~]# ./lvs.sh start

[root@lvs-backup~]# ipvsadm -L -n

IP VirtualServer version 1.2.1 (size=4096)

Prot LocalAddress:PortScheduler Flags

  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

TCP  172.16.1.111:80 rr

  -> 172.16.1.137:80              Route   1     0          0        

  -> 172.16.1.140:80              Route   1     0          0 

 

验证

[root@client~]#curl http://172.16.1.111

web1

[root@client~]#curl http://172.16.1.111

web2

 

[root@lvs-master~]# ipvsadm -L -n

IP VirtualServer version 1.2.1 (size=4096)

ProtLocalAddress:Port Scheduler Flags

  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

TCP  172.16.1.111:80 rr

  -> 172.16.1.137:80              Route   1     1         0        

  -> 172.16.1.140:80              Route   1     1         0

#lvs-master上ActiveConn会一直增加,因为所有访问vip的连接都会经过lvs-master进行调度,转发到后端real server 

[root@lvs-backup~]# ipvsadm -L -n

IP VirtualServer version 1.2.1 (size=4096)

ProtLocalAddress:Port Scheduler Flags

  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

TCP  172.16.1.111:80 rr

  -> 172.16.1.137:80              Route   1     0         0        

  -> 172.16.1.140:80              Route   1      0          0  

#除非lvs-master宕机,lvs-backup上ActiveConn会一直为0,因为没有请求转发到lvs-backup进行调度

 

关闭lvs-master模仿宕机

[root@lvs-backup~]# ip add show | grep 172.16.1.111

    inet 172.16.1.111/32 scope globaleno16777736

[root@client~]#curl http://172.16.1.111

web1

[root@client~]#curl http://172.16.1.111

web2

#由于此时lvs-backup仍然正常工作,所有访问vip的连接经过lvs-backup进行调度,转发到后端real server,所有还可以访问到后端的real server

 

再关闭lvs-backup模仿宕机

[root@client~]# curl http://172.16.1.111

curl: (7)Failed connect to 172.16.1.111:80; Connection timed out

#网络中没有可用的lvs负载均衡器,所有访问vip的连接无法被调度转发到real server

 

开启lvs-master模仿故障恢复

[root@client~]# curl http://172.16.1.111

web1

[root@client~]# curl http://172.16.1.111

web2

#lvs-master正常工作所有访问vip的连接都会经过lvs-master进行调度,转发到后端real server 



如有纰漏,欢迎指正。