UML软件工程组织

LVS和Heartbeat的安装配置说明

1. LVS

1.1. LVS介绍

LVS是LINUX VIRTUL SERVER的简称,是由章文嵩博士主持的著名开放源码项目,一个实现“三高”系统的解决方案。LVS旨在解决高速发展的Web商务中日益凸现的问题:如何在有限资金投入的情况下,最大幅度的提高Web站点的潜在服务性能。核心就是通过一组服务器来进行负载均衡,通过前端的负载调度器(Load Balancer),无缝地将网络请求调度到真实服务器上,从而使得服务器集群的结构对客户是透明的,客户访问集群系统提供的网络服务就像访问一台高性能、高可用的服务器一样。客户程序不受服务器集群的影响不需作任何修改。

系统的伸缩性通过在服务机群中透明地加入和删除一个节点来达到,通过检测节点或服务进程故障和正确地重置系统达到高可用性。由于我们的负载调度技术是在Linux内核中实现的,我们称之为Linux虚拟服务器(Linux Virtual Server)。

LVS的设计根据透明性、性能、高可用性、可管理性和可编程性的指导思想实现的。

我们把前面那台负载均衡机器叫做:director server(DR)。后面的实际服务机器叫做:real server(RS)

1.2. LVS的三种负载均衡模式
调度器的实现技术中,IP负载均衡技术是效率最高的,IP虚拟服务器软件(IPVS)是在linux内核中实现的。

1.2.1. NAT模式

NAT用法本来是因为网络IP地址不足而把内部保留IP地址通过映射转换成公网地址的一种上网方式(原地址NAT)。如果把NAT的过程稍微变化,就可以成为负载均衡的一种方式。原理其实就是把从客户端发来的IP包的IP头目的地址在DR上换成其中一台REAL SERVER的IP地址并发至此REAL SERVER,而REAL SERVER则在处理完成后把数据经过DR主机发回给客户端,DR在这个时候再把数据包的原IP地址改为DR接口上的IP地址即可。期间,无论是进来的流量,还是出去的流量,都必须经过DR。

1.2.2. IP隧道模式

隧道模式则类似于VPN的方式,使用网络分层的原理,在从客户端发来的数据包的基础上,封装一个新的IP头标记(不完整的IP头,只有目的IP部)发给REAL SERVER,REAL SERVER收到后,先把DR发过来的数据包的头给解开,还原其数据包原样,处理后,直接返回给客户端,而不需要再经过DR。需要注意的是,由于REAL SERVER需要对DR发过来的数据包进行还原,也就是说必须支持IP TUNNEL协议。所以,在REAL SERVER的内核中,必须编译支持IP TUNNEL这个选项。IP TUNNEL也在Networking options里面,如下图所示。

1.2.3. 直接路由模式
直接路由模式比较特别,很难说和什么方面相似,前2种模式基本上都是工作在网络层上(三层),而直接路由模式则应该是工作在数据链路层上(二层)。其原理为,DR和REAL SERVER都使用同一个IP对外服务。但只有DR对ARP请求进行响应,所有REAL SERVER对本身这个IP的ARP请求保持静默。也就是说,网关会把对这个服务IP的请求全部定向给DR,而DR收到数据包后根据调度算法,找出对应的REAL SERVER,把目的MAC地址改为REAL SERVER的MAC并发给这台REAL SERVER。这时REAL SERVER收到这个数据包,则等于直接从客户端收到这个数据包无异,处理后直接返回给客户端。由于DR要对二层包头进行改换,所以DR和REAL SERVER之间必须在一个广播域,也可以简单的理解为在同一台交换机上。

1.3. LVS的安装和配置

LVS的安装在其官方网站上有详细的说明文档。网址是:http://www.austintek.com/LVS/LVS-HOWTO/HOWTO/ 。不过一般说来以下网址http://www.austintek.com/LVS/LVS-HOWTO/mini-HOWTO/LVS-mini-HOWTO.html就足够了。

1.3.1. 让DR内核支持 IPVS
2.6及以上内核中已经支持了IPVS功能。至于2.4的内核则看版本,2.4.23及以上的内核已经有了ipvs,所以不必且不能打包,如果打了就会编译出错。对于2.4.23以下内核则必须打IPVS补丁。2.4.23/24的内核有问题,所以不建议使用这两种内核。

IPVS只对DR需要,而RS则不需要。

Ipvs补丁和ipvsadm的下载地址:http://www.linuxvirtualserver.org/software/ipvs.html.

1.3.1.1. 打补丁来支持ipvs

对于2.4.23以下内核需要这个步骤,否则请按1.3.1.2步骤。

到http://www.linuxvirtualserver.org/software/ipvs.html下载对应的补丁。假设你使用的内核是2.4.18, 那么下载Version 1.0.10,包为ipvs-1.0.10.tar.gz。解包后阅读README文件,按中其中的方法打包。不过我对这里的说明有点不明白。下面我说说我的方法:

cd <ipvs的解压目录>

make patchkernel

make installsource

或者

cd /usr/src/linux

cp <ipvs的解压目录>/linux_kernel_ksyms_c.diff ./

cp <ipvs的解压目录>/linux_net_netsyms_c.diff ./

patch –p1 < linux_kernel_ksyms_c.diff

patch –p1 < linux_net_netsyms_c.diff

然后cd /usr/src/linux

make dep; make bzImage;

接着重新copy新的内核文件,然后lilo,然后reboot

1.3.1.2. 重新配置内核选项来支持IPVS

对于2.4.23及以上的内核已经有了ipvs,所以你可以直接在内核中配置来支持IPVS。

cd /usr/src/linux

make menuconfig

对于不同版本的内核来说,各个配置项的路径是不一致的。对于2.6.8.1菜单路径是:Device Drivers->Networking support -> Networking options->IP: Virtual Server Configuration。而在2.4.30的内核中Networking options就在第一层路径下面。请到目的菜单Networking options下面,如下图所示:

如果你需要IPVS支持IP隧道模式,那么请选择下面这两个选项:

然后再选择:IP: Virtual Server Configuration这个选项。这时出现下图:

请选中所有的选项。

