Keepalived起初是为LVS设计的,专门用来监控集群系统中各个服务节点的状态。它根据TCP/IP参考模型的第三、第四和第五层交换机机制检测每个服务节点的状态,如果某个服务节点出现异常,或工作出现故障后,keepalived将检测到,并将出现故障的服务节点从集群系统中剔除,而在故障节点恢复正常后,keepalived又可以自动将此服务节点重新加入服务器集群中,这些工作全部自动完成,不需要人工干涉,需要人工完成的只是修复出现故障的服务节点。
keepalived后来又加入了VRRP的功能,VRRP(Virtual Router Redundancy Protocol,虚拟路由器冗余协议)出现的目的是解决静态路由出现的单点故障问题,通过VRRP协议可以实现网络不间断稳定运行。因此,keepalived一方面具有服务器状态监测和故障隔离功能,另一方面也具有HA cluster功能。下面详细介绍VRRP协议的实现过程。
1.1 VRRP协议与工作原理
在现实的网络环境中,主机之间的通信(寻址)都是通过配置静态路由(默认网关)完成的,而主机之间的路由器一旦出现故障,通信就会失败,因此,在这种通信模式中,路由器就成了一个单点瓶颈,为了解决这个问题,就引入了VRRP协议。
熟悉网络的同学对VRRP协议应该不陌生,它是一种主备模式的协议,通过VRRP可以在网络发生故障时透明地进行设备切换而不影响主机间的数据通信,这其中涉及两个概念:物理路由器和虚拟路由器
VRRP可以将两台或多台物理路由器设备虚拟成一个虚拟路由器,这个虚拟路由器通过虚拟IP(一个或多个)对外提供服务,而在虚拟路由器内部是多个物理路由器协同工作,同一时间只有一台物理路由器对外提供服务,这台物理路由器被称为主路由器(处于MASTER角色)。一般情况下master由选举算法产生,它拥有对外服务的虚拟IP,提供各种网络功能,如ARP请求、ICMP、数据转发等。而其他物理路由器并不拥有对外的虚拟IP,也不能提供对外网络功能,仅仅接收master的VRRP状态通告信息,这些路由器被统称为备份路由器(处于BACKUP角色)。当主路由器失效时,处于backup角色的备份路由器将重新进行选举,产生一个新的主路由器进入master角色继续提供对外服务,整个过程对用户来说是完全透明的。
每个虚拟路由器都有一个唯一标识,称为VRID,一个VRID与一组IP地址构成了一个虚拟路由器。在VRRP协议中,所有的报文都是通过IP多播形式发送的,而在一个虚拟路由器中,只有处于master角色的路由器会一直发送VRRP数据包,处于backup角色的路由器只接收master发送过来的报文信息,用来监控master运行状态,因此,不会发生backup抢占的现象,除非它的优先级更高。而当master不可用时,backup也就无法收到master发送过来的报文信息,于是就认定master出现故障,接着多台backup就会进行选举,优先级最高的backup将成为新的master,这种选举并进行角色 切换的过程非常快,因而保证了服务的持续可用性。
1.2 keepalived工作原理
上面介绍了keepalived通过VRRP协议实现高可用功能的工作原理,而keepalived作为一个高性能的集群软件,它还能实现对集群中服务器运行状态的监控及故障隔离。下面继续介绍下keepalived对服务器运行状态监控和检测的工作原理。
keepalived工作在TCP/IP参考模型的第三、第四和第五层,也就是网络层、传输层、应用层。根据TCP/IP参考模型各层功能实现的功能,keepalived运行机制如下:
在网络层,运行着4个重要的协议:互联网协议IP、互联网控制报文协议ICMP、地址转换协议ARP以及反向地址转换协议RARP。keepalived在网络层采用的最常见的工作方式是通过ICMP协议向服务器集群中的每个节点发送一个ICMP的数据包(类似于ping实现的功能),如果某个节点没有返回响应数据包,那么认为此节点发生故障,keepalived将报告此节点失效,并从服务器集群中剔除故障节点。
在传输层,提供了两个主要的协议:传输控制协议TCP和用户数据协议UDP。传输控制协议TCP可以提供可靠的数据传输服务、IP地址和端口,代表TCP的一个连接端。要获得TCP服务,需要在发送机的一个端口上和接收机的一个端口上建立连接,而keepalived在传输层就是利用TCP协议的端口连接和扫描技术来判断集群节点是否正常的。比如,对于常见的web服务默认的80端口、ssh服务默认的22端口等,当keepalived一旦在传输层探测到这些端口没有响应数据返回,就认为这些端口发生异常,然后强制将此端口对应的节点从服务器集群中剔除。
在应用层,可以运行FTP、TELNET、SMTP、DNS等各种不同类型的高层协议,keepalived的运行方式也更加安全化和复杂化,用户可以通过自定义keepalived的工作方式,例如,用户可以通过编写程序来运行keepalived,而keepalived将根据用户的设定检测各种程序或服务是否运行正常,如果keepalived的检测结果与用户设定不一致时,keepalived将把对应的服务从服务器中剔除。
1.3 keepalived的体系结构
keepalived是一个高度模块化的软件,结构简单。但扩展性强,如下图是官方给出的keepalived体系结构拓扑图。
从图中可以看出,keepalived的体系结构从整体上分为两层,分别是用户空间层(User Space)和内核空间层(Kernel Space)。下面介绍keepalived两层结构的详细组成及实现的功能。
内核空间处于最底层,它包括IPVS和NETLINK两个模块。IPVS模块是keepalived引入的第一个第三方模块,通过IPVS可以实现基于IP的负载均衡集群。IPVS默认包含在LVS软件中。在LVS集群中,IPVS安装在一台叫做Director Server的服务器上。同时在Director Server上虚拟出一个IP地址对外提供服务,而用户必须通过这个虚拟IP地址才能访问服务。这个虚拟IP一般被称为LVS的VIP,即Virtual IP。访问的请求首先经过VIP到达Director Server,然后由Director Server从服务器集群节点中选取一个服务节点响应用户的请求。
keepalived最初就是为LVS提供服务的,由于keepalived可以实现对集群节点的状态监测,而IPVS可以实现负载均衡功能,因此,keepalived借助于第三方模块IPVS就可以很方便的搭建一套负载均衡系统。这这里有个误区,由于keepalived可以和IPVS一起很好的工作,因此有很多人认为keepalived就是一个负载均衡软件,这种理解是错误的。
在keepalived中,IPVS模块是可配置的,如果需要负载均衡功能,可以在编译keepalived时打开负载均衡功能,也可以通过配置编译参数关闭。
注:大多数情况下我们使用LVS或nginx或haproxy来实现负载均衡功能,用keepalived来实现高可用(通过VRRP)和后端服务健康监测功能。
NETLIN模块主要用于实现一些高级路由框架和一些相关的网络功能,完成用户空间层Netlink Reflector模块发来的各种网络请求。
用户空间层位于内核空间层之上,keepalived的所有具体功能都在这里实现,下面介绍下几个重要部分所实现的功能。
在用户空间层,keepalived又分为4个部分,分别是Scheduler I/O Multiplexer、Memory Management、Control Plane和 Core components。其中,Scheduler I/O Multiplexer是一个I/O复用分发调度器,它负责安排keepalived所有内部的任务请求。Memory Management是一个内存管理机制,这个框架提供了访问内存的一些通用方法。Control Plane是keepalived的控制面板,可以实现对配置文件进行编译和解析,keepalived的配置文件解析比较特殊,它并不是一次解析所有模块的配置,而是只有在用到某个模块时才解析相应的配置。最后详细说一下Core components,这部分是keepalived的核心组件,包含了一系列的功能模块,主要有WatchDog、Checkers、VRRP Stack、IPVS wrapper和Netlink Reflector,下面介绍每个模块所实现的功能如下。
WatchDog
WatchDog是计算机可靠性领域中一个极为简单又非常有效的检测工具,它的工作原理是针对被监视的目标设置一个计数器和一个阈值,WatchDog会自己增加此计数值,然后等待被监视的目标周期性的重置该计数值。一旦被监控目标发生错误,就无法重置此计数值,WatchDog就会检测到,于是采取对应的恢复措施,例如关闭或重启。Checkers
这是keepalived最基础的功能,也是最主要的功能,可实现对服务器运行状态监测和故障隔离。VRRP Stack
这是keepalived后来引入的VRRP功能,可以实现HA集群中失败切换(Failover)功能。keepalived通过VRRP功能再结合LVS负载均衡软件即可部署一个高性能的高可用的负载均衡集群系统。IPVS wrapper
这是IPVS功能的一个实现。IPVS wrapper模块可以将设置好的IPVS规则发送到内核空间并提交给IPVS模块,最终实现IPVS模块的负载均衡功能。Netlink Reflector
用来实现高可用集群中Failover时虚拟IP(VIP)的设置和切换。Netlink Reflector的所有请求最后都发送到内核空间层的Netlink模块来完成。