使用lvs与keepalived实现负载均衡
2010-11-05 11:15:11 阿炯

一、LVS与Keepalived介绍
LVS
LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统。本项目在1998年5月由章文嵩博士成立,是中国国内最早出现的自由软件项目之一。目前有三种IP负载均衡技术(VS/NAT、VS/TUN和VS/DR),十种调度算法(rrr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq)。Keepalived在这里主要用作RealServer的健康状态检查以及LoadBalance主机和BackUP主机之间故障转移的实现。

 

Keepalvied
Keepalived在这里主要用作RealServer的健康状态检查以及LoadBalance主机和BackUP主机之间故障转移的实现。keepalived 是一个类似于layer3、4 、5交换机制的软件,也就是我们平时说的第3层、第4层和第5层交换。Keepalived的作用是检测web服务器的状态,如果有一台web服务器死机,或工作出现故障,Keepalived将检测到,并将有故障的web服务器从系统中剔除,当真实服务器工作正常后Keepalived自动将web服务器加入到服务器群中,这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的web服务器。

Layer3、4、5工作在IP/TCP协议栈的IP层,TCP层,及应用层,原理分别如下:
Layer3:Keepalived使用Layer3的方式工作式时,Keepalived会定期向服务器群中的服务器发送一个ICMP的数据包(既我们平时用的Ping包),如果发现某台服务的IP地址没有激活,Keepalived便报告这台服务器失效,并将它从服务器群中剔除,这种情况的典型例子是某台服务器被非法关机。Layer3的方式是以服务器的IP地址是否有效作为服务器工作正常与否的标准。

Layer4:如果理解了Layer3的方式,Layer4就容易了。Layer4主要以TCP端口的状态来决定服务器工作正常与否。如web server的服务端口一般是80,如果Keepalived检测到80端口没有启动,则Keepalived将把这台服务器从服务器群中剔除。

Layer5:Layer5就是工作在具体的应用层了,比Layer3,Layer4要复杂一点,在网络上占用的带宽也要大一些。 Keepalived将根据用户的设定检查服务器程序的运行是否正常,如果与用户的设定不相符,则Keepalived将把服务器从服务器群中剔除。


LVS负载均衡机制

(1)LVS是四层负载均衡,也就是说建立在OSI模型的第四层——传输层之上,传输层上有我们熟悉的TCP/UDP,LVS支持TCP/UDP的负载均衡。因为LVS是四层负载均衡,因此它相对于其它高层负载均衡的解决办法,比如DNS域名轮流解析、应用层负载的调度、客户端的调度等,它的效率是非常高的。

(2)LVS的转发主要通过修改IP地址(NAT模式,分为源地址修改SNAT和目标地址修改DNAT)、修改目标MAC(DR模式)来实现。

①NAT模式:网络地址转换


NAT(Network Address Translation)是一种外网和内网地址映射的技术。NAT模式下,网络数据报的进出都要经过LVS的处理。LVS需要作为RS(真实服务器)的网关。当包到达LVS时,LVS做目标地址转换(DNAT),将目标IP改为RS的IP。RS接收到包以后,仿佛是客户端直接发给它的一样。RS处理完,返回响应时,源IP是RS IP,目标IP是客户端的IP。这时RS的包通过网关(LVS)中转,LVS会做源地址转换(SNAT),将包的源地址改为VIP,这样,这个包对客户端看起来就仿佛是LVS直接返回给它的。客户端无法感知到后端RS的存在。

②DR模式:直接路由


DR模式下需要LVS和RS集群绑定同一个VIP(RS通过将VIP绑定在loopback实现),但与NAT的不同点在于:请求由LVS接受,由真实提供服务的服务器(RealServer, RS)直接返回给用户,返回的时候不经过LVS。详细来看,一个请求过来时,LVS只需要将网络帧的MAC地址修改为某一台RS的MAC,该包就会被转发到相应的RS处理,注意此时的源IP和目标IP都没变,LVS只是做了一下移花接木。RS收到LVS转发来的包时,链路层发现MAC是自己的,到上面的网络层,发现IP也是自己的,于是这个包被合法地接受,RS感知不到前面有LVS的存在。而当RS返回响应时,只要直接向源IP(即用户的IP)返回即可,不再经过LVS。

(3)DR负载均衡模式数据分发过程中不修改IP地址,只修改mac地址,由于实际处理请求的真实物理IP地址和数据请求目的IP地址一致,所以不需要通过负载均衡服务器进行地址转换,可将响应数据包直接返回给用户浏览器,避免负载均衡服务器网卡带宽成为瓶颈。因此,DR模式具有较好的性能,也是目前大型网站使用最广泛的一种负载均衡手段。


二、网站负载均衡拓朴图
IP信息列表:
名称用途            IP
lvsmaster        192.168.2.116
lvsbackup        192.168.2.110
lvsvip            192.168.2.101   
realserver01        192.168.2.100
realserver02        192.168.2.102

三、CentOS下安装并配置LVS和Keepalvied
1.下载相关软件包
#mkdir /usr/src/lvs
#cd /usr/src/lvs
#wgethttp://www.linuxvirtualserver.org/software/kernel-2.6/ipvsadm-1.24.tar.gz
#wgethttp://www.keepalived.org/software/keepalived-1.1.16.tar.gz

2.安装LVS和Keepalived
#查看是否已安装了ipvs模块
#lsmod |grep ip_vs
#uname -r
2.6.18-53.el5PAE
#安装过程中需要一个内核header包,请一定要安装与系统已安装内核版本号完全一致的头包。
#ln -s /usr/src/kernels/2.6.18-53.el5PAE-i686/  /usr/src/linux
#tar zxvf ipvsadm-1.24.tar.gz
#cd ipvsadm-1.24
#make && make install