要关注的是IPVS connection table size,这个东西意思是每个连接的hash table的大小,大家知道通常hash表越大,一次命中的机会越大。这里取值范围是2-20,2的2次方到2的20次方。有的资料建议用20,个人认为默认值就足够了。由于每个连接需要128BYTE,每个HASH位需要8BYTE,所以(128 + 8 ) * 2^20 = 128M + 8 M = 136M,对于我们的系统没问题。

最后的是IPVS application helper,这种是专门针对多次连接的情况的(可以理解为session),大家都知道一次FTP通讯需要2次连接,所以必须保证这两次都在一台服务器上,否则将连接失败。这是个明显针对协议,或者说针对应用层的分类。有点七层交换的味道,希望这个功能尽快把HTTP的SESSION给加上,到时就不用使用后台同步SESSION或者对原地址做HASH定向处理了。

这里负载调度算法的意思请具体参考:http://www.linuxvirtualserver.org/zh/lvs4.html

make dep; make bzImage;

接着重新copy新的内核文件,然后lilo,然后reboot。启动时可以看到ipvs提示信息。

1.3.2. RS的NOARP问题解决
直接路由模式肯定要处理NOARP的问题,官方文档《LVS-mini-HOWTO》3.7节指出在如下情况下必须处理:

IF( (you are using LVS-DR or LVS-Tun on the director)
AND
(you are running a Linux 2.2.x, 2.4.x, 2.6.x kernel on a realserver)
AND
(
the VIP on the realserver is on an ethernet device eg lo:0, tunl0:0
i.e. packets to the VIP are not being accepted by transparent proxy
)
AND
(
the realservers can answer arp requests from
the client/router (the realservers are on the same
piece of wire|network|segment as the director)
) )
THEN { YOU MUST HANDLE THE ARP PROBLEM }
FI

对于这断话的,我不太理解。下面引用其它的文档说明。

在使用LVS中的DR与IP Tunnel的时候,会需要有一块网络卡要设定两个IP的情形,但是Linux在2.2.14之后,就将eth0:1的-NOARP这个FLAG关闭。也就是说在kernel 2.2.14以后,eth0:1就视为eth0的别名,任何对eth0:1的设定也同样作用在eth0,换句话说,我对eth0:1下-NOARP,同样也会对eth0有作用,这样会使得整张网络卡收不到封包。

在直接路由、IP隧道模式下,因为我所有的机器都放在同一个网段,当该网段的Router接收到客户端(Client)对虚拟IP(Virtual IP)的TCP connection要求时,会先在网段中利用Arp request询问谁有VIP的地址,而包含Director与RealServers上所有的interface(不管Primary还是Subinterface),只要他有那个ip,都会发送arp reply回去,造成网段内所有拥有Virtual IP的interface都会reply给Router,最后结果就是看谁的速度快,Router就将该封包送给谁,如此会造成LVS的Server并无法发挥其效果,因此需要利用hidden这个pattch,将Subinterface上的Virtual IP给隐藏起来,如此他就不会对Arp Request进行Reply,如此就可以解决ARP的问题,而这个NOARP的问题,kernel发展小组认为不重要,所以以后都不会修改,要用请自行编译。

所以从http://www.ssi.bg/~ja/#hidden下载对应的补丁,对于2.6.8.1的内核我选择hidden-2.6.4-1.diff。

cp hidden-2.6.4-1.diff /usr/src/linux

cd /usr/src/linux

patch –p1 < hidden-2.6.4-1.diff

make dep;make bzImage;

copy新的内核文件到相应的启动目录。再lilo。最后reboot。

当然解决noarp的问题,不止这一种。譬如leofan在内核中通过以下四个命令解决,前提条件是有这些设备:

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

不过我在2.6.8.1的内核中试了一下好像不行。Lvs把包固定发给了rs1这台机器,估计rs1arp reply响应最快。

1.3.3. 安装ipvsadm
这是一个IPVS的管理工具,提供了一个和IPVS打交道的接口,包括配置IPVS和连接信息统计。到地址:http://www.linuxvirtualserver.org/software/ipvs.html去下载相应的版本。对于2.6.8.1内核,下了ipvsadm-1.24-5.src.rpm。

rpm ipvsadm的存放路径/ipvsadm-1.24-5.src.rpm

cd /usr/src/rpm/SOURCE/

tar –zxvf ipvsadm-1.24.tar.gz

cd ipvsadm-1.24

make ; make install

然后:

ipvsadm,如果出现以下提示说明已经安装成功。

IP Virtual Server version 1.2.0 (size=4096)

Prot LocalAddress:Port Scheduler Flags

-> RemoteAddress:Port Forward Weight ActiveConn InActConn

ipvsadm的具体用法可参考 man ipvsadm.

1.3.4. Ipvsadm的配置
根据http://www.austintek.com/LVS/LVS-HOWTO/mini-HOWTO/LVS-mini-HOWTO.html4节和5结节的说明,Ipvsadm的配置可以用官方的配置脚本配置,配置脚本可在http://www.austintek.com/LVS/下载,也可以手工敲入命令配置。

官方的脚本使用perl写的,配置脚本的命令为包中文件名为cofigure的文件, 包中的lvs_dr.conf.one_NIC_one_network等文件是一些配置信息,作为configure的参数传入.下面这个命令对应两台real server的配置, 需要自己修改lvs_dr.conf.one_NIC_two_network中的信息.

./configure lvs_dr.conf.one_NIC_two_network

不过本人试了一下自动配置没有成功,就手工配置了.读者有兴趣可自行研究如何使用官方配置脚本配置。

1.3.4.1. DR的配置
对于前台负载均衡服务器Direcrt Server(DR)的配置,我自己做一个配置脚本 config_vs.sh。里面的参数请自己替换。

#/bin/sh

#file: config_vs.sh 这里默认使用网卡eth0,如果想用其它网卡请自行替换即可。

VIP=172.30.31.200 #DR的虚拟服务IP

DIP=172.30.31.68 #DR的eth0真实地址

RS1=172.30.31.66 #real server1的真实地址

RS2=172.30.31.67 #real server2的真实地址

