Noname
Noname

lvs+keepalived构建高可用性负载集群

以某运行计费认证web业务平台的负载为例,介绍LVS+Keepalived的配置方法,使用LVS-NAT模式

拓扑图如下:

https://blog.cpmsxe.net/wp-content/uploads/2018/11/11-1.png

拓扑说明:

防火墙(下称FW)作为总出口,在防火墙上做NAT,AD1和AD2为DirectorServer(下称DS),使用主备方式冗余,最下面4台web为RealServer(下称RS)。RS提供真正的服务,而DS负责根据算法挑选出RS,然后将请求转发给RS,并且DS本身有2台做主备冗余,主DS挂掉之后会自动切到备机继续提供转发服务,防止业务中断。两台DS均对上游和下游各自提供单个的虚拟服务IP(VIP),RS的网关全部指向192.168.100.20,而出口FW的回指路由网关指向172.16.0.20。

部署硬件环境:

两台服务器用作DS,各自都需要2块网卡,RS可以是原来已经在跑业务的服务器,届时只需要修改RS的IP和网关即可。

部署软件环境:

全部DS采用CentOS 6.3系统,RS系统可以任意。

软件环境说明:

LVS是一个集成在内核的模块,用于实现负载均衡,其用户级管理程序是ipvsadm,用于配置LVS,而keepalived是一个服务,启动后根据配置的权重选举MASTER服务器,其他的则以BACKUP的状态待命,并使用vrrp协议维护VIP,当侦测到主设备挂掉之后会将VIP漂移到本机,并广播ARP更新报文,以便上下游设备可以将数据包转发到新的服务器上。

keepalived还可以维护LVS的配置,可以侦测RS节点的状态,失效后自动摘除,恢复后自动添加,所以LVSKeepalived可以说是一对最佳组合。

负载软件安装配置:

分别安装两台DS的系统,使用一般安装流程即可,选择安装类型的时候选择最小化桌面安装,要注意DS需要两块网卡,并且分别配置不同网段的IP
分别装完系统后登陆到主DS,先安装ipvsadm包
yum -y install ipvsadm
再安装keepalived包
yum –y install keepalived
检查两个包是否正确安装
ipvsadm
如果有打印IP Virtual Server version 1.2.1字样而不是报错则安装成功
接下来检查keepalived
/etc/init.d/keepalived stop
如果有提示服务关闭(关闭失败也行,因为还没有启动),那则是安装无误
接下来调整系统内核参数,打开路由转发,关闭防火墙(必须)

echo "SELINUX=enforcing" >/etc/selinux/config
echo "SELINUXTYPE=targeted" >>/etc/selinux/config
echo "1" >/proc/sys/net/ipv4/ip_forward
echo "0" >/proc/sys/net/ipv4/conf/all/send_redirects
echo "0" >/proc/sys/net/ipv4/conf/default/send_redirects
echo "0" >/proc/sys/net/ipv4/conf/eth0/send_redirects
service iptables stop

这些命令重启后失效,所以可以写进开机脚本里以便每次重启后自动执行
vi /etc/rc.d/rc.local
这样就完成了准备工作,可以开始配置了,虽然可以使用ipvsadm来配置负载,但是无法实现节点失效后自动去除等功能,所以一般通过配置keepalived来自动完成负载的配置。以下将主要介绍keepalived的配置。
打开keepalived主配置文件
vi /etc/keepalived/keepalived
建议先清空原来的配置,依此按v``shift+g``shift+4``d来删除所有内容,使用下面提供的样例来修改:

! Configuration File for keepalived

global_defs {
    router_id NodeA
}
vrrp_instance VI_1 {
    state MASTER # 为BACKUP时则为备机
    interface eth0 # 此VIP对应的网卡,此例eth0为上联口
    virtual_router_id 51
    priority 100 # 优先级,备机需要配置比这个低的数值,比如95
    advert_int 1
    authentication {
    auth_type PASS
    auth_pass 1111
    }
virtual_ipaddress {
    172.16.0.20/24 #此网口的VIP以及掩码
    }
}

vrrp_instance VI_2 { #此为配置下联口的VIP参数,配置类似上面
    state MASTER    
    interface eth1 #修改为下联口网卡
    virtual_router_id 52 
    priority 110
    advert_int 1   
    authentication {
        auth_type PASS  
        auth_pass 1111 
        }
virtual_ipaddress {
        192.168.100.20/24  
        }
}
#下面将业务配置文件包含进来,业务配置文件主要配置负载均衡部分,稍后进行配置
! include virtual server configure file
include web.conf

