LVS+keepalived高可用集群

一、LVS 负载均衡简介
       LVS是Linux VirtualServer的简写,意为Linux虚拟服务器,是虚拟的服务器集群系统,可在UNIX/LINUX平台下实现负载均衡集群功能。LVS 简单工作原理为用户请求LVSVIP,LVS根据转发方式和算法,将请求转发给后端服务器,后端服务器接收到请求,返回给用户,对于用户来说,看不到Web后端具体的应用。
      互联网主流可伸缩网络服务有很多结构,但是都有一个共同点,它们都需要一个前端的负载调度器(或者多个进行主从备份)。实现虚拟网络服务的主要技术指出IP负载均衡技术是在负载调度器的实现技术中效率最高的。
      已有的IP负载均衡技术中,主要有通过网络地址转换(NAT)将一组服务器构成一个高性能的、高可用的虚拟服务器,通常称之为VS/NAT技术。
      在分析VS/NAT的缺点和网络服务的非对称性的基础上,可以通过IP隧道实现虚拟服务器的方法VS/TUN和通过直接路由实现虚拟服务器的方法VS/DR,它们可以极大地提高系统的伸缩性。
      总体来说,IP负载均衡技术分为VS/NAT、VS/TUN和VS/DR技术,它们是LVS集群中实现的三种IP负载均衡技术。
 
二、LVS 负载均衡工作原理
      实现LVS负载均衡转发方式有三种,分别为NAT、DR、TUN模式,LVS均衡常见算法包括RR(round-robin)、LC(least_connection)、W(weight)RR、WLC模式等(RR为轮询模式,LC为最少连接模式)。
 • LVS NAT原理:
用户请求LVS到达director,director将请求的报文的目标IP地址改为后端的realserverIP地址,同时将报文的目标端口也改成后端选定的realserver相应的端口,最后将报文发送到realserver,realserver将数据返给director,director再把数据发送给用户。因为两次请求都经过director,所以访问量大的话,director会成为瓶颈。
 • LVS DR原理:
用户请求LVS到达director,director将请求的报文的目标MAC地址改成后端的realserverMAC地址,目标IP为VIP(不变),源IP为用户IP地址(不变),然后director将报文发送到realserver,realserver检测到目标为自已本地VIP,如果在同一个网段,然后将请求直接返给用户。如果用户跟realserver不在一个网络,则通过网关返回用户。
 • LVS TUN原理:
用户请求LVS到达director,director通过IP-TUN加密技术将请求的报文的目标MAC地址改成后端的realserverMAC地址,目标IP为VIP(不变),源IP为用户IP地址(不变),然后director将报文发送到realserver,realserver基于IP-TUN解密,然后检测到目标为自己本地VIP,如果在同一个网段,然后将请求直接返给用户,如果用户跟realserver不在一个网段,则通过网关返给用户。
 
三、LVS 负载均衡配置
      LVS负载均衡技术实现是基于Linux内核模块ipvs,与iptables一样是直接工作在内核中,互联网主流的Linux发行版默认都是已经集成了ipvs模块,只需安装管理工具ipvsadm,安装配置步骤如下:
1、YUM安装:
# yum install ipvsadm-y
2、源码包安装:
# wget http://www.linuxvirtualserver.org/software/kernel-2.6/ipvsadm-1.26.tar.gz
# tar xzvfipvsadm-1.26.tar.gz
# cd ipvsadm-1.26
# make
# make install
3、ipvsadm 配置:
软件安装后,需要进行配置,主要配置方法有三步:添加虚拟服务器IP、添加realserver后端服务及启动LVS服务器VIP地址。
# ipvsadm -A -t192.168.28.88:80 -s rr
# ipvsadm -a -t192.168.28.88:80 -r 192.168.28.134:80 -g -w 2
# ipvsadm -a -t192.168.28.88:80 -r 192.168.28.135:80 -g -w 2
4、可以使用shell脚本自动部署LVS相关软件及配置:
# vim/data/sh/auto_ipvsadm.sh
#!/bin/bash
SNS_VIP=$2
SNS_RIP1=$3
SNS_RIP2=$4
if [ "$1" =="stop" -a -z "$2" ];then
echo"------------------------------------------------------------"
echo-e "\033[32mPlease Enter $0 stop LVS_VIP\n\nEXample: $0 stop192.168.28.133\033[0m"
echo
exit
else
if [-z "$2" -a -z "$3" -a -z "$4" ];then
echo"----------------------------------------------------------"
echo-e "\033[32mPlease Enter Input $0 start VIP REALSERVER1REALSERVER2\n\nEXample: $0 start/stop 192.168.28.88 192.168.28.134192.168.28.135\033[0m"
echo
exit0
fi
fi
./ect/rc.d/init.d/functions
logger $0 called with$1
function IPVSADM(){
/usr/sbin/ipvsadm --set30 5 60
/usr/sbin/ifconfigeth0:0 $SNS_VIP broadcast $SNS_VIP netmask 255.255.255.255 broadcast $SNS_VIPup
/usr/sbin/route add-host $SNS_VIP dev eth0:0
/usr/sbin/ipvsadm -A -t$SNS_VIP:80 -s wlc -p 120
/usr/sbin/ipvsadm -a -t$SNS_VIP:80 -r $SNS_RIP1:80 -g -w 1
/usr/sbin/ipvsadm -a -t$SNS_VIP:80 -r $SNS_RIP2:80 -g -w 1
}
case "$1" in
start)
IPVSADM
echo"-----------------------------------------"
/usr/sbin/ipvsadm -Ln
touch/var/lock/subsys/ipvsadm>/dev/null 2>&1
;;
stop)
/usr/sbin/ipvsadm -C
/usr/sbin/ipvsadm -Z
ifconfig eth0:0 down>>/dev/null 2>&1
route del$SNS_VIP>>/dev/null 2>&1
rm -rf/var/lock/subsys/ipvsadm >/dev/null 2>&1
echo "ipvsadmstopped!"
;;
status)
if [ ! -e/var/lock/subsys/ipvsadm ]
then
echo "ipvsadmstopped!"
exit 1
else
echo "ipvsadmstarted!"
fi
;;
*)
echo "Usae: $0{start|stop|status}"
exit 1
;;
esac
exit 0
5、LVS服务器绑定VIP地址:
VIP=192.168.28.88
ifconfig eth0:0 $VIPnetmask 255.255.255.255 broadcast $SNS_VIP up
/usr/sbin/route add-host $VIP dev eth0:0
6、LVS ipvsadm 配置参数:
-A        增加一台虚拟服务器VIP地址
-t        虚拟服务器提供的是TCP服务
-s        使用的调度算法
-a        在虚拟服务器中增加一台后端真实服务器
-r        指定真实服务器地址
-w        后端真实服务器的权重
-m        设置当前转发方式为NAT模式
-g        模式为直接路由模式
-i        模式为隧道模式
7、查看LVS 转发列表命令为:
# ipvsadm -Ln:
IP Virtual Serverversion 1.2.1 (size=4096)
Prot LocalAddress:PortScheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.28.88:80 rr
  -> 192.168.28.134:80            Route   1     0          0        
  -> 192.168.28.135:80            Route   1     0          0
8、查看LVS连接后端转发信息条目:
# ipvsadm -lnc
IPVS connection entries
pro expire state       source             virtual            destination
TCP 01:43  FIN_WAIT   192.168.28.1:53984 192.168.28.88:80  192.168.28.134:80
TCP 00:37  SYN_RECV   192.168.28.1:53985 192.168.28.88:80  192.168.28.135:80
TCP 00:05  FIN_WAIT   192.168.28.1:53930 192.168.28.88:80  192.168.28.134:80
9、Nginx 客户端realserver 配置VIP脚本:
# vim/etc/init.d/lvsrs               #编辑一个lvsrs脚本,并放到/etc/init.d/下
#!/bin/bash 
#description : startrealserver
VIP=192.168.28.88
sh/etc/rc.d/init.d/functions
case "$1" in
start)
/usr/sbin/ifconfig lo:0$VIP broadcast $VIP netmask 255.255.255.255 up
/usr/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
echo " start LVSof REALServer"
exit 0
;;
stop)
/usr/sbin/ifconfig lo:0down
/usr/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 "close LVSDirectorserver"
exit 1
;;
*)
echo "Usage: $0{start|stop}"
exit 1
;;
esac
# chmod 755/etc/init.d/lvsrs      #给新增lvsrs脚本一个755权限
# service lvsrsstart             #启动lvsrs服务,我环境启动时出错,给一个functions 755权限,按各自环境操作  
# chmod 755/etc/rc.d/init.d/functions    #给functions755权限
如果单台LVS发生突发情况,例如宕机、发生不可恢复的错误,会导致用户无法访问后端所有的应用程序,可以基于LVS+keepalived实现负载均衡及高可用功能。如果使用了keepalived.conf配置,就不需要执行ipvsadm-A 命令去添加均衡的realserver命令了,所有的配置都在keepalived.conf里面设置即可。
 