GW=172.30.31.1 #DR使用的网关或路由的地址

SERVICE=22 #你的服务端口

cat /proc/sys/net/ipv4/ip_forward #脚本调试信息

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

echo "1" >/proc/sys/net/ipv4/conf/all/send_redirects #脚本调试信息

cat /proc/sys/net/ipv4/conf/all/send_redirects #脚本调试信息

echo "1" >/proc/sys/net/ipv4/conf/default/send_redirects

cat /proc/sys/net/ipv4/conf/default/send_redirects#脚本调试信息

echo "1" >/proc/sys/net/ipv4/conf/eth0/send_redirects

cat /proc/sys/net/ipv4/conf/eth0/send_redirects #脚本调试信息

/sbin/ifconfig eth0 ${DIP} #配置所使用的网卡IP

#配置虚拟服务IP

/sbin/ifconfig eth0:0 ${VIP} broadcast ${VIP} netmask 255.255.255.255

/sbin/route add -host ${VIP} dev eth0:0 #添加虚拟IP的路由

/sbin/route add default gw ${GW} #添加本地路由

/sbin/ifconfig eth0:0 #脚本调试信息, 显示虚拟IP配置

#/bin/ping -b ${VIP} #脚本调试信息, 看看虚拟IP是否可以ping通

/sbin/route -n #脚本调试信息,显示路由信息

/sbin/ipvsadm –C #清除虚拟服务器表,也就是清除IPVS的原配置

#添加服务及轮调调度算法,-t:tcp服务,-A:添加服务; -s rr:指定调度算法为轮调

/sbin/ipvsadm -A -t ${VIP}:${SERVICE} -s rr

#添加real server, -a:添加一台RS, -t:tcp服务,-r: RS的地址,-g:直接路由模式。

#这里语句个数随real server的个数而定

/sbin/ipvsadm -a -t ${VIP}:${SERVICE} -r ${RS1} -g

/sbin/ipvsadm -a -t ${VIP}:${SERVICE} -r ${RS2} -g

ping -c 1 ${RS1} #脚本调试信息

ping -c 1 ${RS2} #脚本调试信息

/sbin/ipvsadm #脚本调试信息

#end of config_vs.sh

补:由于DR是个单点,为了保证高可用幸,我们使用了开源包Heartbeat来保证。所以有两台DR,一台为主,一台为辅。各自都可用这个脚本来配置,不过DIP要该成各自的真实地址,其它选项必须完全相同。

1.3.4.2. RS的配置
对于real server(RS)的配置,我自己做一个配置脚本 config_rs.sh。里面的参数请自己替换。

#/bin/sh

#file: config_rs.sh这里默认使用网卡eth0,如果想用其它网卡请自行替换即可。

VIP=172.30.31.200 #DR的虚拟服务IP

#DR的eth0真实地址,作用是在配置时测试DR的IP是否有效。但是DR切换后,DIP变了,所以这项取消了。

#DIP=172.30.31.68

LOCALIP=172.30.31.66 #real server1的真实地址

GW=172.30.31.1 #real server使用的网关或路由的地址

/sbin/ifconfig eth0 ${LOCALIP} #配置eth0的本地IP

/sbin/route add default gw ${GW} #添加默认路由

/bin/netstat -rn #脚本调试信息

ping -c 1 ${GW} #脚本调试信息,是否可以ping通网关

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

cat /proc/sys/net/ipv4/ip_forward #脚本调试信息,ip_forward是否配置正确

ping -c 1 ${DIP} #脚本调试信息, 是否可以ping通DR的真实地址

ping –c 1 ${VIP} #是否可以ping通虚拟DR的IP

#按照real server的虚拟IP

/sbin/ifconfig lo:0 ${VIP} broadcast ${VIP} netmask 0xffffffff up

#配置出口

/sbin/ifconfig lo:0

#在lo:0上添加去虚拟IP的路由

/sbin/route add -host ${VIP} dev lo:0

/bin/netstat -rn #脚本调试信息

echo "1" >/proc/sys/net/ipv4/conf/all/hidden

cat /proc/sys/net/ipv4/conf/all/hidden #脚本调试信息

echo "1" >/proc/sys/net/ipv4/conf/lo/hidden

cat /proc/sys/net/ipv4/conf/lo/hidden #脚本调试信息

#end of config_rs.sh

不同real server配置时只要改变LOCALIP选项就可以了。我只添加了172.30.31.66(real server 1)和172.30.31.67(real server 2)两台机器。DR的主节点名称为heatbeat1,副节点名称为heartbeat2

1.4. 试运行结果
安装上面的说明走完所有的步骤后,我用ssh测试了一下。奇数次去了172.30.31.66这台机器,偶数次去了172.30.31.67这台机器

2. heartbeat

2.1. heartbeat的介绍

这里的heartbeat就是linux-ha项目,被许多高可用系统采用。我们这里lvs必须是个高可用系统,所以我们采用heartbeat。本文也以lvs作为高可用服务来说明heartbeat的使用。Heartbeat的高版本可以负责3个及以上的节点。本文2个节点来说明,在你的两台机器(一台作为主节点,另一台为从节点)上运行heartbeat, 并配置好相关的选项,最重要的是lvs资源一定要配置进去。那么开始时主节点提供lvs服务,一旦主节点崩溃,那么从节点立即接管lvs服务。如果是自己开启了其它的服务资源,那么接管的时候,该服务资源相应的tcp连接必须重连,而且主从节点的应用层逻辑状态有应用层自己保证一致。Lvs不存在应用层的逻辑状态。

具体介绍请参考:http://www.linux-ha.org/

2.2. libnet的安装
安装heatbeat前必须先安装libnet包,请到http://www.packetfactory.net/projects/libnet/地址下载。libnet提供了一些高层的api,让应用程序开发者可以修改网络包。我下的包为libnet.tar.gz,版本为1.1.2.1

cd 存放路径

tar –zxvf libnet.tar.gz

cd libnet

./configure; make ; make install

2.3. heartbeat的安装
到http://linux-ha.org/download/index.html下载相应的版本,对于2.6.8.1我下载了最新的稳定版本heartbeat-2.0.2.tar.gz。