#find / -name ipvsadm  # 查看ipvsadm的位置
#tar zxvf keepalived-1.1.16.tar.gz
#cd keepalived-1.1.16
#./configure --prefix=/usr/ && make && make install #记得一定要在”./configure”时加上这一路径,不然编译出来运行会不正常。
#find / -name keepalived  # 查看keepalived位置              

#cp /usr/etc/rc.d/init.d/keepalived /etc/rc.d/init.d/
#cp /usr/etc/sysconfig/keepalived /etc/sysconfig/
#mkdir /etc/keepalived
#cp /usr/etc/keepalived/keepalived.conf /etc/keepalived/
#cp /usr/sbin/keepalived /usr/sbin/
#service keepalived start|stop     #做成系统启动服务方便管理.

3.配置LVS实现负载均衡
1).LVS-DR,配置LVS脚本实现负载均衡
#vi /usr/sbin/lvs-dr.sh
#!/bin/bash
#Description: start LVS of Director Route
#Written by:hto

gateway='192.168.2.97'
#website director vip.
vip=192.168.2.101
rip01=192.168.2.100
rip02=192.168.2.102

#载入系统内定的操作函数
./etc/rc.d/init.d/functions

#写入日志
logger $0 called with $1

case "$1" in
start)
#set web vip
# Clear all iptables rules.
# /sbin/iptables -F
# Reset iptables counters.
/sbin/iptables -Z
# Clear all ipvsadm rules/services.
/sbin/ipvsadm --clear

/sbin/ipvsadm --set 30 5 60
/sbin/ifconfig eth0:0 $vip broadcast $vip netmask 255.255.255.255 broadcast $vip up
/sbin/route add -host $vip dev eth0:0
/sbin/ipvsadm --add-service --tcp-service $vip:80 --scheduler wrr --persistent 3
/sbin/ipvsadm --add-server --tcp-service $vip:80 --real-server $rip01:80 --gatewaying --weight 1
/sbin/ipvsadm --add-server --tcp-service $vip:80 --real-server $rip02:80 --gatewaying --weight 1
touch /var/lock/subsys/ipvsadm >/dev/null 2>&1
;;

stop)
/sbin/ipvsadm -C
/sbin/ipvsadm -Z
ifconfig eth0:0 down
route del $vip
rm -rf /var/lock/subsys/ipvsadm >/dev/null 2>&1
echo "ipvsadm stoped"
;;

status)
if [ ! -e /var/lock/subsys/ipvsadm ];then
echo "ipvsadm stoped"
exit 1
else
echo "ipvsadm OK"
fi
;;

*)
echo "Usage: $0 {start|stop|status}"
exit 1

esac
exit 0

2).配置Realserver脚本.
#vi /usr/local/sbin/realserver.sh
#!/bin/bash
#Description: Config realserver eth0 as real server
#Written by :hto

vip=192.168.2.101

. /etc/rc.d/init.d/functions

case "$1" in
start)
ifconfig eth0:0 $vip netmask 255.255.255.255 broadcast $vip
/sbin/route add -host $vip dev eth0: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 eth0:0 down
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

附上realserver机上的/etc/sysctl.conf:

# Kernel sysctl configuration file for Red Hat Linux
#
# For binary values, 0 is disabled, 1 is enabled.  See sysctl(8) and
# sysctl.conf(5) for more details.
# Controls IP packet forwarding
net.ipv4.ip_forward = 1
# Controls source route verification
net.ipv4.conf.default.rp_filter = 1
# Do not accept source routing
net.ipv4.conf.default.accept_source_route = 0
# Controls the System Request debugging functionality of the kernel
kernel.sysrq = 0
# Controls whether core dumps will append the PID to the core filename.
# Useful for debugging multi-threaded applications.
kernel.core_uses_pid = 1
net.ipv4.conf.eth0.arp_ignore = 1
net.ipv4.conf.eth0.arp_announce = 2
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
或者采用secondary ip address方式配置
# vi /etc/sysctl.conf

添加以下内容如上所示:
net.ipv4.conf.eth0.arp_ignore = 1
net.ipv4.conf.eth0.arp_announce = 2
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
#sysctl -p
#ip addr add 192.68.2.101/32 dev eth0
#ip add list 查看是否绑定

3).启动lvs-dr脚本和realserver启本,在DR上可以查看LVS当前状态:
#watch ipvsadm –ln

四、利用Keepalvied实现负载均衡和和高可用性

1.配置在主负载均衡服务器上配置keepalived.conf

keepalived.conf之vrrp instance部分解读
keepalived既可以配合lvs使用,也可以单独使用,所以它的配置文件分为如下几个部分:
1. Global Configuration
2. Global definitions
3. Static routes/addresses
4. Vrrpd Configuration
5. VRRP synchronization group(s)
6. VRRP instance(s)
7. Lvs Configuration
8. Virtual server group(s)
9. Virtual server(s)

下面是对这个配置的解释:
state MASTER|BACKUP
#如果不指定Master或者BACKUP,那priority最高的就是master

interface eth0
#监听的实际网口

virtual_router_id 51
#组播ID,通过224.0.0.18可以监听到现在已经存在的VRRP ID,最好不要跟现有ID冲突

priority 100
#权重为100,权重数字越大就越高

advert_int 1
#发送组播包的间隔时间,默认为1秒

smtp_alert
#发送邮件报警

