概述:
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 [root@dp1 ~]# ipvsadm -a -t 172.25.9.100:80 -r 172.25.9.43 -g添加真实服务的节点,-a 添加一个真实服务的虚拟ip,-r定义real service的地址,-g使用直接路由方式(DR)。
[root@dp1 ~]# 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 0 -> rs2.mo.com:http Route 1 0 0查看lvs的状态此时给dp1添加虚拟ip。
[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]# ls index.html
[root@rs2 html]# ls index.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 [root@foundation9 0220]# curl 172.25.9.100 rs1发现没有成功,这时如果我们理解原理,就能知道,既然一直访问的是rs1,说明172.25.9.100的ip地址一定绑定在了
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.100 rs2 [root@foundation9 0220]# curl 172.25.9.100 rs1现在重新测试,已经成功符合了负载均衡的结果。
现在我们做一个测试,将rs1的http服务关闭。
[root@foundation9 0220]# curl 172.25.9.100 rs2 [root@foundation9 0220]# curl 172.25.9.100 curl: (7) Failed connect to 172.25.9.100:80; Connection refused发现lvs并没有发现rs1坏掉了,仍然会切换到坏掉的rs1上,在真实环境中,这明显不是我们想要的结果,应该是当检测到rs1坏掉后,就不会再跳到rs1上。使用现有的东西我们无法完成,所以需要添加一个监控服务健康的服务。就是
ldirectord,用于监控在lvs集群的真实服务。ldirectord是和heartbeat相结合的一个服务,可以作为heartbeat的一个启动服务。所以之前要安装好heartbeat,而且配置好,再将ldrectord的配置文件复制到/etc/ha.d下,因为默认没有放到里面。
[root@dp2 ha.d]# rpm -ql ldirectord /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.gzldirectord.cf就是配置文件。
编辑配置文件。
checktimeout=3 checkinterval=1 autoreload=yes quiescent=no
virtual=172.25.9.100:80 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配置如上,通过virtual来定义vip,接下来是定义real service的节点,fallback是当所有real挂掉后,本机冲上去,一般这个页面显示服务器正在维护等界面。service表示;调度的服务,scheduler是调度算法,protocol是定义协议,checktype是检查类型为协商,checkport就是检查的端口,也就是健康检查。request代表你的/var/www/html一定要有index的html。接下来启动服务lvs就会自己开启,而且ip也会自己布置。
但是启动ldirectord模块的时候出现了问题
[root@dp1 ha.d]# /etc/init.d/ldirectord start 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这就是perl模块的问题,我们安装一下perl模块就好了。
[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.100 rs2 [root@foundation9 0220]# curl 172.25.9.100 rs1负载均衡成功。
[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. BEGIN failed--compilation aborted at /usr/sbin/ldirectord line 3061. failure这就是缺少那个perl包了
perl-IO-Socket-INET6.noarch : Perl Object interface for AF_INET|AF_INET6 domain sockets安装之后就可以解决了
4.将ldirectord加入heartbeat集群。
首先配置好heartbeat,对heartbeat还不太了解的小伙伴可以看一下上一篇博客,如下是ha.cf
logfacility local0 keepalive 2 deadtime 30 warntime 10 initdead 60 udpport 10005 bcast eth0 # Linux auto_failback on node ha1.mo.com node ha2.mo.com ping 192.168.5.1 respawn hacluster /usr/lib64/heartbeat/ipfail apiauth ipfail gid=haclient uid=haclusterauthkeys文件
auth 1 1 crcharesource文件
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
[root@ha1 keepalived-1.2.24]# ./configure configure: error: in `/root/keepalived-1.2.24': configure: error: no acceptable C compiler found in $PATH See `config.log' for more details日常执行configure,发现没有c compiler。
configure: error: !!! OpenSSL is not properly installed on your system. !!! !!! Can not include OpenSSL headers files. !!openssl没有继续下载,切记是openssl-devel。因为这是属于编译阶段,缺少的都是devel。
编译成功进入make阶段,但是这里给大家一个建议,由于这个源代码包无法生成rpm,为了之后迁移到另一个节点考虑的话,我们应该将keepalive安装到一个独立的目录中方便迁移。
[root@ha1 keepalived-1.2.24]# ./configure --prefix=/usr/local/keepalived将keepalived的根目录放置到/usr/local下。之后在进行make和make install
[root@ha1 keepalived]# pwd /usr/local/keepalived [root@ha1 keepalived]# ls bin etc lib sbin share现在已经将keepalived的根目录仿真到了/usr/local下。
现在将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/ [root@ha1 ~]# /etc/init.d/keepalived start Starting keepalived: /bin/bash: keepalived: command not found [FAILED]将sysconfig下文件放置好后仍然报错,发现找不到命令,也就是缺少/sbin下的二进制命令,我们继续连接,将启动的二进制文件连接到/sbin下。
[root@ha1 ~]# ln -s /usr/local/keepalived/sbin/keepalived /sbin/ [root@ha1 ~]# /etc/init.d/keepalived start Starting keepalived: [ OK ]测试启动,发现已经打开了。但是现在先关闭keepalived服务,因为配置文件还没有写好,到这里发现还需要连接etc下的配置文件。
[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 [email protected] #警告邮件在哪里发出,注意这里在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 } } }
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