接下来新建一个业务配置文件vi /etc/keepalived/web.conf并写入下面的内容

virtual_server 172.16.0.20 80 {#服务器节点池,一个服务(端口)需要一组,此为HTTP服务
    delay_loop 30 #服务检测间隔秒数
    lb_algo rr #节点选择算法,rr为轮询
    lb_kind NAT #转发方式为NAT
    nat_mask 255.255.255.0
    #persistence_timeout 50#会话保持时间秒,此具体业务不需要保持会话,所以注释掉了
    protocol TCP #协议类型,TCP或者UDP
    real_server 192.168.100.32 80 { #真实服务器节点1,注意修改地址和端口为对应的
        weight 1 #权重
        HTTP_GET { #配置节点检测方式,这里是基于7层的HTTP检测,有其他检测方式
            url {
                path / #httpget路径,这里是访问服务器的主页
                status_code 200 #返回的状态是200则认为节点正常
            }
            connect_timeout 3 #检测连接超时时间秒
            nb_get_retry 3 #检测重试次数
            delay_before_retry 3 #每次重试的间隔秒
        }
    }
    real_server 192.168.100.33 80 { #第2个真实服务器节点
        weight 1
        HTTP_GET {
            url {
                path /
                status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }
    real_server 192.168.100.34 80 { #第3个
        weight 1
        HTTP_GET {
            url {
                path /
                status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }
    real_server 192.168.100.35 80 { #第4个
        weight 1
        HTTP_GET {
            url {
                path /
                status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }
}

virtual_server 172.16.0.20 1812 { #radius认证的配置,同上
    delay_loop 30
    lb_algo rr
    lb_kind NAT
    nat_mask 255.255.255.0
    #persistence_timeout 50
    protocol UDP #注意协议为UDP
    real_server 192.168.100.32 1812 {
        weight 1
        MISC_CHECK { #这里使用自定义脚本来检测UDP端口是否打开,脚本后面会给出
          misc_path "/radius/udpcheck.sh 192.168.100.32 1812" #脚本执行路径和参数
          misc_timeout 5 #等待脚本返回超时时间
          misc_dynamic #写上这条则可以根据脚本返回的code动态调整节点权重
        }
    }
    real_server 192.168.100.33 1812 {
        weight 1
        MISC_CHECK {
          misc_path "/radius/udpcheck.sh 192.168.100.33 1812"
          misc_timeout 5
          misc_dynamic
        }
    }
    real_server 192.168.100.34 1812 {
        weight 1
        MISC_CHECK {
          misc_path "/radius/udpcheck.sh 192.168.100.34 1812"
          misc_timeout 5
          misc_dynamic
        }
    }
    real_server 192.168.100.35 1812 {
        weight 1
        MISC_CHECK {
          misc_path "/radius/udpcheck.sh 192.168.100.35 1812"
          misc_timeout 5
          misc_dynamic
        }
    }
}

virtual_server 172.16.0.20 1813 { #radius计费的配置,同上
    delay_loop 30
    lb_algo rr
    lb_kind NAT
    nat_mask 255.255.255.0
    #persistence_timeout 50
    protocol UDP #注意协议为UDP
    real_server 192.168.100.32 1813 {
        weight 1
        MISC_CHECK {
          misc_path "/radius/udpcheck.sh 192.168.100.32 1813"
          misc_timeout 5
          misc_dynamic
        }
    }
    real_server 192.168.100.33 1813 {
        weight 1
        MISC_CHECK {
          misc_path "/radius/udpcheck.sh 192.168.100.33 1813"
          misc_timeout 5
          misc_dynamic
        }
    }
    real_server 192.168.100.34 1813 {
        weight 1
        MISC_CHECK {
          misc_path "/radius/udpcheck.sh 192.168.100.34 1813"
          misc_timeout 5
          misc_dynamic
        }
    }
    real_server 192.168.100.35 1813 {
        weight 1
        MISC_CHECK {
          misc_path "/radius/udpcheck.sh 192.168.100.35 1813"
          misc_timeout 5
          misc_dynamic
        }
    }
}

由于keepalived本身没有提供UDP的节点检测方式,但是提供了调用自定义脚本或程序来检测的功能,如果脚本或程序return 0则认为正常,如果return 1则认为故障,如果为其他值则认为正常并且可以改变节点权重。这里提供一个简单的脚本用于检测UDP端口是否打开,首先新建一个文本,要先新建radius目录mkdir /radius然后vi /radius/udpcheck.sh

#!/bin/bash
#check udp port by cpm

if [ $# -ne 2 ];then
  echo "Warning: check_command error."
  exit 1
else
  SERVER_IP=$1
  SERVER_PORT=$2
  CMD=`nc -vuz -w 1 ${SERVER_IP} ${SERVER_PORT} 2>/dev/null | grep "succeeded" | wc -l`
  if [ ${CMD} -ne 1 ];then
    echo "CRITCAL: check server ${SERVER_IP} failed."
    exit 1
  else
    echo "OK: check server ${SERVER_IP} OK."
    exit 0
  fi
fi

保存并给予执行权限
chmod a+x /radius/udpcheck.sh
调用方法为/radius/udpcheck.sh 192.168.100.32 1812其中IP为检测的主机,后面是端口号
这样keepalived就可以调用此脚本来检测UDP服务的可用性了

应用服务器配置

接下来配置一下几台RS。基本不需要做什么改动,只需要配置网卡IP为DS下联口同网段的IP,然后网关指向DS的下联口VIP(192.168.100.20)即可
还要配置一下出口的防火墙。由于负载均衡器是没有SNAT功能的,这样一来默认几台RS是无法上网的,没法主动访问外网,为解决此问题需要在防火墙上做好RS服务器网段的回指路由,以及RS服务器网段的SNAT规则。
在防火墙上配置静态路由,下一跳指向DS的上联口VIP
route add 192.168.100.0/24 next 172.16.0.20

接下来配置SNAT,需要将DS的VIP(172.16.0.20),以及所有RS的IP(也可以是RS所在的整个地址段)全部加进SNAT规则里,转换成出口地址。这样一来RS就可以主动访问外网了。如果服务器不需要主动访问外网,也可以不用把RS加进SNAT规则里,只加DS的VIP即可,但是如果是我们具体的计费认证业务则需要全部加入,因为portal协议要服务器主动发包出去,不添加的话业务流程走不通。
另外还要做好端口映射,让外网到达防火墙的80,1812,1813端口转发给172.16.0.20
接下来启动keepalived服务,让DS上线
/etc/init.d keepalived start
这样一来就完成主DS的所有配置了

运行状态检查

首先检查DS的IP和VIP是否正确绑定了
ip a或者ifconfig查看两块网卡上是否分别绑定了2个地址,一个是物理地址,一个是VIP
然后使用ipvsadm来检查节点状态
ipvsadm -Ln
这将打印出节点池,以及相关节点状态,包括转发方式、权重、连接数等,因为刚刚已经在keepalived配好LVS相关的内容,keepalived会维护LVS配置,所以这里会看到配置好的节点池。要查看更详细的连接信息,则要用
ipvsadm -Ln --stats
这会打印出包括节点池在内的转发包数,字节数信息,可以在此看到各个节点的转发情况,还可以通过下面的命令查看各个节点的传输速率
ipvsadm -Ln --rate
如果一切正常,就可以开始配置DS备机了,配置跟第一台一样,要注意一点就是要修改一下keepalived的主配置文件/etc/keepalived/keepalivedstate MASTER要改成state BACKUP,优先级要改得比主设备低,详见上方keepalived主配置文件说明部分。完成配置后同样启动备机的keepalived服务,检查节点池是否有正确配置。
在备机上打ip a是不会看到VIP的,因为此时是处于BACKUP状态。这时候我们可以检查主备是否工作正常。关闭主设备的keepalived服务/etc/init.d/keepalived stop或者直接关了主设备的电源,再到备机上打ip a即可看到VIP已经漂移过来了,这时候外部还可以继续通过外部VIP访问到RS。
我们可以尝试从外网访问服务器,比如HTTP服务,网页正常打开,ipvsadm -Ln --stats发现有数据包进出了,多访问几次,可以发现请求被转发到不同的RS

至此,LVS+Keepalived高可用性负载集群搭建完成

常见问题

①DS上查状态发现有in包,但是却没有out包?
检查一下DS的路由转发有没有开启,Linux默认不允许转发报文,还有检查一下RS的网关是否指向DS的下联口VIP
②RS上ping不通外网,但是外部可以访问进来?
检查DS上游的路由设备有没有做好RS网段的回指路由,检查出口有无做好RS网段的SNAT

发表回复

textsms
account_circle
email

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理

Noname

lvs+keepalived构建高可用性负载集群
以某运行计费认证web业务平台的负载为例,介绍LVS+Keepalived的配置方法,使用LVS-NAT模式 拓扑图如下: 拓扑说明: 防火墙(下称FW)作为总出口,在防火墙上做NAT,AD1和AD2为Direct…
扫描二维码继续阅读
2018-11-22