authentication {
auth_type PASS
auth_pass youpass
}
#这个是验证类型为PASS(明文),密码为youpass。验证类型也可以选择IPSEC,但是官方是不推荐的

virtual_ipaddress {
192.168.2.101
}
#虚拟IP为 192.168.2.101

#############下面这些是文档中存在,但是在上面没有用到的#############################

dont_track_primary
#忽略网卡错误

track_interface {
eth0
eth1
}
#监控eth0和eth1这2块网卡的状态

mcast_src_ip
#使用这个地址作为多播包的源IP,而不是使用interface eth0上的IP

lvs_sync_daemon_interface eth1
#绑定eth1作为lvs同步的

garp_master_delay 2
#master和slave漂移时间改为2秒,默认位5秒

virtual_ipaddress {
/ brd dev scope label 192.168.200.17/24 dev eth1
192.168.200.18/24 dev eth2 label eth2:1
}
#vip可以写成整个网段和某块网卡上的所有IP

virtual_ipaddress_excluded {
/ brd dev scope / brd dev scope ...
}
#排除哪些IP

virtual_routes {
src 192.168.100.1 to 192.168.109.0/24 via 192.168.200.254 dev eth1 192.168.110.0/24 via 192.168.200.254 dev eth1 192.168.111.0/24 dev eth2 192.168.112.0/24 via 192.168.100.254
}
#当状态切换的时候会增加和删除路由,格式如src [to] / via|gw dev scope tab

nopreempt
#这个参数是用来,当master当掉,slave接替原来的master作为master后,这个时候当master重新起来后,有了这个参数后原来的slave就不会自动再自动切换为slave,而是继续作为master

preempt_delay 300
#接上面那个参数,这个表示,只有在老的master重新正常300秒后,老的master才会切换为master,这个参数范围是0-1000,默认为0

notify_master | notify_backup
| notify_fault | notify |
smtp_alert
#各种报警方式,可以定义具体的内容来达到不同的报警信息。

上面这些是官方的配置文件,下面这些是放狗搜索出来的其它配置,主要是为了做服务状态的检测,不然keepalived只能看网口有没有down掉再进行迁移,那样就要另外写其它的监控脚本来达到当服务挂掉后就把网口down掉。下面这个是在1.1.13版本之后就实现了。

