Keepalived——保持存活,在网络里的含义就是保持在线。Keepalived提供高可用和热备的功能,用来防止单点故障的发生。
1、VRRP协议基本原理介绍
Keepalived实现的基础是VRRP协议,我们将会在这一节中简要介绍VRRP协议的基本原理。
1.1 协议
VRRP协议是为消除在静态缺省路由环境下的缺省路由器单点故障引起的网络失效而设计的主备模式的协议,使得在发生故障而进行设备功能切换时可以不影响内外数据通信,不需要再修改内部网络的网络参数。VRRP协议具有IP地址备份,优先路由选择,减少不必要的路由器间通信等功能。
VRRP协议将两台或多台路由器设备虚拟成一个设备,对外提供虚拟路由器IP(一个或多个),而在路由器组内部,如果实际拥有这个对外IP的路由器能够工作正常的话就是MASTER, MASTER实现针对虚拟路由器IP的各种网络功能,如ARP请求,ICMP,以及数据的转发等;其他设备不拥有该IP,状态是BACKUP,除了接收MASTER的VRRP状态通告信息外,不执行对外的网络功能。当主机失效时,BACKUP将接管原先MASTER的网络功能。
配置VRRP协议时需要配置每个路由器的虚拟路由器ID(VRID)和优先权值,使用VRID将路由器进行分组,具有相同VRID值的路由器为同一个组,VRID是一个0~255的正整数;同一组中的路由器通过使用优先权值来选举MASTER,优先权大者为MASTER,优先权也是一个0~255的正整数。
VRRP协议使用多播数据来传输VRRP数据,VRRP数据使用特殊的虚拟源MAC地址发送数据而不是自身网卡的MAC地址,VRRP运行时只有MASTER路由器定时发送VRRP通告信息,表示MASTER工作正常以及虚拟路由器IP(组),BACKUP只接收VRRP数据,不发送数据,如果一定时间内没有接收到MASTER的通告信息,各BACKUP将宣告自己成为MASTER,发送通告信息,重新进行MASTER选举状态。
1.2 MASTER选举
如果对外的虚拟路由器IP就是路由器本身配置的IP地址的话,该路由器始终都是MASTER;否则如果不具备虚拟IP的话,将进行MASTER选举,各路由器都宣告自己是MASTER,发送VRRP通告信息;如果收到其他机器的发来的通告信息的优先级比自己高,将转回BACKUP状态;如果优先级相等的话,将比较路由器的实际IP,IP值较大的优先权高;不过如果对外的虚拟路由器IP就是路由器本身的IP的话,该路由器始终将是MASTER,这时的优先级值为255。
2、Keepalived内部原理
2.1 Keepalived组件
keepalived是模块化设计,不同模块负责不同的功能。
core:keepalived的核心,负责主进程的启动和维护,全局配置文件的加载解析等;
check:负责healthchecker(健康检查),包括了各种健康检查方式,以及对应的配置文件的解析;
vrrp:VRRPD子进程,用来实现VRRP协议;
libipfwc:iptables(ipchains)库,配置LVS;
libipvs*:配置LVS;
2.2 Keepalived进程
keepalived启动后会有三个进程:
父进程:内存管理,子进程管理等等
子进程:VRRP子进程
子进程:healthchecker子进程
两个子进程都被系统WatchDog看管,两个子进程各自负责自己的事,healthchecker子进程负责检查各自服务器的健康程度,如果healthchecker子进程检查到MASTER上服务不可用了,就会通知本机上的兄弟VRRP子进程,让他删除通告,并且去掉虚拟IP,转换为BACKUP状态。
3、Keepalived安装
3.1安装Keepalived
wget http://www.keepalived.org/software/keepalived-1.2.6.tar.gz
tar zxvf keepalived-1.2.6.tar.gz
cd keepalived-1.2.6
./configure
make
make install
3.2 添加Keepalived为系统服务
cp /usr/local/etc/rc.d/init.d/keepalived /etc/rc.d/init.d/
cp /usr/local/etc/sysconfig/keepalived /etc/sysconfig/
cp /usr/local/sbin/keepalived /usr/sbin/
mkdir /etc/keepalived
3.3添加keepalived的配置项
vi /etc/keepalived/keepalived.conf
我们将会在下一节对Keepalived配置文件——keepalived.conf进行详细介绍。
3.4 启动
service keepalived start
4、Keepalived配置详解
一个功能比较完整的keepalived的配置文件,其配置文件keepalived.conf可以包含三个文本块:全局定义块、VRRP实例定义块及虚拟服务器定义块。
4.1 全局定义块
4.1.1 email通知
有故障,发邮件报警。
4.1.2 Lvs负载均衡器标识
在一个网络内,它应该是唯一的。
4.1.3 花括号“{}”
用来分隔定义块,因此必须成对出现。如果写漏了,keepalived运行时,不会得到预期的结果。由于定义块内存在嵌套关系,因此很容易遗漏结尾处的花括号,这点要特别注意。
4.1.4 notification_email_from
指定发件人。
4.1.5 smtp_server
smtp服务器地址,可以配置为localhost。
4.1.6 smtp_connect_timeout
指定smtp连接超时时间。
4.1.7 router_id
运行keepalived机器的一个标识。
4.2 VRRP定义块
4.2.1 同步vrrp组vrrp_sync_group
确定失败切换(FailOver)包含的路由实例个数。即在有2个负载均衡器的场景,一旦某个负载均衡器失效,需要自动切换到另外一个负载均衡器的实例是哪些。
4.2.2 实例组group
至少包含一个vrrp实例。
4.2.3 Vrrp实例vrrp_instance
实例名出自实例组group所包含的那些名字。
(1)实例状态state只有MASTER和BACKUP两种状态,并且需要大写这些单词。其中MASTER为工作状态,BACKUP为备用状态。当MASTER所在的服务器失效时,BACKUP所在的系统会自动把它的状态有BACKUP变换成MASTER;当失效的MASTER所在的系统恢复时,BACKUP从MASTER恢复到BACKUP状态。
(2)通信接口interface。对外提供服务的网络接口,如eth0,eth1。当前主流的服务器都有2个或2个以上的接口,在选择服务接口时,一定要核实清楚。
(3)lvs_sync_daemon_inteface。负载均衡器之间的监控接口,类似于HA HeartBeat的心跳线。但它的机制优于Heartbeat,因为它没有“裂脑”这个问题,它是以优先级这个机制来规避这个麻烦的。【脑裂:在“双机热备”高可用(HA)系统中,当联系2个节点的“心跳线”断开时,本来为一整体、动作协调的HA系统,就分裂成为2个独立的个体。由于相互失去了联系,都以为是对方出了故障,2个节点上的HA软件像“裂脑人”一样,“本能”地争抢“共享资源”、争起“应用服务”,就会发生严重后果:或者共享资源被瓜分、2边“服务”都起不来了;或者2边“服务”都起来了,但同时读写“共享存储”,导致数据损坏(常见如数据库轮询着的联机日志出错)。】
(4) 虚拟路由标识virtual_router_id。这个标识是一个数字,并且同一个vrrp实例使用唯一的标识。即同一个vrrp_stance,MASTER和BACKUP的virtual_router_id是一致的,同时在整个vrrp内是唯一的。
(5)优先级priority。这是一个数字,数值愈大,优先级越高。在同一个vrrp_instance里,MASTER 的优先级高于BACKUP。
(6) 同步通知间隔 advert_int。MASTER与BACKUP负载均衡器之间同步检查的时间间隔,单位为秒。
(7) 验证authentication。包含验证类型和验证密码。类型主要有PASS、AH两种,通常使用的类型为PASS。验证密码为明文,同一vrrp实例MASTER与BACKUP 使用相同的密码才能正常通信。
4.2.4 虚拟ip地址virtual_ipaddress
可以有多个地址,每个地址占一行,不需要指定子网掩码。注意:这个ip必须与我们在lvs客户端设定的vip相一致。(开启Keepalived服务后,可以通过命令:ip a 来查看虚拟IP是否绑定到本机)
4.3虚拟服务器virtual_server定义块
4.3.1 虚拟服务器virtual_server
这个ip来自于vrrp定义块的第“4”步,后面一个空格,然后加上端口号。定义一个vip,可以实现多个tcp端口的负载均衡功能。
(1)delay_loop:健康检查时间间隔,单位是秒。
(2)lb_algo:负载均衡调度算法,互联网应用常使用wlc或rr。
(3)lb_kind:负载均衡转发规则。一般包括DR,NAT,TUN3种。
(4)persistence_timeout:会话保持时间,单位是秒。
(5)protocol:转发协议,一般有tcp和udp两种。
4.3.2 真实服务器real_server
Real_server的值包括ip地址和端口号。多个连续的真实ip,转发的端口相同。
(1)权重weight。权重值是一个数字,数值越大,权重越高。使用不同的权重值的目的在于为不同性能的机器分配不同的负载,性能较好的机器,负载分担大些;反之,性能差的机器,则分担较少的负载,这样就可以合理的利用不同性能的机器资源。
(2)Tcp检查 tcp_check。
5、Keepalived、Redis高可用配置及脚本
5.1 Keepalived配置文件keepalived.conf
global_defs { router_id LVS_DEVEL } vrrp_script Monitor_Redis { script "/home/plat/laizy/redis/redis/script/redis_keepalive.sh" interval 1 #重复执行间隔1秒 weight -2 #当健康检查脚本失败后,主机权重将会-2 } vrrp_instance VI_1 { state BACKUP #主备机状态均设为BASKUP,这样才可以做到在主机宕掉之后,其余#备机争抢主机身份 interface em1 #绑定网卡名称 virtual_router_id 52 priority 100 #优先级,其余备机应设置比100小的值 advert_int 1 nopreempt authentication { auth_type PASS auth_pass 1111 } notify_master /home/plat/laizy/redis/redis/script/redis_master.sh notify_backup /home/plat/laizy/redis/redis/script/redis_backup.sh track_script { Monitor_Redis #健康检查脚本 } virtual_ipaddress { 10.0.63.251 #虚拟IP地址,可以设置多个 } } |
5.2 Redis服务健康检查脚本redis_keepalive.sh
#!/bin/bash time=$(date '+%Y-%m-%d %H:%M:%S' ) redispath=/home/plat/laizy/redis/redis rediscli=$redispath/redis-cli logfile=$redispath/logs/redis-state.log oldfile=$logfile'.'$(date +%Y-%m-%d --date='30 days ago') yesterdayfile=$logfile'.'$(date +%Y-%m-%d --date='1 days ago') if [ -f $yesterdayfile ] then echo "OK" else mv $logfile $yesterdayfile >> $logfile 2>&1 echo "$time [$yesterdayfile] Move yesterdayfile Success!" >> $logfile fi if [ -f $oldfile ] then rm -f $oldfile >> $logfile 2>&1 echo "$time [$oldfile] Delete Old File Success!" >> $logfile else echo "no old file" fi status=`$rediscli -h 127.0.0.1 -p 6379 info|grep role|awk -F ":" '{print $2}'` $rediscli -h 127.0.0.1 -p 6379 info > /dev/null if [ $? -eq 0 ] then echo "$time redis server is OK" >>$logfile echo The status is:$status >>$logfile else echo "$time no redis service found!" >>$logfile sleep 1 # try to found it again $rediscli -h 127.0.0.1 -p 6379 info > /dev/null if [ $? -eq 0 ] then echo "$time redis server is OK" >>$logfile echo The status is:$status >>$logfile #exit 0 else echo "$time redis server error" >>$logfile #stop keepalived /etc/init.d/keepalived stop echo "$time stop keepalived" >>$logfile fi fi |
5.3 转换为Master身份时触发脚本redis_master.sh
#!/bin/sh localip=127.0.0.1 backip=10.0.63.246 port="6379" time=$(date '+%Y-%m-%d %H:%M:%S' ) redispath=/home/plat/laizy/redis/redis rediscli=$redispath/redis-cli logfile=$redispath/logs/redis-state.log for p in $port do { echo "$time redis $p is the master port" >>$logfile #以主机身份配置Redis服务,注意,Redis支持热配置,即在不重启Redis的情况 #下完成主备机身份的转换 $rediscli -h $localip -p $p slaveof no one >>$logfile 2>&1 } done |
5.4转换为Backup身份时触发脚本redis_backup.sh
#!/bin/sh localip=127.0.0.1 backip=10.0.63.246 port="6379" time=$(date '+%Y-%m-%d %H:%M:%S' ) redispath=/home/plat/laizy/redis/redis rediscli=$redispath/redis-cli logfile=$redispath/logs/redis-state.log for p in $port do { echo "$time redis $p change to $backip port" >>$logfile $rediscli -h $localip -p $p slaveof $backip $p >>$logfile 2>&1 } done |