cd 存放路径

tar –zxvf heartbeat-2.0.2.tar.gz

cd heartbeat-2.0.2

./Configureme configure

make ; make install

上述步骤完成后,heartbeat的运行程序文件为/etc/rc.d/heartbeat。并且出现/etc/ha.d目录。

2.4. heartbeat的配置

heartbeat的配置信息非常复杂,但是最关键也就是那么几项。如果你要自己弄懂所有配置选项,那么自己参考:http://www.linux-ha.org/ConfiguringHeartbeat中的文档,特别是《Getting Started with Linux-HA(heartbeat)》文档。

这里需要配置文件有三个:ha.cf、haresources、authkeys。这三个配置文件需要在/etc/ha.d目录下面,但是默认是没有这三个文件的,所以你要

copy存放路径/ heartbeat-2.0.2/doc/ha.cf /etc/ha.d/

copy存放路径/ heartbeat-2.0.2/doc/ haresources /etc/ha.d/

copy存放路径/ heartbeat-2.0.2/doc/ authkeys /etc/ha.d/

2.4.1. authkeys
这个配置文件非常简单,就是在auth选择一个值。每个值对应一种算法,这个算法是在主节点和从节点间数据校验用的。这个配置文件权限必须是0600。

Chmod 0600 authkeys

自己选一种算法。我选md5。

配置文件的值如下:

auth 3

#1 crc

#2 sha1 HI!

3 md5 Hello!

2.4.2. haresources
这个文件配置的是节点要管理的资源也就你的高可用服务,这些资源在主节点down调时候,从节点就会开启这些资源。Heartbeat认为

你配置资源名称 start/stop

就可以开启/停止这些资源。所以让你的资源支持start/stop。其实这你只需要对你的应用服务作个脚本,脚本接受start参数就会启动应用服务,接受stop参数就会停止服务。个人建议,你什么都不要做,就把应用程序名当作资源名就可以了,启动资源名的时候就自动启动你的服务了。而在down机的时候,所有的程序都死了,根本就不需要heartbeat调用

你配置资源名称stop

命令来结束程序。

在文件中找到:

#node1 10.0.0.170 Filesystem::/dev/sda1::/data1::ext2

这一项,去掉#号,根据格式配置你的资源。第一字段(Node1):主节点名称(必须uname –n的保持一致);第二字段(10.0.0.170):对外虚拟服务IP;第三字段(Filesystem::/dev/sda1::/data1::ext2):Filesystem表示资源名称,/dev/sda1表示资源启动时的第一个参数,/data1表示第二个参数,/ext2表示第三个参数,依此类推。我们的lvs的配置如下所示:

heartbeat1 172.30.27.200 config_vs.sh

heartbeat1是主节点的名称。172.30.27.200是对外服务的虚拟IP,也是lvs对外服务的虚拟IP。Config_vs.sh是资源名称,因为这个就是DR的配置文件脚本,只要执行过这个脚本那么机器就变成DR了。

2.4.3. ha.cf
这个配置文件比较复杂。我只配了关键的几项:

debugfile /var/log/ha-debug

说明:调试日志文件文件,取默认值

logfile /var/log/ha-log

说明:系统运行日志文件,取默认值

logfacility local0

说明:日志等级,取默认值

keepalive 1

说明:心跳频率,自己设定。1:表示1秒;200ms:表示200毫秒

deadtime 10

说明:节点死亡时间阀值,就是从节点在过了10后还没有收到心跳就认为主节点死亡,自己设定

warntime 5

说明:发出警告时间,自己设定

udpport 28855

说明:心跳信息传递的udp端口,自己设定

#bcast eth0 # Linux

说明:采用udp广播播来通知心跳,建议在副节点不只一台时使用

ucast eth0 172.30.31.68

说明:采用网卡eth0的udp单播来通知心跳,eth0的IP

#mcast eth0 225.0.0.1 694 1 0

说明:采用udp多播播来通知心跳,建议在副节点不只一台时使用

auto_failback off

说明:主节点重启成功后,资源是自动拿回到主节点还是等到副节点down调后拿回资源

node heartbeat1

说明:主节点名称,与uname –n保持一致。排在第一的默认为主节点,所以不要搞措顺序

node heartbeat2

说明:副节点名称,与uname –n保持一致

watchdog /dev/watchdog

说明:看门狗。如果本节点在超过一分钟后还没有发出心跳,那么本节点自动重启

以上这些是我个人认为必配项,下面这些是可选项。

stonith baytech /etc/ha.d/conf/stonith.baytech

说明:主/副等所有节点的一种校验。

respawn userid /path/name/to/run

说明:和heartbeat必须一起启动的本地服务

ping 10.10.10.254

说明:伪节点IP,伪节点就是其失效时主/副节点不会正常工作但本身不是主/副节点之一。

respawn hacluster /usr/lib/heartbeat/ipfail

说明:与ping选项一起使用,取默认值。

baud 19200

说明:串口波特率,与serial一起使用。

serial /dev/ttyS0 # Linux

说明:采用串口来传递心跳信息。

2.5. 运行结果

在主节点heartbeat1(172.30.31.68)和副节点heartbeat2(172.30.31.69)启动heatbeat

/etc/rc.d/heartbeat start

这时,我用ssh登录172.30.31.200,第一次登录进17230.31.66,第二次则17230.31.67,第三次17230.31.66. 在主节点输入ipvsadm,显示

IP Virtual Server version 1.2.0 (size=4096)

Prot LocalAddress:Port Scheduler Flags

-> RemoteAddress:Port Forward Weight ActiveConn InActConn

TCP 172.30.31.200:ssh rr

-> 172.30.31.67:ssh Route 1 1 1

-> 172.30.31.66:ssh Route 1 2 0

这时,reboot 主节点172.30.31.68, 那么以前的连接失效, 副节点172.30.31.69::/var/log/ha-log中显示主节点死亡,然后本节点接管资源. 这时再用ssh登录172.30.31.200,依然可以.只是所有的登录已经通过副节点转发.

LVS和Heartbeat的安装配置说明

索引: LVS,Heartbeat,集群调度