! Configuration File for keepalived
vrrp_script chk_sshd {
script "killall -0 sshd" # cheaper than pidof
interval 2 # check every 2 seconds weight -4 # default prio: -4 if KO }
vrrp_script chk_haproxy {
script "killall -0 haproxy" # cheaper than pidof
interval 2 # check every 2 seconds }
vrrp_script chk_http_port {
script "/tcp/127.0.0.1/80" # connects and exits
interval 1 # check every second
weight -2 # default prio: -2 if connect fails
}

vrrp_script chk_https_port {
script "/tcp/127.0.0.1/443"
interval 1
weight -2
}

vrrp_script chk_smtp_port {
script "/tcp/127.0.0.1/25"
interval 1
weight -2
}

vrrp_instance VI_1 {
interface eth0
state MASTER
virtual_router_id 51
priority 100
virtual_ipaddress {
192.168.200.18/25
}
track_interface {
eth1 weight 2 # prio = +2 if UP
eth2 weight -2 # prio = -2 if DOWN
eth3 # no weight, fault if down
}
track_script {
chk_sshd # use default weight from the script chk_haproxy weight 2 # +2 if process is present
chk_http_port
chk_https_port
chk_smtp_port
}
}

vrrp_instance VI_2 {
interface eth1
state MASTER
virtual_router_id 52
priority 100
virtual_ipaddress {
192.168.201.18/26
}
track_interface {
eth0 weight 2 # prio = +2 if UP
eth2 weight -2 # prio = -2 if DOWN
eth3 # no weight, fault if down
}
track_script {
chk_haproxy weight 2
chk_http_port
chk_https_port
chk_smtp_port
}
}

====================================
#vim /etc/keepalived/keepalived.conf
global_defs {
notification_email {
lvsm@mail.loc
#failover@firewall.loc
#sysadmin@firewall.loc
}
notification_email_from lvs@mail.loc
smtp_server 127.0.0.1
#smtp_connect_timeout 30
router_id LVS_DEVEL
}

#VIP1
vrrp_instance VI_1 {
state MASTER             #备份服务器上将MASTER改为BACKUP 
interface eth0
virtual_router_id 51
priority 100    #备份服务上将100改为比100小的数字,如99
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.2.101 
#(如果有多个VIP,继续换行填写.)
}
}

virtual_server 192.168.2.101 80 {
delay_loop 10                  #(每隔10秒查询realserver状态)
lb_algo wrr                  #(lvs 算法)
lb_kind DR                  #(Direct Route-直接路由)
persistence_timeout 60        #(同一IP的连接60秒内被分配到同一台realserver)
protocol TCP                #(用TCP协议检查realserver状态)

real_server 192.168.2.100 80 {
weight 3               #(权重)
TCP_CHECK {
connect_timeout 10       #(10秒无响应超时)
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
real_server 192.168.2.102 80 {
weight 3
TCP_CHECK {
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
}

2.BACKUP服务器同上配置,先安装lvs再按装keepalived,仍后配置/etc/keepalived/keepalived.conf,只需将上述的部分改一下即可.

3.vim /etc/rc.local
#/usr/local/sbin/lvs-dr.sh  将lvs-dr.sh这个脚本注释掉。步
#/usr/local/sbin/lvs-dr.sh stop 停止lvs-dr脚本
#/etc/init.d/keepalived start  启动keepalived 服务,keepalived就能利用keepalived.conf 配
置文件,实现负载均衡和高可用.

4.查看lvs服务是否正常
#watch ipvsadm –ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  61.164.122.8:80 wrr persistent 60
-> 192.168.2.102:80            Route   3      0          0
-> 192.168.2.100:80             Route   5      0          0
#tail –f /var/log/message  监听日志,查看状态,测试LVS负载均衡及高可用性是否有效。

5.停Master服务器的keepalived服务,查看BAKCUP服务器是否能正常接管服务。

五、Debian下安装并配置LVS和Keepalvied
这里我们在debian采用nginx来做web服务器,使用lvs与keepalived做负载均衡,使用'IP Tunnel'模式。
1.安装相关软件包
将各个机器上的apt源更新至最新
#apt-get update

1).web环境配置
在两台realserver上安装好nginx。将其配置好后,能使用ip地址直接访问没有问题,在其默认文档目录'/var/www/nginx-default/'创建一'info.html'的文件,用vim编辑其内容仅为其ip的最后一位(192.168.2.100则取其中的'100')。分别使用浏览器访问:http://192.168.2.100|102/info.html 能看到各自的ip地址最后一位,这样我们可以在集群环境里测试我正在连接的是哪台主机。

2).lvs与keepalived安装及配置
在lvsmaster与lvsbackup主机安装其,配置文件位置在目录:/etc/keepalived/下。
#apt-get install keepalived

启动keepalived后内核会加载下面所列的模块。
# lsmod|grep vs
ip_vs_wrr               2336  1
ip_vs                  63424  3 ip_vs_wrr

这里提供一个我的配置参考文件:
global_defs {
notification_email {
lvsm@freeoa.net
}
notification_email_from hto@freeoa.net
smtp_server smtp.freeoa.net
smtp_connect_timeout 10
router_id freeoa_site
}

vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 50
nopreempt
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 3at_a-32
}
virtual_ipaddress {
192.168.2.101
192.168.2.105
}
}

virtual_server 192.168.2.101 80 {
delay_loop 10
lb_algo wrr
lb_kind TUN    #注意这里与前面的调度方法不一样
persistence_timeout 60        #(同一IP的连接60秒内被分配到同一台realserver,建议与apache或nginx中设置的连接超时值一样)
protocol TCP                #(用TCP协议检查realserver状态)

#  sorry_server 192.168.200.200 1358

real_server 192.168.2.100 80 {
weight 100
#这里采用了更加明确的验证方法,使用文件的md5哈希码,具体下面将会讲解
HTTP_GET {
url {
path /info.html
digest 60b8e060b9d08011fd413a74d93d18f7
}
connect_timeout 5
nb_get_retry 5
delay_before_retry 5
}
}
#####
real_server 192.168.2.102 80 {
weight 100
HTTP_GET {
url {
path /info.html
digest c1a252a8902bbdbf08808cf96f16c207
}
connect_timeout 5
nb_get_retry 5
delay_before_retry 5
}
}
}

2.keepalived认识及配置
keepalived是VRRP(虚拟路由器冗余协议)的一个很好的软件实现。关于其工作原理和实现方法可以写一本书了。这里只是讲一下它是如何来验证后端的真实服务器的。
真实主机要对外提供服务,它必须是对外可以连接且在特定端口提供特定的服务。我们就可以通过其是否可连接、端口是否存在、所请求的内容是否正常等,以不同层次的判断标准来作为其考核后端服务器是否正常。

我们这里就以上面为例来说明其从'请求的内容'来考核真实服务器的实现过程吧:通过http的方式来取得默认站点下的'info.html'文件,并计算出其md5值,来与配置文件中的相比较,相同则认为其正常,反之亦反。即使返回的是一个404页面,只要md5校验码值相等,都可以通过的。参考配置文件中的这一段:
url {
path /info.html
digest c1a252a8902bbdbf08808cf96f16c207
}
那么我们如何取得这个校验码呢?
1)genhas工具
这是keepalived自带的工具,
# /usr/bin/genhash -s 192.168.2.100 -p 80 -u /info.html

MD5SUM = 60b8e060b9d08011fd413a74d93d18f7

可以为其加上一个参数'-v',可以查看到更加详细的内容:
# /usr/bin/genhash -s 192.168.2.100 -p 80 -u /info.html -v

2)在配置文件中不写其值,通过重启keepalived让它去验证对应服务器的文件码值,它会在'/var/log/messages'中写入对应的值,将它从日志文件取出写到配置文件中即可。

当验证不能通过时,keepalived将会把这台主机从集群中移除,每隔'delay_loop'秒后,再去检查该主机下的所定义的文件的校验码是否正确(与配置文件中写的相一致),若正确则将其重新加入集群。

注意:它是通过ip地址访问的方式来实现验证的,如果在集群中有一台主机的web服务没有邦定相关域名及其配置文件,keepalived是检查不出来的(用户就会间歇性访问不到正常的页面),除非将ip地址替换为域名,但那样可能会降低效率。同样的在lvsbackup主机也需要同样的配置,甚至可以将配置文件复制过去,注意修改'state MASTER'为'state BACKUP','priority 100'为'priority 99'(只要比100小的正数即可)。

