平民LVS_DR+Keepalived攻略(包含UDP服务)
系统环境:?
??? CentOS 5.5 内核[2.6.18-194.el5]
平台结构:
??? 2台负载均衡器 ——
??????? LVS1: 172.19.1.13
??????? LVS2: 172.19.1.14
??? 虚拟IP(VIP,漂移地址)——
??????? 172.19.1.19
??? 群集节点(RIP,真实服务器)——
??????? RealServer1: 172.19.1.15
??????? RealServer2:172.19.1.16
??? 提供服务:
??????? apache2(tcp 80)
??????? turnserver(udp 3478)
?
??? 每台host上iptables功能都打开
?
?? 公网IP地址: 61.147.xxx.xxx
?
?? 公网IP和虚拟IP地址会经过NAT转化。外部访问61.147.xxx.xxx会被NAT转换到172.19.1.19,同理172.19.1.19往外发数据包,源地址也会被设置为61.147.xxx.xxx。
?
?
1. 在LVS1和LVS2上安装ipvsadm,由于lvs已被继承在linux内核中,所以只需安装ipvsadm就可以了。不建议用源码make;make install 安装,会有莫名其妙的错误报出。直接:
?
yum install ipvsadm
?
2. 在LVS1和LVS2上安装keepalived. 步骤如下:
?
wget http://www.keepalived.org/software/keepalived-1.2.2.tar.gz
?
tar -xvf keepalived-1.2.2.tar.gz
?
cd keepalived-1.2.2/
?
./configure --prefix=/usr/local/keepalived --with-kernel-dir=/usr/src/kernels/2.6.18-194.el5-i686
?
注: 如果你/usr/src/kernels下没有2.6.18-194.el5-i686,你需要安装内核源码,安装很简单,运行
yum install kernel-devel
?
configure会产生以下效果:
?
Keepalived configuration
------------------------
Keepalived version?????? : 1.2.2
Compiler???????????????? : gcc
Compiler flags?????????? : -g -O2 -DETHERTYPE_IPV6=0x86dd
Extra Lib??????????????? : -lpopt -lssl -lcrypto
Use IPVS Framework?????? : Yes
IPVS sync daemon support : Yes
IPVS use libnl?????????? : No
Use VRRP Framework?????? : Yes
Use Debug flags????????? : No
?
注意:
?
Use IPVS Framework?????? : Yes
IPVS sync daemon support : Yes
这2项一定要是yes的,如果不是的话,去看configure时缺少了什么导致这2个失败,一般是缺乏相关的package所致。
然后你看它少什么,你就yum install 什么即可。举例:如果配置时提示OpenSSL的安装错误,则执行yum install openssl-devel openssl进行安装
?
configure后,下面就是:
?
make;
?
make install;
?
—— 注意:make步骤中若出现fd_set、blkcnt_t类型冲突之类的错误,可以修改./keepalived/libipvs-2.6/ip_vs.h文件,将#include linux/types.h行移到#include sys/types.h行之后,然后重新执行make进行编译即可。
[root@localhost keepalived-1.2.2]# vi keepalived/libipvs-2.6/ip_vs.h
……
#include sys/types.h
#include linux/types.h
……
?
查找keepalived的安装位置:
# find / -name keepalived
?
/usr/local/keepalived/etc/sysconfig/keepalived
/usr/local/keepalived/etc/rc.d/init.d/keepalived
/usr/local/keepalived/etc/keepalived
/usr/local/keepalived/sbin/keepalived
?
拷贝keepalived的配置文件到/etc目录下
?
# cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/rc.d/init.d/
# cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig
# mkdir /etc/keepalived
# cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived
# cp /usr/local/keepalived/sbin/keepalived /usr/sbin
?
将keepalived作为服务添加到chkconfig中,并设置开机启动
?
# chkconfig --add keepalived
# chkconfig --level 35 keepalived on
# chkconfig --list keepalived
?
keepalived????? 0:off?? 1:off?? 2:off?? 3:on??? 4:off?? 5:on??? 6:off
?
3. 配置Keepalived
?
在LVS1上:
?
vi /etc/keepalived/keepalived.conf
?
内容配置如下:
?
global_defs {
?? router_id LVS_STUN
}
vrrp_sync_group VGM {
?? group {
?????? VI_1
?? }
}
vrrp_instance VI_1 {
??? state MASTER??? #//负载均衡器的角色
??? interface eth0?? #//承载VIP地址的物理接口
??? lvs_sync_daemon_inteface eth0? #//虚拟路由器的ID号,每个热备组保持相同
??? virtual_router_id 51?
??? priority 200? #//竞选优先级,数字越大优先级越高
??? advert_int 5?? ? #//通告间隔秒数(心跳频率)
??? authentication {? #//本VRRP组的认证信息
??????? auth_type PASS
??????? auth_pass 1111
??? }
??? virtual_ipaddress {
??????? 172.19.1.19??? #//热备所针对的虚拟地址(VIP),可以有多个
??? }
}
virtual_server 172.19.1.19 80 { #//虚拟服务器的IP地址、端口
??? delay_loop 2 #//健康检查的间隔时间
??? lb_algo wrr?? #//负载调度算法(wrr为根据权重轮询,其他参见ipvsadm手册)
??? lb_kind DR???? #//负载均衡类型,常用的为DR、NAT方式
#??? persistence_timeout 1? #//连接保持时间,适用于动态Web站点、FTP站点等情况
??? protocol TCP? #//协议类型
??? real_server 172.19.1.15 80 { #//真实服务器的IP地址、端口
??????? weight 1?? #//节点权重
??????? TCP_CHECK {
??????????? connect_timeout 10? #//连接超时
??????????? nb_get_retry 3????????? #//重试次数
??????????? delay_before_retry 3? #//重试间隔
??????? }
??? }
??? real_server 172.19.1.16 80 {
??????? weight 1
??????? TCP_CHECK {
??????????? connect_timeout 10
??????????? nb_get_retry 3
??????????? delay_before_retry 3
??????? }
??? }
}
virtual_server 172.19.1.19 3478 {
??? delay_loop 2
??? lb_algo wrr
??? lb_kind DR
??? persistence_timeout 10
??? protocol UDP
??? real_server 172.19.1.15 3478 {
??????? weight 1
??????? TCP_CHECK {
??????????? connect_timeout 10
??????????? nb_get_retry 3
??????????? delay_before_retry 3
??????? }
??? }
??? real_server 172.19.1.16 3478 {
??????? weight 1
??? TCP_CHECK {
??????????? connect_timeout 10
??????????? nb_get_retry 3
??????????? delay_before_retry 3
??????? }
??? }
}
?
同理LVS2上的也需要配置这个文件:
?
global_defs {
?? router_id LVS_STUN
}
vrrp_sync_group VGM {
?? group {
?????? VI_1
?? }
}
vrrp_instance VI_1 {
??? state BACKUP
??? interface eth0
??? lvs_sync_daemon_inteface eth0
??? virtual_router_id 51
??? priority 150
??? advert_int 5
??? authentication {
??????? auth_type PASS
??????? auth_pass 1111
??? }
??? virtual_ipaddress {
??????? 172.19.1.19
??? }
}
virtual_server 172.19.1.19 80 {
??? delay_loop 2
??? lb_algo wrr
??? lb_kind DR
#??? persistence_timeout 1
??? protocol TCP
??? real_server 172.19.1.15 80 {
??????? weight 1
??????? TCP_CHECK {
??????????? connect_timeout 10
??????????? nb_get_retry 3
??????????? delay_before_retry 3
??????? }
??? }
??? real_server 172.19.1.16 80 {
??????? weight 1
??????? TCP_CHECK {
??????????? connect_timeout 10
??????????? nb_get_retry 3
??????????? delay_before_retry 3
??????? }
??? }
}
virtual_server 172.19.1.19 3478 {
??? delay_loop 2
??? lb_algo wrr
??? lb_kind DR
#??? persistence_timeout 1
??? protocol UDP
??? real_server 172.19.1.15 3478 {
??????? weight 1
??????? TCP_CHECK {
??????????? connect_timeout 10
??????????? nb_get_retry 3
??????????? delay_before_retry 3
??????? }
??? }
??? real_server 172.19.1.16 3478 {
??????? weight 1
??????? TCP_CHECK {
??????????? connect_timeout 10
??????????? nb_get_retry 3
??????????? delay_before_retry 3
??????? }
??? }
}
?
这2个文件的差别只有2个地方,一个是vrrp_instance.state, 一个是vrrp_instance.priority.
?
4 Real server配置
?
4.1. 设置VIP接口、调整ARP响应参数等
?
[root]# vi /etc/init.d/lvsreal
#!/bin/bash
# chkconfig: 35 99 10
# description: tune lo:0 interface and arp response for lvs-real servers.
VIP="172.19.1.19"
VIP_MASK="255.255.255.255"
VIF="lo:0"
case "$1" in
start)
? echo "Start lvsreal server for $VIP"
? /sbin/ifconfig $VIF $VIP netmask $VIP_MASK up
? /sbin/route add -host $VIP dev $VIF
? /sbin/sysctl -w net.ipv4.conf.lo.arp_ignore=1 &> /dev/null
? /sbin/sysctl -w net.ipv4.conf.lo.arp_announce=2 &> /dev/null
? /sbin/sysctl -w net.ipv4.conf.all.arp_ignore=1 &> /dev/null
? /sbin/sysctl -w net.ipv4.conf.all.arp_announce=2 &> /dev/null
? ;;
stop)
? echo "Stop lvsreal server for $VIP"
? /sbin/ifconfig $VIF down
? /sbin/route del -host $VIP
? /sbin/sysctl -w net.ipv4.conf.lo.arp_ignore=0 &> /dev/null
? /sbin/sysctl -w net.ipv4.conf.lo.arp_announce=0 &> /dev/null
? /sbin/sysctl -w net.ipv4.conf.all.arp_ignore=0 &> /dev/null
? /sbin/sysctl -w net.ipv4.conf.all.arp_announce=0 &> /dev/null
? ;;
*)
? echo "Usage: $0 {start|stop}"
? exit 1
esac
?
[root]# chmod +x /etc/init.d/lvsreal
[root]# chkconfig --add lvsreal
[root]# /etc/init.d/lvsreal start
?
4.2 安装apache2和turnserver
?
[root]# yum install apache2
?
从http://turnserver.sourceforge.net/index.php?n=Main.Download下载turnserver源码包
?
?$ autoreconf -i
?$ ./configure
?$ make
?# make install
?
当然提示少什么package,你就yum install 相应的package即可。
?
4.3 apache2设置
?
修改RealServer1和RealServer2上的/var/www/index.html
?
比如RealServer1上的改成
?
<html><body><h1>my ip is 172.19.1.15!!</h1>
</body></html>
?
RealServer2上的改成
<html><body><h1>my ip is 172.19.1.16!!</h1>
</body></html>
?
4.4 turnserver配置
请参考:http://turnserver.sourceforge.net/index.php?n=Doc.Install,配置就是2个文件:
?
/etc/ turnserver.conf
/etc/turnusers.txt
?
5 iptables配置
我们考虑下4台host与外间和彼此交互需要的端口
?
TCP 80 http端口
UDP 3478 turnserver UDP 端口
TCP 3478 turnserver TCP 端口
?
还有一个重要的别忘了:
112 keepalived的master与backup之间需要保证心跳(vrrp)所需端口。
?
显然的,对于LVS server上,我们需要配置如下:
-A INPUT -p udp -m udp --dport 3478 -j ACCEPT
-A OUTPUT -p udp -m udp --sport 3478 -j ACCEPT
?
-A INPUT -p tcp -m tcp --dport 3478 -j ACCEPT
-A OUTPUT -p tcp -m tcp --sport 3478 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A OUTPUT -p tcp -m tcp --sport 80 -j ACCEPT
-I INPUT -i eth0 -d 224.0.0.0/8 -j ACCEPT
-A INPUT -i eth0 -p vrrp -j ACCEPT
-A OUTPUT -o eth0 -p vrrp -j ACCEPT
?
第一种颜色是为了接受和转发stun binding request的
第二种颜色是为了让keepalived通过tcp 3478端口检查turnserver是否正常使用。检查udp服务比价复杂,所以你开启一个udp服务的进程时,同时打开一个tcp端口让keepalived来检查你的服务是否正常也是可行的。
第三种颜色当然是为了转发http请求的
第四种颜色是为了keepalived的MASTER和BACKUP心跳通讯用的。 vrrp即112端口。
?
对于real server上,显然下面的是必须的:
-A INPUT -p udp -m udp --dport 3478 -j ACCEPT
-A OUTPUT -p udp -m udp --sport 3478 -j ACCEPT
?
-A INPUT -p tcp -m tcp --dport 3478 -j ACCEPT
-A OUTPUT -p tcp -m tcp --sport 3478 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A OUTPUT -p tcp -m tcp --sport 80 -j ACCEPT
?
颜色对应的条目解释同上。
?
6 现在我们可以检验我们的劳动成果了。
?
在real server上:
?
启动apache server: service apache2 start
启动turnserver:? turnserver &
启动lvsreal服务: service lvsreal start
?
执行ip add:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
??? link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
??? inet 127.0.0.1/8 scope host lo
??? inet 172.19.1.19/32 brd 172.19.1.19 scope global lo:0
??? inet6 ::1/128 scope host
?????? valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
??? link/ether d0:0d:31:a6:07:17 brd ff:ff:ff:ff:ff:ff
??? inet 172.19.1.15/27 brd 172.19.1.31 scope global eth0
??? inet6 fe80::d20d:31ff:fea6:717/64 scope link
?
可现在虚拟ip: 172.19.1.19被设置在lo:0上。
?
在LVS1和LVS2都运行:
?
keepalived -D
?
同时你可以开一个终端查看keepalived的日志
?
tail -f /var/log/messages
?
注意:
?? 把service avahi-daemon和avahi-dnsconfd关掉。不然一直刷log,很烦。
?
通过看日志,你可以发现一台lvs的keepalived会处于MASTER状态,一台处于BACKUP状态。而且通过
?
ip add
你可以发现MASTER上绑定了虚拟ip:172.19.1.19
?
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue
??? link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
??? inet 127.0.0.1/8 scope host lo
??? inet6 ::1/128 scope host
?????? valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
??? link/ether d0:0d:34:8d:06:80 brd ff:ff:ff:ff:ff:ff
??? inet 172.19.1.13/27 brd 172.19.1.31 scope global eth0
??? inet 172.19.1.19/32 scope global eth0
??? inet6 fe80::d20d:34ff:fe8d:680/64 scope link
?????? valid_lft forever preferred_lft forever
3: sit0: <NOARP> mtu 1480 qdisc noop
??? link/sit 0.0.0.0 brd 0.0.0.0
?
而backup上并没有绑定虚拟ip。
?
?
在这4台host之外选择一台host,比如172.19.1.12 执行:
?
curl http://172.19.1.19 多次,可以发现
?
<html><body><h1>my ip is 172.19.1.15!!</h1>
</body></html>
?
和
<html><body><h1>my ip is 172.19.1.16!!</h1>
</body></html>
?
轮流出现,而且任意停止keepalived服务一台和apache2服务一台,都不会影响使用。
?
当然你也可以在浏览器中输入http://61.147.xxx.xxx,通过公网ip来访问。
?
好了, TCP的服务是好了。那么UDP的服务呢?
非常令人失望,客户端通过公网ip--61.147.xxx.xxx连接turnserver,并不能得到正确回应。
这是为什么呢?我们来分析一下过程:
?
经过wireshark和tcpdump,分析得出通讯的过程如下:
?
cleint--->Client NAT---61.147.xxx.xxx---->Server NAT---->VIP(172.19.1.19)----->RealServer----->Server NAT------>Client NAT--->Client
?
在NAT 地址映射中:
?
172.19.1.19<------>61.147.xxx.xxx
?
但是RealServer(172.19.1.15或者172.19.1.16)却是对应了别的公网ip。
?
所以客户端的NAT接受到一个非61.147.xxx.xxx发过来的UDP包时,会把它丢弃掉,这样client就收不到任何东西了。
?
解决方案:
用iptables的NAT和DNAT
?
在RealServer1(172.19.1.15)上用iptables添加
?
iptables -t nat -A PREROUTING -d 172.19.1.19/32 -p udp -m udp --dport 3478 -j DNAT --to-destination 172.19.1.15
iptables -t nat -A POSTROUTING -p udp -m udp --sport 3478 -j SNAT --to-source 172.19.1.19
?
意思就是:
1 收到目的端口为3478的udp,且目的地址为172.19.1.19的包,把目的地址改为172.19.1.15,以便应用程序turnserver处理,因为turnserver绑定的地址172.19.1.15。
2 往外发出源端口为3478的udp包,源地址都被改成172.19.1.19,这样server nat就会把地址映射为61.147.xxx.xxx,这样client NAT就会就收这个udp包了。
?
在RealServer2(172.19.1.16)上用iptables添加
?
iptables -t nat -A PREROUTING -d 172.19.1.19/32 -p udp -m udp --dport 3478 -j DNAT --to-destination 172.19.1.16
iptables -t nat -A POSTROUTING -p udp -m udp --sport 3478 -j SNAT --to-source 172.19.1.19
?
?
然后测试,发现udp服务可以正常使用啦。
?
当然有些UDP应用可以直接绑定在虚拟IP地址上,这种方法在www.linuxvirtualserver.org上有说过,不知有人部署成功过没有,如有人成功过,请不吝指教。
?
qq: 15520929
msn: hery1977@hotmail.com
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?