四、LVS + keepalived 配置
 • 主MASTER的keepalived.conf配置:
! Configuration Filefor keepalived
global_defs {
   notification_email {
      ytwu@leqee.com
   }
   notification_email_from ytwu@leqee.com
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL
   vrrp_skip_check_adv_addr
#   vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}
#VIP1
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    lvs_sync_daemon_inteface eth0
    virtual_router_id 51
    priority 110
    advert_int 1
    nopreempt
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.28.88/24
   }        
}
virtual_server192.168.28.88 80 {
    delay_loop 6
    lb_algo wrr
    lb_kind DR
    persistence_timeout 60
    protocol TCP
    real_server 192.168.28.134 80 {
        weight 100
        TCP_CHECK {
           connect_port 80
           connect_timeout 10
           nb_get_retry 3
           delay_before_retry 3
          }
}        
    real_server 192.168.28.135 80 {
        weight 1
        TCP_CHECK {
           connect_port 80
           connect_timeout 10
           nb_get_retry 3
           delay_before_retry 3
  }
}
}
 • 备BACKUP的keepalived.conf配置:
    state BACKUP
    priority 90
Master keepalived配置state 状态为MASTER,priority设置为110,backup keepalived配置state状态为BACKUP,priority设置为90,转发方式为DR直连路由模式,算采用wrr模式,在LVSbackup服务器写入如上配置,需要注意客户端的配置修改优先级及状态。由于LVS采用LVS采用DR模式,根据DR模式转发原理,需在客户端realserver绑定VIP。
 
五、LVS DR客户端配置VIP
      根据DR模式的工作原理,director与realserver位于同一个物理网络中,当director直接将请求转发给realserver时,如果realserver检测到该请求包目的IP是VIP而非自己,便会丢弃,不会响应,为了解决这个问题,需在所有realserver上都配置上VIP,保证数据包不丢弃,同时由于后端realserver都配置VIP会导致IP冲突,所以需将VIP配置在lo网卡上,这样限制了VIP不会在物理交换机上产生MAC地址表,从而避免IP冲突。可用脚本来启动后端服务器VIP配置:
# vim/etc/init.d/lvsrs               #编辑一个lvsrs脚本,并放到/etc/init.d/下
#!/bin/bash 
#description : startrealserver
VIP=192.168.28.88
sh/etc/rc.d/init.d/functions
case "$1" in
start)
/usr/sbin/ifconfig lo:0$VIP broadcast $VIP netmask 255.255.255.255 up
/usr/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
echo " start LVSof REALServer"
exit 0
;;
stop)
/usr/sbin/ifconfig lo:0down
/usr/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 "close LVSDirectorserver"
exit 1
;;
*)
echo "Usage: $0{start|stop}"
;;
esac
# chmod 755/etc/init.d/lvsrs      #给新增lvsrs脚本一个755权限
# service lvsrsstart             #启动lvsrs服务,我环境启动时出错,给一个functions 755权限,按各自环境操作  
# chmod 755/etc/rc.d/init.d/functions    #给functions755权限
 
六、LVS 负载均衡排错
1)负载不均排查
生产环境中ipvsadm -L -n发现两台RS的负载均衡,一台有很多请求,一台没有并且没有请求的那台RS测试服务正常, lo:VIP也有,但是就是没有请求。
# ipvsadm -L -n
IP Virtual Serverversion 1.2.1 (size=4096)
Prot LocalAddress:PortScheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.28.88:80 rr
  -> 192.168.28.134:80            Route   1     0          0        
  -> 192.168.28.135:80            Route   1     0          0     
问题原因:
persistence_timeout 的原因,persistent会话保持,当clientA访问网络的时候,LVS把请求分发给了52,那么以后clientA 在点击的其他操作请求,也会发送给52这台机器。
解决办法:
到keepalived中注释掉 persistence_timeout 60 然后把/etc/init.d/keepalived reload 然后就可看到以后负载两边都均衡了。
导致负载均衡不均的原因可能有:
 • LVS自身的会话保持参数设置(-p300,persistent 300)
  优化:大公司尽量用cookies替代session
 • LVS调度算法设置 例如: rr  wrr wlc  lc算法
 • 后端RS节点的会话保持参数,例如:apache的keepalive参数
 • 访问较少的情况,不均衡的现象更加明显、
 • 用户发送的请求的时间长短,和请求资源的大小。