3.realserver的配置
想要通过keepalived的用户请求分配到真实主机上,realserver必须持有一个虚拟ip,即'vip'。在dr与tunnel模式下,真实主机将用户所请求的内容直接发给用户。其配置如下:
# ifconfig
eth0      Link encap:Ethernet  HWaddr 08:00:27:26:94:b4 
inet addr:192.168.2.100  Bcast:192.168.2.127  Mask:255.255.255.224
inet6 addr: fe80::a00:27ff:fe26:94b4/64 Scope:Link
UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
RX packets:29847 errors:0 dropped:0 overruns:0 frame:0
TX packets:21446 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:17299413 (16.4 MiB)  TX bytes:2721068 (2.5 MiB)

tunl0     Link encap:IPIP Tunnel  HWaddr  
UP RUNNING NOARP  MTU:1480  Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

tunl0:101 Link encap:IPIP Tunnel  HWaddr  
inet addr:192.168.2.101  Mask:255.255.255.224
UP RUNNING NOARP  MTU:1480  Metric:1

可以编写脚本来做以上配置:
# vim /etc/init.d/tunl.sh
#!/bin/bash
##First intface
ifconfig tunl0 0.0.0.0 -arp up

ifconfig tunl0:101 192.168.2.101 netmask 255.255.255.224 broadcast 192.168.2.127 -arp up

echo "0" > /proc/sys/net/ipv4/conf/tunl0/rp_filter
echo '2' > /proc/sys/net/ipv4/conf/tunl0/arp_announce
echo '1' > /proc/sys/net/ipv4/conf/tunl0/arp_ignore
echo '2' > /proc/sys/net/ipv4/conf/lo/arp_announce
echo '1' > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo '2' > /proc/sys/net/ipv4/conf/all/arp_announce
echo '1' > /proc/sys/net/ipv4/conf/all/arp_ignore

iptables -A OUTPUT -s 192.168.2.101 -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN,ACK -j TCPMSS --set-mss 1440

赋于其可执行权限并加入到'/etc/init.d/rc.local'中使之中开机启动。

至此,基本的带负载均衡的功能集群搭建起来了。

4.测试及验证
现在用浏览器或lynx、w3m这些工具来进行访问测试。对vip(192.168.2.101)的info.html文件请求,在一段时间内,分配到同一机器是正常的,所以需要多台机器用来测试访问,在Linux下可以用下面的方式来测试。
# lynx http://192.168.2.101/info.html

注意:所有的机器都可以用来测试,但对集群的机器不能用来测试这样的连接访问!

1).日志监测法
在lvsmaster机器上可以看到日志(/var/log/messages):
Nov  5 08:13:48 lvsm Keepalived_vrrp: Using MII-BMSR NIC polling thread...
Nov  5 08:13:48 lvsm Keepalived_vrrp: Registering Kernel netlink reflector
Nov  5 08:13:48 lvsm Keepalived_vrrp: Registering Kernel netlink command channel
Nov  5 08:13:48 lvsm Keepalived_vrrp: Registering gratutious ARP shared channel
Nov  5 08:13:48 lvsm kernel: [   39.511587] IPVS: Registered protocols (TCP, UDP, AH, ESP)
Nov  5 08:13:48 lvsm kernel: [   39.511673] IPVS: Connection hash table configured (size=4096, memory=32Kbytes)
Nov  5 08:13:48 lvsm kernel: [   39.511715] IPVS: ipvs loaded.
Nov  5 08:13:48 lvsm Keepalived_vrrp: Opening file '/etc/keepalived/keepalived.conf'.
Nov  5 08:13:48 lvsm Keepalived_healthcheckers: Using MII-BMSR NIC polling thread...
Nov  5 08:13:48 lvsm Keepalived_healthcheckers: Registering Kernel netlink reflector
Nov  5 08:13:48 lvsm Keepalived_healthcheckers: Registering Kernel netlink command channel
Nov  5 08:13:48 lvsm Keepalived_healthcheckers: Opening file '/etc/keepalived/keepalived.conf'.
Nov  5 08:13:48 lvsm Keepalived_vrrp: Configuration is using : 36578 Bytes
Nov  5 08:13:48 lvsm Keepalived_healthcheckers: Configuration is using : 14707 Bytes
Nov  5 08:13:49 lvsm kernel: [   39.826088] IPVS: [wrr] scheduler registered.
Nov  5 08:13:49 lvsm Keepalived_healthcheckers: Activating healtchecker for service [192.168.2.100:80]
Nov  5 08:13:49 lvsm Keepalived_healthcheckers: Activating healtchecker for service [192.168.2.102:80]
Nov  5 08:13:49 lvsm Keepalived_vrrp: VRRP_Instance(VI_1) Transition to MASTER STATE
Nov  5 08:13:50 lvsm Keepalived_healthcheckers: Error connecting server [192.168.2.102:80].
Nov  5 08:13:50 lvsm Keepalived_healthcheckers: Removing service [192.168.2.102:80] from VS [192.168.2.101:80]
Nov  5 08:13:50 lvsm Keepalived_healthcheckers: Remote SMTP server [127.0.0.1:25] connected.
Nov  5 08:13:50 lvsm Keepalived_healthcheckers: SMTP alert successfully sent.
Nov  5 08:13:50 lvsm Keepalived_vrrp: VRRP_Instance(VI_1) Entering MASTER STATE
Nov  5 08:13:50 lvsm Keepalived_vrrp: Netlink: skipping nl_cmd msg...
Nov  5 08:13:50 lvsm Keepalived_vrrp: Netlink: skipping nl_cmd msg...