摘要:本文描述开源工具LVS和Heartbeat的安装和配置

1. LVS

1.1. LVS介绍
LVS是LINUX VIRTUL SERVER的简称,是由章文嵩博士主持的著名开放源码项目,一个实现“三高”系统的解决方案。LVS旨在解决高速发展的Web商务中日益凸现的问题:如何在有限资金投入的情况下,最大幅度的提高Web站点的潜在服务性能。核心就是通过一组服务器来进行负载均衡,通过前端的负载调度器(Load Balancer),无缝地将网络请求调度到真实服务器上,从而使得服务器集群的结构对客户是透明的,客户访问集群系统提供的网络服务就像访问一台高性能、高可用的服务器一样。客户程序不受服务器集群的影响不需作任何修改。

系统的伸缩性通过在服务机群中透明地加入和删除一个节点来达到,通过检测节点或服务进程故障和正确地重置系统达到高可用性。由于我们的负载调度技术是在Linux内核中实现的,我们称之为Linux虚拟服务器(Linux Virtual Server)。以下为其大体的结构图

LVS的设计根据透明性、性能、高可用性、可管理性和可编程性的指导思想实现的。

我们把前面那台负载均衡机器叫做:director server(DR)。后面的实际服务机器叫做:real server(RS)

具体介绍请参考以下网址:http://www.linuxvirtualserver.org/zh

1.2. LVS的三种负载均衡模式
调度器的实现技术中,IP负载均衡技术是效率最高的,IP虚拟服务器软件(IPVS)是在linux内核中实现的。

1.2.1. NAT模式

NAT用法本来是因为网络IP地址不足而把内部保留IP地址通过映射转换成公网地址的一种上网方式(原地址NAT)。如果把NAT的过程稍微变化,就可以成为负载均衡的一种方式。原理其实就是把从客户端发来的IP包的IP头目的地址在DR上换成其中一台REAL SERVER的IP地址并发至此REAL SERVER,而REAL SERVER则在处理完成后把数据经过DR主机发回给客户端,DR在这个时候再把数据包的原IP地址改为DR接口上的IP地址即可。期间,无论是进来的流量,还是出去的流量,都必须经过DR。

1.2.2. IP隧道模式

隧道模式则类似于VPN的方式,使用网络分层的原理,在从客户端发来的数据包的基础上,封装一个新的IP头标记(不完整的IP头,只有目的IP部)发给REAL SERVER,REAL SERVER收到后,先把DR发过来的数据包的头给解开,还原其数据包原样,处理后,直接返回给客户端,而不需要再经过DR。需要注意的是,由于REAL SERVER需要对DR发过来的数据包进行还原,也就是说必须支持IP TUNNEL协议。所以,在REAL SERVER的内核中,必须编译支持IP TUNNEL这个选项。IP TUNNEL也在Networking options里面,如下图所示。

1.2.3. 直接路由模式
直接路由模式比较特别,很难说和什么方面相似,前2种模式基本上都是工作在网络层上(三层),而直接路由模式则应该是工作在数据链路层上(二层)。其原理为,DR和REAL SERVER都使用同一个IP对外服务。但只有DR对ARP请求进行响应,所有REAL SERVER对本身这个IP的ARP请求保持静默。也就是说,网关会把对这个服务IP的请求全部定向给DR,而DR收到数据包后根据调度算法,找出对应的REAL SERVER,把目的MAC地址改为REAL SERVER的MAC并发给这台REAL SERVER。这时REAL SERVER收到这个数据包,则等于直接从客户端收到这个数据包无异,处理后直接返回给客户端。由于DR要对二层包头进行改换,所以DR和REAL SERVER之间必须在一个广播域,也可以简单的理解为在同一台交换机上。

具体请参考以下网址:http://www.linuxvirtualserver.org/zh/lvs3.html

1.3. LVS的安装和配置

LVS的安装在其官方网站上有详细的说明文档。网址是:http://www.austintek.com/LVS/LVS-HOWTO/HOWTO/ 。不过一般说来以下网址http://www.austintek.com/LVS/LVS-HOWTO/mini-HOWTO/LVS-mini-HOWTO.html就足够了。

1.3.1. 让DR内核支持 IPVS
2.6及以上内核中已经支持了IPVS功能。至于2.4的内核则看版本,2.4.23及以上的内核已经有了ipvs,所以不必且不能打包,如果打了就会编译出错。对于2.4.23以下内核则必须打IPVS补丁。2.4.23/24的内核有问题,所以不建议使用这两种内核。

IPVS只对DR需要,而RS则不需要。

Ipvs补丁和ipvsadm的下载地址:http://www.linuxvirtualserver.org/software/ipvs.html.

1.3.1.1. 打补丁来支持ipvs

对于2.4.23以下内核需要这个步骤,否则请按1.3.1.2步骤。

到http://www.linuxvirtualserver.org/software/ipvs.html下载对应的补丁。假设你使用的内核是2.4.18, 那么下载Version 1.0.10,包为ipvs-1.0.10.tar.gz。解包后阅读README文件,按中其中的方法打包。不过我对这里的说明有点不明白。下面我说说我的方法:

cd <ipvs的解压目录>

make patchkernel

make installsource

或者

cd /usr/src/linux

cp <ipvs的解压目录>/linux_kernel_ksyms_c.diff ./

cp <ipvs的解压目录>/linux_net_netsyms_c.diff ./

patch –p1 < linux_kernel_ksyms_c.diff

patch –p1 < linux_net_netsyms_c.diff

然后cd /usr/src/linux

make dep; make bzImage;

接着重新copy新的内核文件,然后lilo,然后reboot

1.3.1.2. 重新配置内核选项来支持IPVS
对于2.4.23及以上的内核已经有了ipvs,所以你可以直接在内核中配置来支持IPVS。

cd /usr/src/linux

make menuconfig

对于不同版本的内核来说,各个配置项的路径是不一致的。对于2.6.8.1菜单路径是:Device Drivers->Networking support -> Networking options->IP: Virtual Server Configuration。而在2.4.30的内核中Networking options就在第一层路径下面。请到目的菜单Networking

