Keepalived工作原理详解及配置实例
keepalived资料
故障场景测试
一、集群基础
1、系统的扩展方式
- scale up向上扩展:提高单台服务器的性能
- scale out向外扩展:多台服务器联合起来满足同一个需要
2、集群类型
- LB :load balancing,负载均衡集群,通过横向扩展提高系统性能
- 实现方式
* 传输层 : ipvs(lvs)
- 应用层 : nginx(upstream,proxy)
- 架构的基本表现方式
- 前端 : 负载均衡器,调度器
- 后端 : 上游服务器(upstream server),后端服务器,“真”服务器(real server)
SPOF : Single point of failure(单点故障)`
- 实现方式
- HA : High Avalilability,高可用集群,提供冗余主机提升系统可用性
* 架构的基本表现方式 * 前端:Active,活动服务器* 后端:passive,备用服务器
`avalilability = 平均无故障时间/(平均无故障时间+平均修复时间)值的取值范围:0-1之间,99%,99.9%, 99.99%,99.999% 5个9表示: 一年有5分钟不在线的时间`
- HP : High Performance,高可用集群
组合多台主机解决一个问题, 每个主机只负责其中一部分运算 - DS : Distributed System,分布式系统
* 分布式存储 * HDFS(hadoop)* mogileFS* ClusterFS* Ceph(已经收录到linux内核)
- 分布式计算
* Hadoop的YARN框架
- batch : MapReduce(批处理计算)
- in-memory : spark
- stream : storm
二、集群实现方式
1、集群的实现
- 分布式计算
- 基于实现方式划分:
* 硬件实现: * F5(BIG-IP)* Citrix Netscaler* A10(A10)* Arry* redware
- 软件实现
* Lvs(Linux virtual Server)
- HAproxy
- Nginx
- ats (apache traffic server)
- perlbal
- 软件实现
- 基于工作的协议层次划分
* 传输层 * lvs* HAproxy(mode tcp)
- 应用层
* HAproxy(mode http)
- Nginx
- ats
- perlbal
2、HA集群的实现
- 应用层
- Keepalived
* 通过模拟Vrrp协议来实现地址漂移
- AIS系统
* heartbeat(Centos 6之前系统可能使用)
- Cman+rgmanager(RHCS : Redhat Cluster Suite)
- Corosync+pacemaker+crmsh
三、HA Cluster
HA Nginx Porxy Service需要的关键资源
- 公网IP
- Nginx Service(两台server的时间要严格同步)
- 相同的配置文件
AIS可用性委员组,规定高可用集群栈
- 1、Messaging Layer(Infrastructure Layer),消息层(心跳层)
* 互相传递心跳信息(集群事务信息的传递,由监听的套接字服务来实现),向上提供一堆的API接口,在这周提供高可用的能力
- 2、CRM(Cluster Resource manager)集群资源管理层
* 专门负责高可用集群的资源管理,如:选取主节点
- 其中CRM包含了LRM(Local Resource Manager),执行资源配置
- 3、RA(Resource Agent),资源代理层
* 管理机制的实现(如:start,stop,restart,status,monitor)
四、高可用集群面临的问题
1、集群的分裂(partion)
被称之为集群的分区(partion)也被称之为脑裂(brain-split))为了避免出现分裂,事先做好决策,在每个主机上都有一票,票数多的将获取主节点。如果一个服务器性能好,可以有2票。
2、多节点使用同一个共享存储
在集群发生分裂的情况下, 可能会引发多节点同时对一个块级别的共享存储写一个文件,这样会导致文件系统损坏
- 解决方法
* 干掉对方服务器的电源(如通过电源交换机将主机的电源断掉)
五、VRRP概述
VRRP协议
虚拟路由冗余协议(virtual router redundancy protocol,简称VRRP),是由IETF提出的解决局域网中配置静态网关出现单点失效现象的路由协议,1998年已推出正式的RFC2338协议标准,VRRP广泛应用在边缘网络中,它的设计目标是支持特定情况下IP数据流量失败转移不会引起混乱,允许主机使用单路由器,以及及时在实际第一跳路由器使用失败的情形下仍能够维护路由器间的连通性。
VRRP术语
虚拟路由器
* 由一个Master路由器和多个Backup路由器组成,主机将虚拟路由器当作默认网关
VRID
* 虚拟路由器的标识,有相同VRID的一组路由器构成一个虚拟路由器
Master路由器
* 虚拟路由器中承担报文转发任务的路由器,即主节点(仅能有一个)
Backup路由器
* Master路由器出现故障时,能够代替Master路由器工作的路由器,即备用节点(可以有多个)
虚拟IP地址(VIP)
* 虚拟路由器的IP地址,已改为虚拟路由器可以拥有一个或多个IP地址
IP地址拥有者
* 接口IP地址与虚拟IP地址相同的路由器被称之为IP地址拥有者
虚拟MAC地址(VMAC)
* 一个虚拟路由器拥有一个虚拟MAC地址,虚拟路由器回应ARP请求使用的是虚拟MAC地址
优先级
* VRRP根据优先级来确定虚拟路由器中每台路由器的地位
非抢占方式
* 若Backup路由器工作在非抢占模式下,则只要Master路由器没有故障,Backup路由器即使随后被配置了更高的优先级也不会成为Master路由器
抢占方式
* 如果backup路由器工作在抢占方式下, 当它收到VRRP报文后,会将自己的优先级与通告报文中的优先级进行比较,如果自己的优先级比当前的Master优先级高,就会主动抢占成为Master路由器,否则,将保持Backup状态
VRRP工作过程
- 1、虚拟路由器中的路由器根据优先级选举出Master,Master通过发送ARP报文,将自己的虚拟MAC地址发送给其它设备和主机
- 2、Master路由器周期性发送VRRP报文,以公布其配置信息(优先级等)和工作状态
- 3、如果Master路由器出现故障, 虚拟路由器的backup路由器根据优先级重新选举新的Master
- 4、虚拟路由器状态切换时,新的Master路由器只是简单地发送一个携带虚拟路由器的MAC地址和IP地下信息的ARP报文,这样就可以更新与它连接的主机或设备中的ARP相关信息,网络中的主机感知不到Master的切换
- 5、backup路由器优先级高于master路由器时,由backup路由的工作方式(抢占或非抢占方式)决定是否重新选举Master
- VRRP优先级的取值范围为0-255(数值越大优先级越高),可配置的范围为1到254,优先级0为系统保留给路由器放弃master位置时使用,255则是系统保留给IP地址拥有者使用,当路由器为IP地址拥有者时,其优先级始终为255,当虚拟路由器拥有虚拟IP地址时,只要其工作正常,则为Master路由器
路由通告的工作原理
- Master路由器周期发送VRRP报文,在虚拟路由器中公布其配置信息(优先级)和工作状态,backup路由器通过接收vrrp报文情况来判断master是否工作正常
- master路由器主动放弃master地位时,发送优先级为0的VRRP报文,致使backup路由器切换为master路由器,这个切换时间为skew time, 计算方式为:(256-backup路由器的优先级/256,单位为秒)
- 当master路由器发送网络故障不能发送VRRP报文的时,backup路由器不能立即知道其工作状态,backup路由器等待一段时间后,如果还没有收到VRRP报文, 会认为master工作不正常, 而把自己升级为master路由器,周期发送VRRP报文,如果此时多个backup路由器竞争master路由的位置,将通过优先级选举master路由器,backup路由器默认等待的时间为master_down_interval,取值为:(3*VRRP报文的发送时间间隔+skew time,单位为秒)
- 在性能不稳定的网络中, backup路由器可能因为网络堵塞而在master_down_interval期间没有收到master路由的报文,而主动抢占master位置, 如果此时master报文又到达了, 就会出现虚拟路由器的成员频繁的进行master抢占现象,为了缓解这种情况发生,特制定了延迟等待定时器,它可以使得backup路由器在等待了master_down_interval后,再等待延迟等待时间,如果在此期间仍然没有收到VRRP报文,则此backup路由器才会切换为master路由器,对外发送VRRP报文
VRRP实现的工作
- 路由选举
- 路由状态通知
- 为了提高安全性,VRRP还软件娃娃了认证功能
VRRP认证方式
- 无认证
- 简单字符认证,通常用于局域网
- MD5认证,跨越互联网
VRRP高可用工作模型
主备备份
* 主备备份方式表示业务仅由Master路由器承担,当Master路由器出现故障时,才会由选举出来的Backup路由器接替它的工作,如下图:
主主备份
* 在路由器的一个接口上可以创建多个虚拟路由器,使得该路由器可以在一个虚拟路由器中作为Master路由器,同时在其它的虚拟路由器中作为Bacup路由器,主主备份模式可以实现负载分担方式,是指多台路由器同时承担业务,因此负载分担方式需要两个或两个以上的虚拟路由器,每个虚拟路由器都包括一个Master路由器和若干个Backup路由器。各虚拟路由器的Master路由器可以不相同,如下图:
Keepalived
一、keepalived功能
keepalived程序是vrrp协议在linux主机上以守护进程方式的实现,能够根据配置文件生成IPVS规则 ,并对各real server的健康做检测,以及Loadbalance主机和backup主机之间failover的实现,keepalived在Centos6.4+收录到了发行版光盘中。
二、keepalived核心组件
- 核心组件
* Watchdog : 高可用监视器(监控服务本身,可实现重启的)
- Checkers : 健康状态检测器,可实现如下协议
* TCP
- HTTP
- SSL
- MISC
- SMTP : 支持发送邮件通知机制
- System Call : 通过系统调用做出管理操作
- VRRP stack : VRRP栈的实现,实现VRRP协议调用
- NetLink Reflectior : VRRP借助于netlink监控网络,实现网络功能配置
- Ipvs wrapper : ipvs控制
- Checkers : 健康状态检测器,可实现如下协议
- IO复用器
- 内存管理
- 控制面板(配件文件分析器,以实现应用配置文件)
三、Keepalive的工作原理:
- 1、主节点主动向备用节点发送存活通知消息(只是3层判断)
- 2、发送存活通知消息机制:
* 广播(broadcast)
- 组播(multicast)
- 单播(unicast)
- 3、设定各服务器的优先级,优先级判断方法
* 手动设定
- 根据IP地址数值大小,大的优先级高
- 随机的挑选
- 4、需要监控服务器的存活状态,如果服务故障需要重启服务,如重启服务无效,就需要降低主节点的优先级
- 5、各节点需要安装keepalive服务,并且都加入到同一个集群中,并且每个节点都监听在某个套接字止,不断向外传递心跳信息
- 6、多个节点配置域共享密钥,防止有人恶意加入集群
- 7、集群自行决定来启动服务,不能够也不应该手动启动(建立策略来决定哪个节点启动服务)
- 8、将多个资源绑定在一起,一同调用或配置
- 9、模拟VRRP协议,实现地址飘移,keepalived仅能飘移IP地址
- 10、不能转移服务,内置了一个模块,能直接向内核的ipvs添加规则,创建一人LVS(keepalved天生高可用lvs)
- 11、内置的提供了一个接口,可以通过编写脚本,来检测服务的状态,根据返回的状态,如果发生了故障,就主动降低服务器的优先级(vrrp_script,track_script)
Keepalived高可用集群配置前提
- 各节点时间要同步,一般使用网络时间服务器
- 确保iptables及selinux服务关闭
- 各节点之间可通过主机名互相通信,节点的名称设定与hosts文件中解析的主机名都要保持一致(AIS架构必须项)
* uname -n 获得主机名,与解析的主机名要相同
- 各节点基于密钥认证的方式通过ssh互信通信
keepalived的程序环境
- 主配置文件
* /etc/keepalived/keepalived.service
- 生成hash指纹的工具
* /etc/bin/genhash
`[root@Centos7 ~]# genhash -s 172.16.36.70 -p 80 -u index.htmlMD5SUM = 7833123aaf6b782a8997b80affda274f`
四、keepalived配置详解
/etc/keepalived/keepalived.conf
- Global configuration : 全局配置
` global_defs { ... }`
- VRRP Configuration : 配置VRRP实例
` vrrp_instance NAME { ... }`
- LVS Configuration : IPVS的相关配置
` virtual_server IP PORT { ... real_server IP PORT { ... } }`
Global指令
notification_email {}
: 邮件通知的对象,收件人邮箱notification_email_from
: 发件人邮箱smtp_server
: 邮件发送服务器IP地址smtp_connect_timeout
: 连接邮件服务器的超时时长router-id HOSTNAME
: 物理节点的标识符,建议使用主机名vrrp_mcast_grou4 224.0.0.18
: vrrp的多播地址,IPV4,默认为224.0.0.18vrrp_mcast_group6 ff02::12
: vrrp的多播地址, IPV6vrrp_script NAME { }
: 定义脚本,可以在vrrp_instance中使用track_script引用* script COMMAND : script是固定字段,后面为脚本的内容,有空格需要使用引号包括起来
- interval # : 间隔多长时间进行状态查看,以秒为单位
- weight [+|-] # : 如果脚本的返回状态是失败的,将优先级减去相应的数值
nopreempt
: 定义为非抢占模式preempt_delay TIME
: 定义为延迟抢占模式
VRRP_instance指令
state MASTER | BACKUP
: 在当前VRRP实例中(虚拟路由器组)此节点的初始实例Interface IFACE_NAME
: vrrp用于绑定VIP的接口,各节点网卡接口名称需保持一致virtual_route_id #
: 虚拟路由器的ID(VRID),可用值为0-255,默认为51priority #
: 当前路由器节点的优先级,可用范围为0-255advert_in #
: 通告时间间隔,单位是秒种,默认是1秒authentication { }
: 定义认证的特殊引用段* auth type PASS : 指定集群密钥方式
- auth_pass 1234 : 字符密钥吸有前8个有效
virtual_ipaddress { }
: 定义集群中主机的特殊引用* \/brd \Dev\scope \label \
notify_master <string> | <quoted-string>
: 当前节点转为主节点触发的脚本notify_backup <string> | <quoted-string>
: 当前节点转为备用节点触发的脚本notify_fault <string> | <quoted-string>
: 当前节点出现故障时触发的脚本notify <string> | <quoted-string>
: 一般情况下, 只使用上面三个, 或者只使用下面一个track_script { VRRP_SCRIPT_NAME }
: 使用此引用,可以调用vrrp_script定义的脚本并执行track_script { IFACE_NAME }
: 调用vrrp_script内置方法,可以判断主机的网络接口是否正常,如果不正常将自动降低其权重,转为backup模式
virtual_server指令
delay_loop <INT>
: 延迟多长时间检测集群服务是否OKlb_algo rr|wrr|lc|wlc|lblc|sh|dh
: lvs的调度算法lb_kind NAT|DR|TUN
: lvs的类型,如需支持fullnat,需要打补丁persistence_timeout <INT>
: 持久时长,0表示不启用nat_mask 255.255.255.0
: IP掩码地址,此处的nat没有写错protocol TCP
: lvs调度的协议,默认是udp,如果是udp可以不用添加此指令virtual_host <string>
: 对哪个虚拟主机做健康状态检测,可以不定义quorum <INT>
: 最少法定票数,判断realserver有几台才是OK的quorum_up
: 添加票数quorum_down
: 降低票数sorry_server <IPADDR><PORT>
: 定义sorry serverreal_server IP PORT { }
:定义一个real_server主机* `weight <INT>` : 权重
inhibit_no_failure
: 如果检测失败,就把权重设置为0notify_up <string> | <quoted-string>
: realserver上线通知,依赖脚本完成notify_down <string> | <quoted-string>
: realserver下线通知,依赖脚本完成HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK
: 对后端的realserver主机,使用相应的方法做健康状态检测* `url { }` : 对url做健康检测的特殊引用 * `path <string>` : 检测的url路径* `status_code <INT>` : 依赖返回状态码进行检测* `digest <string>` : 依赖页面的hash值进行检测,基于genhash命令完成hash值计算
nb_get_retry <INT>
: get请求的重试次数delay_befor_retry <INT>
: 两次重试之间的时间间隔,要延迟多长时间,再retryconnect_ip <IPADDR>
: 默认会按real server的IP做健康状态检测,一般不需要再写,但有的时候可能有一个IP专门做健康状态检测的IP,故要手动添加上去connect_port <PORT>
: 连接的端口bindto <IPADDR>
: 如果keepalived主机有多个IP,定义用哪个IP完成健康状态检测connect_timeout <INT>
: 连接超时时长,默认为5秒,但这个时长比较长, 建议调整至3秒warmup <INT>
: 做健康状态检测的延迟, 即keepalived服务起来后,等待多长时间再开始健康状态检测,有时候后端的real server还未启动完成,故需要等待一段时间
TCP_CHECK { }
: 传输层健康状态检测* `connect_timeout <INT>` : 连接超时时长
connect_ip
: 检测的realserver的IP,一般不需要写,同url中的参数一样connect_port
: 检测的realserver的port,一般不需要写,同url中的参数一样bindto <IP ADDR>
: 同url中的参数一样bind_port <port>
: 使用哪个端口做健康状态检测
五、主备模式的可高可用nginx的配置实例
`实验环境: 172.16.36.70 172.16.36.71 ######172.16.36.70的配置 ~]# ssh-keygen -t rsa -P ‘’ -f /root/.ssh/id_rsa ~]# ssh-copy-id root@172.16.36.71 ~]# vim /etc/hosts 172.16.36.71 Centos7.pc2 ~]# ntpdate 172.16.0.1 ~]# yum install nginx ~]# mv /usr/share/nginx/html/index.html{,.bak} ~]# vim /usr/share/nginx/html/index.html 172.16.36.70 ~]# systemctl start nginx 使用客户端IE测试测试页面,是否正常显示 ~]# yum install keepalived ~]# vim /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { notification_email {
root@localhost
}
notification_email_from keepalived_admin@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id Centos7.pc1 #路由设备在网络中的名称,一般为hostname
}
######使用vrrp_script实现依赖脚本监测文件的存在性,来降低节点的优先级,以此实现主备模式的切换
vrrp_script chk_down {script "[ -f /etc/keepalived/down ] && exit 1 || exit 0"interval 1weight -20
}
######监测web的访问返回结果,判断服务的可用性, 来了解你节点的优先级
vrrp_script chk_nginx {script "curl -s 172.16.36.70 | grep 172 &> /dev/null"interval 1weight -20
}
######监控主机的nginx是否存在,0信号只是做进程探测的
vrrp_script chk_nginx2 {script "killall -0 nginx" interval 1 weigth -20
}
vrrp_instance VI_1 {state MASTERinterface eno16777736virtual_router_id 100priority 100advert_int 1authentication { auth_type PASS auth_pass 99999999}virtual_ipaddress {172.16.36.100/16 dev eno16777736 label eno16777736:1}notify_master "/etc/keepalived/keepalived.sh master"notify_bakcup "/etc/keepalived/keepalived.sh backup"notify_fault "/etc/keepalived/keepalived.sh fault"track_script {chk_downchk_nginxeno16777736 #监控主机的网卡,如果出现故障可自动降低优先级。 此脚本调用不用定义,是vrrp_script内置的}
}
~]# vim /etc/keepalived/keepalived.sh
#!/bin/bash
#author :Magedu
#Description : an example of notify script
contact=’root@localhost’
notify() {mailsubject="$(hostname) to be $1:vip floating"mailbody="$(date +'%F %H:%M:%S'): vrrp transition,$(hostname) change to be $1"echo $mailbody | mail -s "$mailsubject" $contact
case $1 in
master)notify mastersystemctl start nginx.serviceexit 0;;
backup)
notify backupsystemctl restart nginx.serviceexit 0;;
fault)
notify faultsystemctl stop nginx.serviceexit 0;;
*)
echo "Usage: $(basename $0) {master|backup|fault}"exit;;
esac
######172.16.36.71的配置
172.16.36.71
~]# ssh-keygen -t rsa -P ‘’ -f /root/.ssh/id_rsa
~]# ssh-copy-id root@172.16.36.70
~]# vim /etc/hosts
172.16.36.70 Centos7.pc1
~]# ntpdate 172.16.0.1~]# yum install nginx
~]# mv /usr/share/nginx/html/index.html{,.bak}
~]# vim /usr/share/nginx/html/index.html
172.16.36.70
~]# systemctl start nginx
使用客户端IE测试测试页面,是否正常显示
~]# yum install keepalived
~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {root@localhost
}
notification_email_from keepalived_admin@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id Centos7.pc2
}
vrrp_script chk_down {script "[ -f /etc/keepalived/down ] && exit 1 || exit 0" interval 1 weight -20
}
vrrp_script chk_nginx {script "curl -s http://172.16.36.100 | grep 172 &> /dev/null" interval 1 weight -10
}
vrrp_instance VI_1 {state BACKUPinterface eno16777736virtual_router_id 100priority 99advert_int 1authentication { auth_type PASS auth_pass 99999999}virtual_ipaddress { 172.16.36.100/16 dev eno16777736 label eno16777736:1}notify_master "/etc/keepalived/keepalived.sh master"notify_bakcup "/etc/keepalived/keepalived.sh backup"notify_fault "/etc/keepalived/keepalived.sh fault"track_script { chk_down chk_nginx}
}
~]# vim /etc/keepalived/keepalived.sh
#!/bin/bash
#author :Magedu
#Description : an example of notify script
contact=’root@localhost’
notify() {mailsubject="$(hostname) to be $1:vip floating"mailbody="$(date +'%F %H:%M:%S'): vrrp transition,$(hostname) change to be $1"echo $mailbody | mail -s "$mailsubject" $contact
case $1 in
master)notify mastersystemctl start nginx.serviceexit 0;;
backup)
notify backupsystemctl restart nginx.serviceexit 0;;
fault)
notify faultsystemctl stop nginx.serviceexit 0;;
*)
echo "Usage: $(basename $0) {master|backup|fault}"exit;;
esac
转自:微信公众号-运维部落