这里102的机器没有启动,所以lvs移除了它。我们来启动102上的nginx,看有什么日志输出:
Nov  5 10:50:26 lvsm Keepalived_healthcheckers: MD5 digest success to [192.168.2.102:80] url(1).
Nov  5 10:50:36 lvsm Keepalived_healthcheckers: Remote Web server [192.168.2.102:80] succeed on service.
Nov  5 10:50:36 lvsm Keepalived_healthcheckers: Adding service [192.168.2.102:80] to VS [192.168.2.101:80]
Nov  5 10:50:36 lvsm Keepalived_healthcheckers: Remote SMTP server [127.0.0.1:25] connected.
Nov  5 10:50:36 lvsm Keepalived_healthcheckers: SMTP alert successfully sent.

将102加入到了集群中。

2).使用'ipvsadm'命令查看
该命令可以查看各真实服的状态,示例如下:
# ipvsadm -l -n --stats
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port               Conns   InPkts  OutPkts  InBytes OutBytes
-> RemoteAddress:Port
TCP  192.168.2.101:80                    5       46        0     7118        0
-> 192.168.2.102:80                    1       10        0     1681        0
-> 192.168.2.100:80                    4       36        0     5437        0

可以看到每台机器的连接数、进来通过的流量,在dr及Tunnel模式下,只能看到进来的流量,而看不到出去的流量,即'只进不出'。为什么呢?这个思考留给你吧,笔者前面也已经说过。

还可以通过:# ipvsadm -l -n  -c
IPVS connection entries
pro expire state       source             virtual            destination
TCP 14:53  ESTABLISHED 192.168.2.106:1036 192.168.2.101:80   192.168.2.100:80
TCP 14:56  ESTABLISHED 192.168.2.98:1334  192.168.2.101:80   192.168.2.102:80
TCP 00:36  NONE        192.168.2.98:0     192.168.2.101:80   192.168.2.102:80
TCP 00:02  NONE        192.168.2.106:0    192.168.2.101:80   192.168.2.100:80

查看客户与服务器的连接记录。客户只能看到与101(vip)之间的通信,而看不到真实服务器的ip;但返回给用户的数据包是从真实服务器的ip上过来的,但它用的是vip地址。

3).keepalived主、备切换
如果lvsmaster 这台主机失效了,那整个集群就不能正常工作了吗?显然设计者也考虑到了这一点,lvsbackup 就是这样一台主机,当它检查到master主机出现不可用时,接替它来进行工作。我们重启一下lvsmaster这台主机,看下lvsbackup主机的日志里会有什么。
# tail -f /var/log/messages
Nov  5 12:49:29 phaster Keepalived_healthcheckers: Registering Kernel netlink reflector
Nov  5 12:49:29 phaster Keepalived_healthcheckers: Registering Kernel netlink command channel
Nov  5 12:49:29 phaster Keepalived_healthcheckers: Opening file '/etc/keepalived/keepalived.conf'.
Nov  5 12:49:29 phaster Keepalived_healthcheckers: Configuration is using : 14711 Bytes
Nov  5 12:49:29 phaster Keepalived_vrrp: Opening file '/etc/keepalived/keepalived.conf'.
Nov  5 12:49:29 phaster Keepalived_vrrp: Configuration is using : 36582 Bytes
Nov  5 12:49:29 phaster Keepalived_vrrp: VRRP_Instance(VI_1) Entering BACKUP STATE
Nov  5 12:49:29 phaster kernel: [   24.513722] IPVS: [wrr] scheduler registered.
Nov  5 12:49:29 phaster Keepalived_healthcheckers: Activating healtchecker for service [192.168.2.100:80]
Nov  5 12:49:29 phaster Keepalived_healthcheckers: Activating healtchecker for service [192.168.2.102:80]
Nov  5 13:08:34 phaster Keepalived_vrrp: VRRP_Instance(VI_1) Transition to MASTER STATE
Nov  5 13:08:35 phaster Keepalived_vrrp: VRRP_Instance(VI_1) Entering MASTER STATE
Nov  5 13:08:35 phaster Keepalived_vrrp: Netlink: skipping nl_cmd msg...
Nov  5 13:08:35 phaster Keepalived_vrrp: Netlink: skipping nl_cmd msg...
Nov  5 13:09:15 phaster Keepalived_vrrp: VRRP_Instance(VI_1) Received higher prio advert
Nov  5 13:09:15 phaster Keepalived_vrrp: VRRP_Instance(VI_1) Entering BACKUP STATE
Nov  5 13:09:15 phaster Keepalived_vrrp: Netlink: skipping nl_cmd msg...
Nov  5 13:09:15 phaster Keepalived_vrrp: Netlink: skipping nl_cmd msg...

先是它处于备机状态,后它随着master停机而成为'MASTER STATE',接替它为外界用户提供服务,当master机重启完成以后,它交出控制权,自我降级为'BACKUP STATE'。这就是一个较完整的主、备切换过程。

六、关于LVS的回答式总结


LVS负载均衡有哪些策略?
LVS一共有三种工作模式: DR,Tunnel,NAT

对LVS的理解?
LVS是一个虚拟的服务器集群系统,在unix系统下实现负载均衡的功能;采用IP负载均衡技术和机遇内容 请求分发技术来实现。

LVS采用三层结构分别是:
第一层:负载调度器
第二层:服务池
第三层:共享存储

负载调度器(load balancer/Director),是整个集群的总代理,它有两个网卡,一个网卡面对访问网站的客户端,一个网卡面对整个集群的内部。负责将客户端的请求发送到一组服务器上执行,而客户也认为服务是来自这台主机的。举个生动的例子,集群是个公司,负载调度器就是在外接受请求,将接到的请求分发给后台的真正服务的真正的主机们。当然需要将活按照一定的算法分发下去,让大家都公平的服务。

服务器池(server pool/Realserver),是一组真正执行客户请求的服务器,可以当作WEB服务器。