请选中所有的选项。

要关注的是IPVS connection table size,这个东西意思是每个连接的hash table的大小,大家知道通常hash表越大,一次命中的机会越大。这里取值范围是2-20,2的2次方到2的20次方。有的资料建议用20,个人认为默认值就足够了。由于每个连接需要128BYTE,每个HASH位需要8BYTE,所以(128 + 8 ) * 2^20 = 128M + 8 M = 136M,对于我们的系统没问题。

最后的是IPVS application helper,这种是专门针对多次连接的情况的(可以理解为session),大家都知道一次FTP通讯需要2次连接,所以必须保证这两次都在一台服务器上,否则将连接失败。这是个明显针对协议,或者说针对应用层的分类。有点七层交换的味道,希望这个功能尽快把HTTP的SESSION给加上,到时就不用使用后台同步SESSION或者对原地址做HASH定向处理了。

这里负载调度算法的意思请具体参考:http://www.linuxvirtualserver.org/zh/lvs4.html

make dep; make bzImage;

接着重新copy新的内核文件,然后lilo,然后reboot。启动时可以看到ipvs提示信息。

1.3.2. RS的NOARP问题解决
直接路由模式肯定要处理NOARP的问题,官方文档《LVS-mini-HOWTO》3.7节指出在如下情况下必须处理:

IF( (you are using LVS-DR or LVS-Tun on the director)
AND
(you are running a Linux 2.2.x, 2.4.x, 2.6.x kernel on a realserver)
AND
(
the VIP on the realserver is on an ethernet device eg lo:0, tunl0:0
i.e. packets to the VIP are not being accepted by transparent proxy
)
AND
(
the realservers can answer arp requests from
the client/router (the realservers are on the same
piece of wire|network|segment as the director)
) )
THEN { YOU MUST HANDLE THE ARP PROBLEM }
FI
对于这断话的,我不太理解。下面引用其它的文档说明。

在使用LVS中的DR与IP Tunnel的时候,会需要有一块网络卡要设定两个IP的情形,但是Linux在2.2.14之后,就将eth0:1的-NOARP这个FLAG关闭。也就是说在kernel 2.2.14以后,eth0:1就视为eth0的别名,任何对eth0:1的设定也同样作用在eth0,换句话说,我对eth0:1下-NOARP,同样也会对eth0有作用,这样会使得整张网络卡收不到封包。

在直接路由、IP隧道模式下,因为我所有的机器都放在同一个网段,当该网段的Router接收到客户端(Client)对虚拟IP(Virtual IP)的TCP connection要求时,会先在网段中利用Arp request询问谁有VIP的地址,而包含Director与RealServers上所有的interface(不管Primary还是Subinterface),只要他有那个ip,都会发送arp reply回去,造成网段内所有拥有Virtual IP的interface都会reply给Router,最后结果就是看谁的速度快,Router就将该封包送给谁,如此会造成LVS的Server并无法发挥其效果,因此需要利用hidden这个pattch,将Subinterface上的Virtual IP给隐藏起来,如此他就不会对Arp Request进行Reply,如此就可以解决ARP的问题,而这个NOARP的问题,kernel发展小组认为不重要,所以以后都不会修改,要用请自行编译。

所以从http://www.ssi.bg/~ja/#hidden下载对应的补丁,对于2.6.8.1的内核我选择hidden-2.6.4-1.diff。

cp hidden-2.6.4-1.diff /usr/src/linux

cd /usr/src/linux

patch –p1 < hidden-2.6.4-1.diff

make dep;make bzImage;

copy新的内核文件到相应的启动目录。再lilo。最后reboot。

当然解决noarp的问题,不止这一种。譬如leofan在内核中通过以下四个命令解决,前提条件是有这些设备:

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

不过我在2.6.8.1的内核中试了一下好像不行。Lvs把包固定发给了rs1这台机器,估计rs1arp reply响应最快。

1.3.3. 安装ipvsadm
这是一个IPVS的管理工具,提供了一个和IPVS打交道的接口,包括配置IPVS和连接信息统计。到地址:http://www.linuxvirtualserver.org/software/ipvs.html去下载相应的版本。对于2.6.8.1内核,下了ipvsadm-1.24-5.src.rpm。

rpm ipvsadm的存放路径/ipvsadm-1.24-5.src.rpm

cd /usr/src/rpm/SOURCE/

tar –zxvf ipvsadm-1.24.tar.gz

cd ipvsadm-1.24

make ; make install

然后:

ipvsadm,如果出现以下提示说明已经安装成功。

IP Virtual Server version 1.2.0 (size=4096)

Prot LocalAddress:Port Scheduler Flags

-> RemoteAddress:Port Forward Weight ActiveConn InActConn

ipvsadm的具体用法可参考 man ipvsadm.

1.3.4. Ipvsadm的配置
根据http://www.austintek.com/LVS/LVS-HOWTO/mini-HOWTO/LVS-mini-HOWTO.html4节和5结节的说明,Ipvsadm的配置可以用官方的配置脚本配置,配置脚本可在http://www.austintek.com/LVS/下载,也可以手工敲入命令配置。

官方的脚本使用perl写的,配置脚本的命令为包中文件名为cofigure的文件, 包中的lvs_dr.conf.one_NIC_one_network等文件是一些配置信息,作为configure的参数传入.下面这个命令对应两台real server的配置, 需要自己修改lvs_dr.conf.one_NIC_two_network中的信息.

./configure lvs_dr.conf.one_NIC_two_network

不过本人试了一下自动配置没有成功,就手工配置了.读者有兴趣可自行研究如何使用官方配置脚本配置。

1.3.4.1. DR的配置
对于前台负载均衡服务器Direcrt Server(DR)的配置,我自己做一个配置脚本 config_vs.sh。里面的参数请自己替换。

#/bin/sh

#file: config_vs.sh 这里默认使用网卡eth0,如果想用其它网卡请自行替换即可。

VIP=172.30.31.200 #DR的虚拟服务IP

DIP=172.30.31.68 #DR的eth0真实地址

RS1=172.30.31.66 #real server1的真实地址

