概述:
lvs负载均衡是一个虚拟服务器集群项目,无论是哪一种lvs结构都需要一个前端的调度器,让原本应该直接访问真实服务器的网络请求经过该调度器,让该调度器去决定该请求应该由谁处理。根据调度器将网络请求分配到真正服务器的不同方式,基本分成了三种模式--nat,tun,dr,还有一种需要对内核添加功能的模式是fullnat,但这次我们先不介绍这个模式。
1.三种模式的介绍
nat模式,这种模式十分好理解,也很好配置,顾名思义nat(Network Address Translation)地址转换的意思,调度器收到客户端请求后将这个请求的ip头部中的目的地址转换成为调度器内网的某台真实主机(选择哪台主机与调度算法有关)。
优点:只要调度器拥有真实ip即可,真正的服务器可以设置为内网的任意ip。
缺点:扩展性不好,因为所有的真实服务都必须和调度器在一个局域网内,而且必须以调度器作为网关,所以所有的网络请求都要经过调度器进来,也要经过调度器出去,当真实服务扩展时,调度器的瓶颈将会越来越明显。
tun模式,该模式是在ip包外再添加一个ip包头也就是ip隧道技术,真实服务也可以接受这样的数据包,解析后去和真实的客户端通信。
优点:现在调度器只是一个添加ip包头的作用,调度器的性能不再成为系统的瓶颈。而且由于使用的是隧道技术,真实服务器可以在公网上布置。
缺点:网络上对数据包的大小是有规定的,包过大将会被拆分,而且每台真实服务都要有公网上的合法ip。
dr模式,与前两种不同的是,这个模式修改的是以太网包的头部的目的mac地址,将数据包转发到不同mac地址的主机,之后真实服务器将和客户端进行通信。
优点:和tun一样,不会让调度器成为系统的瓶颈,而且不需要ip隧道技术。
缺点:调度器和真实服务都需要配置上虚拟ip,而且为了防止局域网内的mac地址混淆,需要关闭掉真实服务器对局域网内对寻找虚拟ip主机的mac地址广播的回应。
2.配置DR模式
首先安装lvs的支持软件
[root@dp1 ~]# yum install ipvsadm设置虚拟ip和提供的服务,
[root@dp1 ~]# ipvsadm -A -t 172.25.9.100:80 -s rr-A添加一个虚拟服务,-t添加tcp服务,-s lvs的算法
[root@dp1 ~]# ipvsadm -a -t 172.25.9.100:80 -r 172.25.9.42 -g添加真实服务的节点,-a 添加一个真实服务的虚拟ip,-r定义real service的地址,-g使用直接路由方式(DR)。
[root@dp1 ~]# ipvsadm -a -t 172.25.9.100:80 -r 172.25.9.43 -g
[root@dp1 ~]# ipvsadm -L查看lvs的状态此时给dp1添加虚拟ip。
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.25.9.100:http rr
-> rs1.mo.com:http Route 1 0 0
-> rs2.mo.com:http Route 1 0 0
[root@rs1 ~]# ip addr add 172.25.9.100/24 dev eth0
在真实服务器上架设http服务
[root@rs1 html]# /etc/init.d/httpd start
Starting httpd: [ OK ]
[root@rs1 html]# lsindex.html
[root@rs2 html]# lsindex.htmlrs1和rs2上是不同的内容,为了一会的实验结果明显
dp1,rs1,rs2在同一网段内,但是他们都具有172.25.9.100的ip,我们希望外界认为172.25.9.100是dp1,所以需要屏蔽掉rs1,rs2对172.25.9.100这个ip查询mac时的回应。我们采用arptables,一个基于二层的防火墙,使用方法类似iptables。
[root@rs1 html]# yum install arptables_jf.x86_64
[root@rs1 html]# arptables -A IN -d 172.25.9.100 -j DROP
[root@rs1 html]# arptables -A OUT -s 172.25.9.100 -j mangle --mangle-ip-s 172.25.9.42
[root@rs1 html]# /etc/init.d/arptables_jf save第一条策略是当有找172.25.9.100的arp包时候,这台机器不做回应,第二条是当发出查找其他ip对应的mac的时候的源头地址应该是172.25.9.42也就是本机的独有ip。
rs2同理。
rs1,rs2都开启arptables的服务。
现在测试lvs是否成功
[root@foundation9 0220]# curl 172.25.9.100发现没有成功,这时如果我们理解原理,就能知道,既然一直访问的是rs1,说明172.25.9.100的ip地址一定绑定在了
rs1
[root@foundation9 0220]# curl 172.25.9.100
rs1
rs1上,查看一下
[root@foundation9 0220]# arp -an 172.25.9.100
? (172.25.9.100) at 52:54:00:ce:44:70 [ether] on br0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 52:54:00:ce:44:70 brd ff:ff:ff:ff:ff:ff inet 172.25.9.42/24 brd 172.25.9.255 scope global eth0 inet 172.25.9.100/24 scope global secondary eth0发现确实如此,所以清除客户机的arp缓存。
[root@foundation9 0220]# arp -d 172.25.9.100
[root@foundation9 0220]# curl 172.25.9.100rs2[root@foundation9 0220]# curl 172.25.9.100rs1现在重新测试,已经成功符合了负载均衡的结果。
3.添加lvs的健康检查
现在我们做一个测试,将rs1的http服务关闭。
[root@foundation9 0220]# curl 172.25.9.100发现lvs并没有发现rs1坏掉了,仍然会切换到坏掉的rs1上,在真实环境中,这明显不是我们想要的结果,应该是当检测到rs1坏掉后,就不会再跳到rs1上。使用现有的东西我们无法完成,所以需要添加一个监控服务健康的服务。就是
rs2
[root@foundation9 0220]# curl 172.25.9.100
curl: (7) Failed connect to 172.25.9.100:80; Connection refused
ldirectord,用于监控在lvs集群的真实服务。ldirectord是和heartbeat相结合的一个服务,可以作为heartbeat的一个启动服务。所以之前要安装好heartbeat,而且配置好,再将ldrectord的配置文件复制到/etc/ha.d下,因为默认没有放到里面。
[root@dp2 ha.d]# rpm -ql ldirectordldirectord.cf就是配置文件。
/etc/ha.d/resource.d
/etc/ha.d/resource.d/ldirectord
/etc/init.d/ldirectord
/etc/logrotate.d/ldirectord
/sbin/rcldirectord
/usr/sbin/ldirectord
/usr/share/doc/packages/ldirectord
/usr/share/doc/packages/ldirectord/ldirectord.cf
/usr/share/man/man8/ldirectord.8.gz
编辑配置文件。
checktimeout=3
checkinterval=1
autoreload=yes
quiescent=no
virtual=172.25.9.100:80配置如上,通过virtual来定义vip,接下来是定义real service的节点,fallback是当所有real挂掉后,本机冲上去,一般这个页面显示服务器正在维护等界面。service表示;调度的服务,scheduler是调度算法,protocol是定义协议,checktype是检查类型为协商,checkport就是检查的端口,也就是健康检查。request代表你的/var/www/html一定要有index的html。接下来启动服务lvs就会自己开启,而且ip也会自己布置。
real=172.25.9.42:80 gate
real=172.25.9.43:80 gate
fallback=127.0.0.1:80 gate
service=http
scheduler=rr
#persistent=600
#netmask=255.255.255.255
protocol=tcp
checktype=negotiate
checkport=80
request="index.html"
# receive="Test Page"
# virtualhost=www.x.y.z
但是启动ldirectord模块的时候出现了问题
[root@dp1 ha.d]# /etc/init.d/ldirectord start这就是perl模块的问题,我们安装一下perl模块就好了。
Starting ldirectord... Can't locate IO/Socket/INET6.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at /usr/sbin/ldirectord line 3061.
BEGIN failed--compilation aborted at /usr/sbin/ldirectord line 3061.
failure
[root@dp1 ha.d]# yum install -y perl-IO-Socket-INET6安装成功后就启动成功了。
[root@dp1 html]# ipvsadm -L
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.25.9.100:http rr
-> rs1.mo.com:http Route 1 0 2
-> rs2.mo.com:http Route 1 0 1
[root@foundation9 0220]# curl 172.25.9.100rs2[root@foundation9 0220]# curl 172.25.9.100rs1负载均衡成功。
现在关掉rs1的http服务
[root@foundation9 0220]# curl 172.25.9.100
rs2
[root@foundation9 0220]# curl 172.25.9.100
rs2
发现不会出现切到坏掉的服务器上了。
问题发现:
ldirectord是对perl的一个包有依赖的,所以当你启动的时候遇到问题不要惊慌。
如下:
Starting ldirectord... Can't locate IO/Socket/INET6.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at /usr/sbin/ldirectord line 3061.这就是缺少那个perl包了
BEGIN failed--compilation aborted at /usr/sbin/ldirectord line 3061.
failure
perl-IO-Socket-INET6.noarch : Perl Object interface for AF_INET|AF_INET6 domain sockets安装之后就可以解决了
4.将ldirectord加入heartbeat集群。
首先配置好heartbeat,对heartbeat还不太了解的小伙伴可以看一下上一篇博客,如下是ha.cf
logfacilitylocal0authkeys文件
keepalive 2
deadtime 30
warntime 10
initdead 60
udpport10005
bcasteth0# Linux
auto_failback on
nodeha1.mo.com
nodeha2.mo.com
ping 192.168.5.1
respawn hacluster /usr/lib64/heartbeat/ipfail
apiauth ipfail gid=haclient uid=hacluster
auth 1haresource文件
1 crc
ha1.mo.com IPaddr::192.168.5.100/24/eth0 ldirectord
现在启动heartbeat服务,但是我发现我heartbeat启动后没有任何的输出信息,甚至连日志一行都不输出,仔细搜索后发现这竟然是官网的一个小bug。
273 vim /usr/lib/ocf/resource.d/heartbeat/.ocf-directories
${HA_BIN:=/usr/libxec/heartbeat}将上面这行的libxec修改成lib64你就会发现一切都正常了。
现在我们的基础结构就成了有ha1,ha2作为lvs双机备份的调度节点,rs1,rs2作为真实服务。
5.keepalive+lvs
首先安装keepalived的源码包
[root@ha1 keepalived-1.2.24]# ls
aclocal.m4 bin_install configure COPYING genhash keepalived Makefile.am README
ar-lib ChangeLog configure.ac depcomp INSTALL keepalived.spec.in Makefile.in TODO
AUTHOR compile CONTRIBUTORS doc install-sh lib missing
源码包的内容如上所示,没有喜闻乐见的spec结尾,也就是可以生成rpm包。
[root@ha1 keepalived-1.2.24]# ./configure日常执行configure,发现没有c compiler。
configure: error: in `/root/keepalived-1.2.24':
configure: error: no acceptable C compiler found in $PATH
See `config.log' for more details
configure: error:openssl没有继续下载,切记是openssl-devel。因为这是属于编译阶段,缺少的都是devel。
!!! OpenSSL is not properly installed on your system. !!!
!!! Can not include OpenSSL headers files. !!
编译成功进入make阶段,但是这里给大家一个建议,由于这个源代码包无法生成rpm,为了之后迁移到另一个节点考虑的话,我们应该将keepalive安装到一个独立的目录中方便迁移。
[root@ha1 keepalived-1.2.24]# ./configure --prefix=/usr/local/keepalived将keepalived的根目录放置到/usr/local下。之后在进行make和make install
[root@ha1 keepalived]# pwd现在已经将keepalived的根目录仿真到了/usr/local下。
/usr/local/keepalived
[root@ha1 keepalived]# ls
bin etc lib sbin share
现在将keepalived的配置文件,启动脚本等放置到操作系统的相应目录下,使用软链接即可。
[root@ha1 ~]# ln -s /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/
[root@ha1 ~]# /etc/init.d/keepalived start
/etc/init.d/keepalived: line 15: /etc/sysconfig/keepalived: No such file or directory
只将keepalived启动脚本连接好就是如上结果,将sysconfig文件也放置好
[root@ha1 ~]# ln -s /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/将sysconfig下文件放置好后仍然报错,发现找不到命令,也就是缺少/sbin下的二进制命令,我们继续连接,将启动的二进制文件连接到/sbin下。
[root@ha1 ~]# /etc/init.d/keepalived start
Starting keepalived: /bin/bash: keepalived: command not found
[FAILED]
[root@ha1 ~]# ln -s /usr/local/keepalived/sbin/keepalived /sbin/测试启动,发现已经打开了。但是现在先关闭keepalived服务,因为配置文件还没有写好,到这里发现还需要连接etc下的配置文件。
[root@ha1 ~]# /etc/init.d/keepalived start
Starting keepalived: [ OK ]
[root@ha1 ~]# ln -s /usr/local/keepalived/etc/keepalived /etc/
现在将ha2上也布置好keepalived服务,我们将/usr/local/keepalived发送到ha2下。做和一上相同的软连接。
修改配置文件。
ha1上的配置文件如下:
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost#接收报警的email地址
}
notification_email_from keepalived@ha1.mo.com#警告邮件在哪里发出,注意这里在MASTER和BACKUP上是不一样的
smtp_server 127.0.0.1#设置smtp服务地址,一般为本地
smtp_connect_timeout 30
router_id LVS_DEVEL#load balancer的标志id
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state MASTER#节点的标志,MASTER为主节点,BACKUP为从节点
interface eth0#监测的网络端口
virtual_router_id 51#MASTER和BACKUP的id必须相同
priority 100#优先级,MASTER一定要高于BACKUP
advert_int 1#主备之间通告的间隔秒数
authentication {
auth_type PASS#设置验证类型,有PASS和AUTH
auth_pass 1111
}
virtual_ipaddress {#设置虚拟IP地址
192.168.5.100
}
}
virtual_server 192.168.5.100 80 {#定义虚拟服务
delay_loop 6
lb_algo rr#定义lvs的调度算法,这里使用的是轮询
lb_kind DR#定义lvs模式,这里是DR
#persistence_timeout 50#这里是保持连接时间,对动态页面有很大作用
protocol TCP#定义转发协议的类型
real_server 192.168.5.13 80 {#真正提供服务节点的配置
weight 1#节点权重,数值越大,所承受的负载越大
TCP_CHECK {
connect_timeout 3#3秒无响应超时
nb_get_retry 3#重试次数
delay_before_retry 3#重试间隔
}
}
real_server 192.168.5.14 80 {
weight 1
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}
将这个配置文件发送到ha2上进行,再把所有与ha1和MASTER相关的修改成ha2和BACKUP,在上面的配置文件内容中已经标出。
现在两边重启服务即可。
观察一下ip有没有挂上去,负载均衡是否工作正常。
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:f4:26:bf brd ff:ff:ff:ff:ff:ff
inet 192.168.5.11/24 brd 192.168.5.255 scope global eth0
inet 192.168.5.100/32 scope global eth0
inet6 fe80::20c:29ff:fef4:26bf/64 scope link
valid_lft forever preferred_lft forever
[root@ha1 ~]# ipvsadm
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.5.100:http rr
-> rs1.mo.com:http Route 1 0 0
-> rs2.mo.com:http Route 1 0 0