共享存储(shared storage),它为服务器池提供一个共享的存储区,这样很容易使得服务器池拥有相同的内容,提供相同的服务。


负载均衡的原理是什么?
当客户端发起请求时,请求直接发给Director Server(调度器),这时会根据设定的调度算法,将请求按照算法的规定智能的分发到真正的后台服务器。以达到将压力均摊。

LVS由哪两部分组成的?
LVS 由2部分程序组成,包括 ipvs 和 ipvsadm。

1.ipvs(ip virtual server):一段代码工作在内核空间,叫ipvs,是真正生效实现调度的代码。

2. ipvsadm:另外一段是工作在用户空间,叫ipvsadm,负责为ipvs内核框架编写规则,定义谁是集 群服务,而谁是后端真实的服务器(Real Server)

与lvs相关的术语有哪些?
DS:Director Server。指的是前端负载均衡器节点。
RS:Real Server。后端真实的工作服务器。
VIP:Virtual IP 向外部直接面向用户请求,作为用户请求的目标的IP地址。
DIP:Director Server IP,主要用于和内部主机通讯的IP地址。
RIP:Real Server IP,后端服务器的IP地址。
CIP:Client IP,访问客户端的IP地址。


LVS-NAT模式的原理


(a). 当用户请求到达Director Server,此时请求的数据报文会先到内核空间的PREROUTING链。 此时报文的源IP为CIP,目标IP为VIP

(b). PREROUTING检查发现数据包的目标IP是本机,将数据包送至INPUT链

(c). IPVS比对数据包请求的服务是否为集群服务,若是,修改数据包的目标IP地址为后端服务器 IP, 然后将数据包发至POSTROUTING链。 此时报文的源IP为CIP,目标IP为RIP

(d). POSTROUTING链通过选路,将数据包发送给Real Server

(e). Real Server比对发现目标为自己的IP,开始构建响应报文发回给Director Server。 此时报文 的源IP为RIP,目标IP为CIP

(f). Director Server在响应客户端前,此时会将源IP地址修改为自己的VIP地址,然后响应给客户 端。 此时报文的源IP为VIP,目标IP为CIP

LVS-NAT模型的特性

RS应该使用私有地址,RS的网关必须指向DIP

DIP和RIP必须在同一个网段内

请求和响应报文都需要经过Director Server,高负载场景中,Director Server易成为性能瓶颈

支持端口映射

RS可以使用任意操作系统,缺陷:对Director Server压力会比较大,请求和响应都需经过director server


LVS-DR模式原理


(a) 当用户请求到达Director Server,此时请求的数据报文会先到内核空间的PREROUTING链。此时报文的源IP为CIP,目标IP为VIP

(b) PREROUTING检查发现数据包的目标IP是本机,将数据包送至INPUT链

(c) IPVS比对数据包请求的服务是否为集群服务,若是,将请求报文中的源MAC地址修改为DIP的MAC地址,将目标MAC地址修改RIP的MAC地址,然后将数据包发至POSTROUTING链。 此时的源IP和目的IP均未修改,仅修改了源MAC地址为DIP的MAC地址,目标MAC地址为RIP的MAC地址

(d) 由于DS和RS在同一个网络中,所以是通过二层来传输。POSTROUTING链检查目标MAC地址为 RIP的MAC地址,那么此时数据包将会发至Real Server

(e) RS发现请求报文的MAC地址是自己的MAC地址,就接收此报文。处理完成之后,将响应报文通 过lo接口传送给eth0网卡然后向外发出。此时的源IP地址为VIP,目标IP为CIP

(f) 响应报文最终送达至客户端

LVS-DR模型的特性

特点1:保证前端路由将目标地址为VIP报文统统发给Director Server,而不是RS

RS可以使用私有地址;也可以是公网地址,如果使用公网地址,此时可以通过互联网对RIP进行直接访问

RS跟Director Server必须在同一个物理网络中

所有的请求报文经由Director Server,但响应报文必须不能进过Director Server

不支持地址转换,也不支持端口映射

RS可以是大多数常见的操作系统

RS的网关绝不允许指向DIP(因为我们不允许他经过director)

RS上的lo接口配置VIP的IP地址

缺陷:RS和DS必须在同一机房中


LVS三种负载均衡模式的比较
三种负载均衡:nat,tunneling,dr
|类目|NAT|TUN|DR|
操作系统|任意|支持隧道|多数(支持non-arp)
|服务器网络|私有网络|局域网/广域网|局域网
|服务器数目|10-20|100|大于100
|服务器网关|负载均衡器|自己的路由|自己的路由|
效率|一般|高|最高

LVS的负载调度算法
轮叫调度
加权轮叫调度
最小连接调度
加权最小连接调度
基于局部性能的最少连接
带复制的基于局部性能最小连接
目标地址散列调度
源地址散列调度

负载均衡的作用有哪些?
1、转发功能
按照一定的算法【权重、轮询】,将客户端请求转发到不同应用服务器上,减轻单个服务器压力,提高系统并发量。

2、故障移除
通过心跳检测的方式,判断应用服务器当前是否可以正常工作,如果服务器期宕掉,自动将请求发送到 其他应用服务器。

3、恢复添加
如检测到发生故障的应用服务器恢复工作,自动将其添加到处理用户请求队伍中。

Nginx实现负载均衡的分发策略

Nginx 的 upstream目前支持的分配算法:
1)、轮询——1:1轮流处理请求(默认)
每个请求按时间顺序逐一分配到不同的应用服务器,如果应用服务器down掉,自动剔除,剩下的继续轮询。