2)LVS故障拍错思路
 • 调度器上LVS调度规则及IP的正确性
 • RS节点上VIP绑定和arp抑制的检查
 生产环境中:
 • 对RS绑定的VIP做实时监控,出问题报警或者自动处理后报警
 • 把RS绑定的vip 做成配置文件,例如:vi/etc/sysconfig/network-script/lo:0
3)ARP抑制的配置思路:
 • 如果是单个VIP那么可以用stop传参设置0
 • 如果rs端有多个vip绑定,此时,即使停止VIP绑定,也不一定不要配置0
if [ ${#VIP[@]} -lt 1];then
  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
fi
 • RS节点上自身提供服务的检查(DR不能端口转换)
 • 辅助排除工具有tcpdump ping 等
 • 负载均衡和反向代理集群的三角形排查理论:
   haproxy 代理
   -     -
  -       -
 -         -
用户--------------webserver 
   Squid 代理
   -     -
  -       -
 -         -
用户--------------webserver 
tcpdump命令:
#抓取访问游览器访问的数据包
# tcpdump -i eth0tcp port 80 -x -vv -X -s 1500
4)集群LVS高并发拓展方案
 • LVS Cluster部署(OSPF + LVS)
http://my.oschina.net/lxcong/blog/143904
 • DNS轮询(数据库–全国IP分配的运营商以及省市)
  1)智能DNS
    根据用户线路的位置
    选项和用户最近的服务器线路相同的机房的地址
5)LVS集群下的代码发布方案详解
代码上线的基本流程:
发布代码:
开发人员本地测试---》办公室内部测试(开发人员,测试人员)---》(配置管理员)---》IDC机房环境测试(测试人员)---》正式服务器
1、例如:后台代码是PHP环境
一般上线方式分为:
测试好代码后,正式上线是把测试好的代码先推送到正式环境的目录(新建一个目录)下面
 • 等待推送完成后,确认ok然后使用mv命令替换
 • 等待推送完成后,使用ln命令做软连接
最大程度的保证用户体验
2、例如:后台代码是JAVA环境(上线服务需要重启)
一般上线方式分为:
利用lvs服务平滑上线
  大概过程是:LVS下有6台webserver (分为两组)使用ipvsadm -d 剔除另外一组,然后挂到另外一组VIP上测试,测试好后利用ipvsadm-a在添加进来。然后在对另外一组同样的操作。
总结:
代码上线是一个多方协作配合的一个项目流程环节,除了技术方案本身其科学完整的上线方案也非常重要。在过程中按照完备的流程,与开发、测试的前期的沟通也是保证完成整个上线流程的必要前提保障。
实例:
企业网站LVS+keepalived+Nginx 架构中,突然发现网站部分用户访问巨慢,甚至无法访问:
 • 客户端ping网站域名,通过ping返回域名对应的IP是否正常;
 • 如果无法返回IP,或者响应比较慢,定位 DNS 或者网络延迟问题,可以通过tracert域名测试客户端到服务器的延迟;
 • 登录 LVS 服务器,ipvsadm -L -n 查看当前后端Web连接信息。
通过LVS ipvsadm 信息,检查轮询方式与权重。无异常,猜测是某一台Web服务器无法访问或者访问巨慢导致。
查看keepaleved.conf 负载均衡健康检查配置,部分代码如下:
    real_server 192.168.28.135 80 {
        weight 1
        TCP_CHECK {
           connect_port 80
           connect_timeout 10
           nb_get_retry 3
           delay_before_retry 3
  }
}
通过配置文件发现LVS默认使用的是默认的80端口,只要80端口能通,请求就会被转发到后端服务器,使用wget http://192.168.28.135/ 返回很慢,直到超时,另外几台realserver 返回正常。经检查发现192.168.28.135服务器ifconfig查看IP,但没有发现VIP地址绑定lo:0网卡上。配置VIP后恢复正常。
为防止上述突发问题,增加LVS对后端Nginx URL的检测,能访问则表示服务正常,对比之前的检测方式,从单纯的80端口到现在的URL检测,后端如果某台出现502超时错误,keepalived列表会自动踢出异常的realserver,等待后端realserver 恢复后自动添加到服务器正常列表。keepalived 基于URL检查代码如下:
    real_server 192.168.28.135 80 {
        weight 1
           HTTP_GET {
              url {
              path /monitor/warn.jsp
              status_code 200
              }
           connect_timeout 10
           nb_get_retry 3
           delay_before_retry 3
  }
}