RS2=172.30.31.67 #real server2的真实地址

GW=172.30.31.1 #DR使用的网关或路由的地址

SERVICE=22 #你的服务端口

cat /proc/sys/net/ipv4/ip_forward #脚本调试信息

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

echo "1" >/proc/sys/net/ipv4/conf/all/send_redirects #脚本调试信息

cat /proc/sys/net/ipv4/conf/all/send_redirects #脚本调试信息

echo "1" >/proc/sys/net/ipv4/conf/default/send_redirects

cat /proc/sys/net/ipv4/conf/default/send_redirects#脚本调试信息

echo "1" >/proc/sys/net/ipv4/conf/eth0/send_redirects

cat /proc/sys/net/ipv4/conf/eth0/send_redirects #脚本调试信息

/sbin/ifconfig eth0 ${DIP} #配置所使用的网卡IP

#配置虚拟服务IP

/sbin/ifconfig eth0:0 ${VIP} broadcast ${VIP} netmask 255.255.255.255

/sbin/route add -host ${VIP} dev eth0:0 #添加虚拟IP的路由

/sbin/route add default gw ${GW} #添加本地路由

/sbin/ifconfig eth0:0 #脚本调试信息, 显示虚拟IP配置

#/bin/ping -b ${VIP} #脚本调试信息, 看看虚拟IP是否可以ping通

/sbin/route -n #脚本调试信息,显示路由信息

/sbin/ipvsadm –C #清除虚拟服务器表,也就是清除IPVS的原配置

#添加服务及轮调调度算法,-t:tcp服务,-A:添加服务; -s rr:指定调度算法为轮调

/sbin/ipvsadm -A -t ${VIP}:${SERVICE} -s rr

#添加real server, -a:添加一台RS, -t:tcp服务,-r: RS的地址,-g:直接路由模式。

#这里语句个数随real server的个数而定

/sbin/ipvsadm -a -t ${VIP}:${SERVICE} -r ${RS1} -g

/sbin/ipvsadm -a -t ${VIP}:${SERVICE} -r ${RS2} -g

ping -c 1 ${RS1} #脚本调试信息

ping -c 1 ${RS2} #脚本调试信息

/sbin/ipvsadm #脚本调试信息

#end of config_vs.sh

补:由于DR是个单点,为了保证高可用幸,我们使用了开源包Heartbeat来保证。所以有两台DR,一台为主,一台为辅。各自都可用这个脚本来配置,不过DIP要该成各自的真实地址,其它选项必须完全相同。

1.3.4.2. RS的配置

对于real server(RS)的配置,我自己做一个配置脚本 config_rs.sh。里面的参数请自己替换。

#/bin/sh

#file: config_rs.sh这里默认使用网卡eth0,如果想用其它网卡请自行替换即可。

VIP=172.30.31.200 #DR的虚拟服务IP

#DR的eth0真实地址,作用是在配置时测试DR的IP是否有效。但是DR切换后,DIP变了,所以这项取消了。

#DIP=172.30.31.68

LOCALIP=172.30.31.66 #real server1的真实地址

GW=172.30.31.1 #real server使用的网关或路由的地址

/sbin/ifconfig eth0 ${LOCALIP} #配置eth0的本地IP

/sbin/route add default gw ${GW} #添加默认路由

/bin/netstat -rn #脚本调试信息

ping -c 1 ${GW} #脚本调试信息,是否可以ping通网关

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

cat /proc/sys/net/ipv4/ip_forward #脚本调试信息,ip_forward是否配置正确

ping -c 1 ${DIP} #脚本调试信息, 是否可以ping通DR的真实地址

ping –c 1 ${VIP} #是否可以ping通虚拟DR的IP

#按照real server的虚拟IP

/sbin/ifconfig lo:0 ${VIP} broadcast ${VIP} netmask 0xffffffff up

#配置出口

/sbin/ifconfig lo:0

#在lo:0上添加去虚拟IP的路由

/sbin/route add -host ${VIP} dev lo:0

/bin/netstat -rn #脚本调试信息

echo "1" >/proc/sys/net/ipv4/conf/all/hidden

cat /proc/sys/net/ipv4/conf/all/hidden #脚本调试信息

echo "1" >/proc/sys/net/ipv4/conf/lo/hidden

cat /proc/sys/net/ipv4/conf/lo/hidden #脚本调试信息

#end of config_rs.sh

不同real server配置时只要改变LOCALIP选项就可以了。我只添加了172.30.31.66(real server 1)和172.30.31.67(real server 2)两台机器。DR的主节点名称为heatbeat1,副节点名称为heartbeat2

1.4. 试运行结果
安装上面的说明走完所有的步骤后,我用ssh测试了一下。奇数次去了172.30.31.66这台机器,偶数次去了172.30.31.67这台机器

2. heartbeat

2.1. heartbeat的介绍

这里的heartbeat就是linux-ha项目,被许多高可用系统采用。我们这里lvs必须是个高可用系统,所以我们采用heartbeat。本文也以lvs作为高可用服务来说明heartbeat的使用。Heartbeat的高版本可以负责3个及以上的节点。本文2个节点来说明,在你的两台机器(一台作为主节点,另一台为从节点)上运行heartbeat, 并配置好相关的选项,最重要的是lvs资源一定要配置进去。那么开始时主节点提供lvs服务,一旦主节点崩溃,那么从节点立即接管lvs服务。如果是自己开启了其它的服务资源,那么接管的时候,该服务资源相应的tcp连接必须重连,而且主从节点的应用层逻辑状态有应用层自己保证一致。Lvs不存在应用层的逻辑状态。

具体介绍请参考:http://www.linux-ha.org/

2.2. libnet的安装
安装heatbeat前必须先安装libnet包,请到http://www.packetfactory.net/projects/libnet/地址下载。libnet提供了一些高层的api,让应用程序开发者可以修改网络包。我下的包为libnet.tar.gz,版本为1.1.2.1

cd 存放路径

tar –zxvf libnet.tar.gz

cd libnet

./configure; make ; make install

2.3. heartbeat的安装
到http://linux-ha.org/download/index.html下载相应的版本,对于2.6.8.1我下载了最新的稳定版本heartbeat-2.0.2.tar.gz。