2)、权重——you can you up 通过配置权重,指定轮询几率,权重和访问比率成正比,用于应用服务器性能不均的情况。

3)、ip_哈希算法 每个请求按访问ip的hash结果分配,这样每个访客固定访问一个应用服务器,可以解决session共享的问题。

keepalived 是什么?
广义上讲是高可用,狭义上讲是主机的冗余和管理

Keepalived起初是为LVS设计的,专门用来监控集群系统中各个服务节点的状态,它根据tcp/IP参考模型的第三、第四层、第五层交换机制检测每个服务节点的状态,如果某个服务器节点出现异常,或者工作出现故障,Keepalived将检测到,并将出现的故障的服务器节点从集群系统中剔除,这些工作全部是自动完成的,不需要人工干涉,需要人工完成的只是修复出现故障的服务节点。

后来Keepalived又加入了VRRP的功能,VRRP(VritrualRouterRedundancyProtocol,虚拟路由冗余协议)出现的目的是解决静态路由出现的单点故障问题,通过VRRP可以实现网络不间断稳定运行,因此Keepalvied一方面具有服务器状态检测和故障隔离功能,另外一方面也有HACluster功能。

所以keepalived的核心功能就是健康检查和失败且换。所谓的健康检查,就是采用tcp三次握手,icmp请求,http请求,udp echo请求等方式对负载均衡器后面的实际的服务器(通常是承载真实业务的服务器)进行保活;

而失败切换主要是应用于配置了主备模式的负载均衡器,利用VRRP维持主备负载均衡器的心跳,当主负载均衡器出现问题时,由备负载均衡器承载对应的业务,从而在最大限度上减少流量损失,并提供服务的稳定性


如何理解VRRP协议?
主机之间的通信都是通过配置静态路由或者(默认网关)来完成的,而主机之间的路由器一旦发生故障,通信就会失效,因此这种通信模式当中,路由器就成了一个单点瓶颈,为了解决这个问题,就引入了VRRP协议。VRRP协议是一种容错的主备模式的协议,保证当主机的下一跳路由出现故障时,由另一台路由器来代替出现故障的路由器进行工作,通过VRRP可以在网络发生故障时透明的进行设备切换而不影响主机之间的数据通信。

VRRP的三种状态:
VRRP路由器在运行过程中有三种状态:
Initialize状态: 系统启动后就进入Initialize,此状态下路由器不对VRRP报文做任何处理;
Master状态;
Backup状态; 一般主路由器处于Master状态,备份路由器处于Backup状态。

keepalived的工作原理?
keepalived采用是模块化设计,不同模块实现不同的功能。主要有三个模块,分别是core、check和vrrp。
core:是keepalived的核心,负责主进程的启动和维护,全局配置文件的加载解析等
check:负责healthchecker(健康检查),包括了各种健康检查方式,以及对应的配置的解析包括LVS的 配置解析;可基于脚本检查对IPVS后端服务器健康状况进行检查
vrrp:VRRPD子进程,VRRPD子进程就是来实现VRRP协议的

Keepalived高可用对之间是通过VRRP进行通信的,VRRP是通过竞选机制来确定主备的,主的优先级高于备,因此,工作时主会优先获得所有的资源,备节点处于等待状态,当主宕机的时候,备节点就会接管主节点的资源,然后顶替主节点对外提供服务。

在Keepalived服务对之间,只有作为主的服务器会一直发送VRRP广播包,告诉备它还活着,此时备不会抢占主,当主不可用时,即备监听不到主发送的广播包时,就会启动相关服务接管资源,保证业务的连 续性,接管速度最快。

出现脑裂的原因

什么是脑裂?
在高可用(HA)系统中,当联系2个节点的“心跳线”断开时,本来为一整体、动作协调的HA系统,就分裂成为2个独立的个体。由于相互失去了联系,都以为是对方出了故障。两个节点上的HA软件像“裂脑人”一样,争抢“共享资源”、争起“应用服务”,就会发生严重后果。共享资源被瓜分、两边“服务”都起不来了;或者两边“服务”都起来了,但同时读写“共享存储”,导致数据损坏。

都有哪些原因导致脑裂?
高可用服务器对之间心跳线链路发生故障,导致无法正常通信
因心跳线坏了(包括断了,老化)
因网卡及相关驱动坏了,ip配置及冲突问题(网卡直连)
因心跳线间连接的设备故障(网卡及交换机)
因仲裁的机器出问题(采用仲裁的方案)
高可用服务器上开启了 iptables防火墙阻挡了心跳消息传输
高可用服务器上心跳网卡地址等信息配置不正确,导致发送心跳失败
其他服务配置不当等原因,如心跳方式不同,心跳广插冲突、软件Bug等


如何解决keepalived脑裂问题?
在实际生产环境中,我们从以下方面防止脑裂:
同时使用串行电缆和以太网电缆连接、同时使用两条心跳线路,这样一条线路断了,另外一条还是好的,依然能传送心跳消息
当检查脑裂时强行关闭一个心跳节点(这个功能需要特殊设备支持,如stonith、fence)相当于备节点接收不到心跳消息,通过单独的线路发送关机命令关闭主节点的电源
做好对脑裂的监控报警

解决常见方案:
如果开启防火墙,一定要让心跳消息通过,一般通过允许IP段的形式解决
可以拉一条以太网网线或者串口线作为主被节点心跳线路的冗余
开发检测程序通过监控软件检测脑裂


该文章最后由 阿炯 于 2021-10-27 14:24:34 更新,目前是第 4 版。