cd 存放路径

tar –zxvf heartbeat-2.0.2.tar.gz

cd heartbeat-2.0.2

./Configureme configure

make ; make install

上述步骤完成后,heartbeat的运行程序文件为/etc/rc.d/heartbeat。并且出现/etc/ha.d目录。

2.4. heartbeat的配置

heartbeat的配置信息非常复杂,但是最关键也就是那么几项。如果你要自己弄懂所有配置选项,那么自己参考:http://www.linux-ha.org/ConfiguringHeartbeat中的文档,特别是《Getting Started with Linux-HA(heartbeat)》文档。

这里需要配置文件有三个:ha.cf、haresources、authkeys。这三个配置文件需要在/etc/ha.d目录下面,但是默认是没有这三个文件的,所以你要

copy存放路径/ heartbeat-2.0.2/doc/ha.cf /etc/ha.d/

copy存放路径/ heartbeat-2.0.2/doc/ haresources /etc/ha.d/

copy存放路径/ heartbeat-2.0.2/doc/ authkeys /etc/ha.d/

2.4.1. authkeys
这个配置文件非常简单,就是在auth选择一个值。每个值对应一种算法,这个算法是在主节点和从节点间数据校验用的。这个配置文件权限必须是0600。

Chmod 0600 authkeys

自己选一种算法。我选md5。

配置文件的值如下:

auth 3

#1 crc

#2 sha1 HI!

3 md5 Hello!

2.4.2. haresources
这个文件配置的是节点要管理的资源也就你的高可用服务,这些资源在主节点down调时候,从节点就会开启这些资源。Heartbeat认为

你配置资源名称 start/stop

就可以开启/停止这些资源。所以让你的资源支持start/stop。其实这你只需要对你的应用服务作个脚本,脚本接受start参数就会启动应用服务,接受stop参数就会停止服务。个人建议,你什么都不要做,就把应用程序名当作资源名就可以了,启动资源名的时候就自动启动你的服务了。而在down机的时候,所有的程序都死了,根本就不需要heartbeat调用

你配置资源名称stop

命令来结束程序。

在文件中找到:

#node1 10.0.0.170 Filesystem::/dev/sda1::/data1::ext2

这一项,去掉#号,根据格式配置你的资源。第一字段(Node1):主节点名称(必须uname –n的保持一致);第二字段(10.0.0.170):对外虚拟服务IP;第三字段(Filesystem::/dev/sda1::/data1::ext2):Filesystem表示资源名称,/dev/sda1表示资源启动时的第一个参数,/data1表示第二个参数,/ext2表示第三个参数,依此类推。我们的lvs的配置如下所示:

heartbeat1 172.30.27.200 config_vs.sh

heartbeat1是主节点的名称。172.30.27.200是对外服务的虚拟IP,也是lvs对外服务的虚拟IP。Config_vs.sh是资源名称,因为这个就是DR的配置文件脚本,只要执行过这个脚本那么机器就变成DR了。

2.4.3. ha.cf
这个配置文件比较复杂。我只配了关键的几项:

debugfile /var/log/ha-debug

说明:调试日志文件文件,取默认值

logfile /var/log/ha-log

说明:系统运行日志文件,取默认值

logfacility local0

说明:日志等级,取默认值

keepalive 1

说明:心跳频率,自己设定。1:表示1秒;200ms:表示200毫秒

deadtime 10

说明:节点死亡时间阀值,就是从节点在过了10后还没有收到心跳就认为主节点死亡,自己设定

warntime 5

说明:发出警告时间,自己设定

udpport 28855

说明:心跳信息传递的udp端口,自己设定

#bcast eth0 # Linux

说明:采用udp广播播来通知心跳,建议在副节点不只一台时使用

ucast eth0 172.30.31.68

说明:采用网卡eth0的udp单播来通知心跳,eth0的IP

#mcast eth0 225.0.0.1 694 1 0

说明:采用udp多播播来通知心跳,建议在副节点不只一台时使用

auto_failback off

说明:主节点重启成功后,资源是自动拿回到主节点还是等到副节点down调后拿回资源

node heartbeat1

说明:主节点名称,与uname –n保持一致。排在第一的默认为主节点,所以不要搞措顺序

node heartbeat2

说明:副节点名称,与uname –n保持一致

watchdog /dev/watchdog

说明:看门狗。如果本节点在超过一分钟后还没有发出心跳,那么本节点自动重启

以上这些是我个人认为必配项,下面这些是可选项。

stonith baytech /etc/ha.d/conf/stonith.baytech

说明:主/副等所有节点的一种校验。

respawn userid /path/name/to/run

说明:和heartbeat必须一起启动的本地服务

ping 10.10.10.254

说明:伪节点IP,伪节点就是其失效时主/副节点不会正常工作但本身不是主/副节点之一。

respawn hacluster /usr/lib/heartbeat/ipfail

说明:与ping选项一起使用,取默认值。

baud 19200

说明:串口波特率,与serial一起使用。

serial /dev/ttyS0 # Linux

说明:采用串口来传递心跳信息。

2.5. 运行结果

在主节点heartbeat1(172.30.31.68)和副节点heartbeat2(172.30.31.69)启动heatbeat

/etc/rc.d/heartbeat start

这时,我用ssh登录172.30.31.200,第一次登录进17230.31.66,第二次则17230.31.67,第三次17230.31.66. 在主节点输入ipvsadm,显示

IP Virtual Server version 1.2.0 (size=4096)

Prot LocalAddress:Port Scheduler Flags

-> RemoteAddress:Port Forward Weight ActiveConn InActConn

TCP 172.30.31.200:ssh rr

-> 172.30.31.67:ssh Route 1 1 1

-> 172.30.31.66:ssh Route 1 2 0

这时,reboot 主节点172.30.31.68, 那么以前的连接失效, 副节点172.30.31.69::/var/log/ha-log中显示主节点死亡,然后本节点接管资源. 这时再用ssh登录172.30.31.200,依然可以.只是所有的登录已经通过副节点转发.

 

版权所有:UML软件工程组织