zoukankan      html  css  js  c++  java
  • keepalive基础知识

    一、LVS负载均衡集群的缺点

    二、Keepalived介绍

    三、Keepalived的功能

    四、Keepalived工作原理

    五、Keepalived组件框架

    六、Keepalived的安装

      6.1 高可用集群配置的前提

      6.2 Keepalived配置

      6.3 Keepalived高可用其它服务

    一、LVS负载均衡集群的缺点

    在之前的一篇博客中介绍了有关LVS的工作原理,详情可参考《LVS工作原理》。LVS能够实现四层负载,能够支持足够大的并发量,但使用LVS负载均衡集群有以下两个缺点。

    ① 如果调度器(Director)挂了(不可用),将会导致整个系统不可用,从而调度器成为了单点故障(SPOF)。

    ② 调度器(Director)无法对后端RealServer做健康状态检测。因此,如果后端的某一台RealServer挂了,前端调度器将无法得知,仍然会向该RealServer调度请求,导致服务不可用;另外,如果某一台挂了的RealServer但已经恢复正常并重新提供服务时,前端调度器也无法得知,并将其加入调度队列。

    因此,为了能够使前端调度器(Director)能够冗余、使Director能够对后端各RS做健康状态检测,并按需增删RS,需要引入高可用集群的解决方案。以下介绍的是Keepalived高可用软件。

    二、Keepalived介绍

    Keepalived是VRRP协议的实现,原生设计目的是高可用IPVS服务。此外,Keepalived能够根据配置文件的规则生成IPVS规则,并能够对各RealServer的健康状态进行检测。

    Keepalived的高可用功能是通过VRRP协议实现的,VRRP是Virtual Router Redundancy Protocol(虚拟路由器冗余协议)的缩写。VRRP的出现是为了解决静态路由单点故障的问题,当某一节点出现故障时,可以防止导致整个网络不可用。Keepalived除了可以高可用LVS之外,还可以作为其他系统网络服务(Nginx、Haproxy等)的高可用解决方案(Keepalived可通过调用vrrp_script来高可用其它服务,并通过调用vrrp_track来追踪每一个服务)。

    三、Keepalived的功能

    Keepalived有三个重要功能,如下。

    (1) 高可用系统网络服务。

    Keepalived可以实现在两台或多台主机之间的故障切换转移。如果在两台主机中都安装了Keepalived,当正常工作时,有一台主机工作为Master角色,另一台主机工作为Backup角色。角色为Master的主机获得所有资源(VIP资源、服务资源)并向用户提供服务,角色为Backup的主机不提供服务而仅作为Master主机的热备。当角色为Master的主机出现故障时,角色为Backup的主机将自动接管Master主机的所有资源(VIP资源、服务资源)并开始工作。当Master主机故障修复完成时,将重新接管原来的资源和工作,而Backup主机则释放Master主机故障时它接管的资源和工作,各自恢复原来的角色。

    (2) 实现对LVS集群中各RealServer的健康状态进行检测。

    Keepalived可以通过在自身配置文件keepalived.conf中配置LVS集群服务中各台RealServer的IP地址和相关参数,并可以通过网络层、传输层和应用层这三层进行探测各RealServer的健康状态。当有一台或多台RealServer出现故障而无法提供服务时,Keepalived服务可以把出现故障的RealServer从LVS的正常转发队列中移除,保证不影响用户的访问。而当有RealServer故障修复完成时,Keepalived服务可以将其重新加入LVS的正常转发队列中,向用户提供服务。

    (3) 管理LVS负载均衡软件。

    Keepalived可以读取配置文件,并通过一个更为底层的接口来管理IPVS并生成IPVS规则,这使得LVS的使用更为方便。

    四、Keepalived工作原理

    前面提到,Keepalived的高可用功能是通过VRRP协议实现的,要了解Keepalived的工作原理,需要先了解VRRP协议的工作原理。

    4.1 VRRP工作原理

    VRRP,是Virtual Router Redundancy Protocol的缩写,中文名为虚拟路由器冗余协议。VRRP的出现是为了解决静态路由的单点故障问题,早期应用于交换机、路由器等设备中。VRRP协议是通过竞选机制来实现将路由任务交给某一台VRRP路由器的。

    在一组VRRP路由器中,可以有多台物理路由器,但只有一台称为Master的路由器负责路由任务(响应ARP请求、转发发送给网关的数据包),而其他路由器都是Backup角色。Master和Backup是通过竞选机制选举出来的,这种竞选机制是根据优先级的高低来选举,在这一组VRRP路由器中优先级最高的路由器就是Master,其他路由器为Backup。Master路由器需要基于IP组播(默认组播地址为224.0.0.18)的方式发送心跳消息给其它的Backup路由器,告诉其它路由器自己还活着,同时告知Master自己的优先级。而当Master路由器发生故障时,就没法发送心跳消息,这样Backup路由器就检测不到Master的心跳消息了,这时多台Backup路由器就会再通过同样的竞选机制,选举出优先级最高的一台作为新的Master路由器,并接管路由任务(响应ARP请求、转发发送给网关的数据包)。

    虚拟路由器由VRID(虚拟路由器标识,0-255),对外部则表现为一个VMAC(Virtual MAC)地址:00-00-5E-00-01-{VRID}和一个VIP(Virtual IP)。

    4.2 Keepalived工作原理

    Keepalived服务的高可用对之间的通信是基于VRRP协议进行通信的,VRRP是通过竞选机制来确定主、备节点的,主节点的优先级高于备节点。当Keepalived服务正常工作时,主Master节点接管IP资源和服务资源,向用户提供服务,并不断地向备Backup节点发送心跳消息(以组播的方式),用以告知备节点自己还活着,而备节点收到心跳消息后,一方面得知主节点还活着,另一方面得知主节点的优先级仍高于自己,因此不敢“犯上”。当主Master节点出现故障时,就无法发送心跳消息,所以备Backup节点就收不到主节点发来的心跳消息,这时所有备节点就会再此互相发送协议报文进行协商(再次进行竞选),各备节点将自己的优先级通告给所有其他备节点,最后优先级高的备节点则为新的主Master节点,由其调用自身的接管程序接管之前主节点的IP资源和服务资源,向用户提供服务。当先前的主Master节点故障修复完成时,则会再次接管IP资源和服务资源(如果Keepalived工作于抢占模式的话),继续向用户提供服务,而后来接管IP资源和服务资源的备Backup节点会释放接管的资源,再次成为备节点。

    导致主、备节点切换的原因不仅仅是主节点发生了故障,也有可能是主Master节点被人为降低优先级(降到比备节点还低),这时备Backup节点会发现主节点的优先级比自己还低,同样会抢占资源并成为主节点。

    前面提到,Keepalived主要由三个功能,此处介绍的原理只是其中之一,另外两个功能较为简单,其原理可以参考前面第三点。

    五、Keepalived的组件框架

    Keepalived的框架可以参考下图(图片来自Keepalived官网)。

    wKioL1mD9QrSE125AACUn7rdsas574.gif

    Keepalived的组件有控制组件(配置文件分析器)、内存管理、I/O复用和核心组件。其中,核心组件包括VRRP Stack、Checkers、IPVS wrapper、WatchDog和SMTP等,各部分功能如下。

    VRRP Stack ==> 是VRRP协议的实现,能够实现Keepalived的高可用性。

    Checkers ==> 能够基于网络层(IP)、传输层(TCP)、应用层(HTTP、SSL等)对RealServer进行健康状态检查。

    IPVS Checkers ==> 根据配置文件生成IPVS规则并送往IPVS使之生效。

    WatchDog ==> 用于监控VRRP Stack和Checkers这两个Keepalived关键组件是否正常工作。

    SMTP ==> 是一个SMTP接口,主要用于当VRRP Stack中发生地址流动时,或者当Checkers发现服务上下线并增删服务节点时,能够以邮件方式通知管理员。

    六、Keepalived的安装

    对于CentOS 6.4+的系统版本,Keepalived程序包已经在base源提供。在CentOS 7.x上使用yum工具安装如下:

    # yum -y install keepalived
     

    6.1 高可用集群配置的前提

    ① 确保各节点时间同步 ==> 基于NTP协议或Chrony协议

    ② 确保iptables和selinux不会阻碍

    ③ 各节点之间可通过主机名互相通信(对Keepalived并非必须) ==> 名称解析服务的解析结果必须与"uname -n"命令的执行结果相同。

    ④ 各节点之间的root用户可以基于密钥认证的SSH进行通信(对Keepalived并非必须)

    6.2 Keepalived配置

    主配置文件 ==> /etc/keepalived/keepalived.conf

    Unit File ==> /usr/lib/systemd/system/keepalived.service

    Unit File的配置文件 ==> /etc/sysconfig/keepalived

    Keepalived配置内容块:

    GLOBAL CONFIGURATION(全局配置)

    VRRPD CONFIGURATION(VRRP配置)

    LVS CONFIGURATION(LVS配置)

    (1) GLOBAL CONFIGURATION(全局配置)

    全局配置框架:

    global_defs {
        ...
    }
     

    常用配置:

    global_defs {
        notification_email        # 邮件通告的收件人(如果有多个收件人须用花括号'{}'括起来)
            {
            admin@example1.com    # postfix服务只能由本机用户发给本机用户
            ...                   # 如果要发送给其它主机上的用户可借助于有提供smtp服务的主机,
            }                       但一般smtp服务器需要申请有互联网的公网IP地址
        notification_email_from admin@example.com    # 邮件通告的发送人
        smtp_server 127.0.0.1     # smtp服务器的IP地址。如果是向外提供服务的smtp服务器,则需要
                                    支持正反解
        smtp_connect_timeout 30   # 发送邮件的超时时长
        router_id my_hostname     # 定义当前路由器设备的ID号(不一定要使用主机名)
        vrrp_mcast_group4 224.0.0.18    # 基于VRRP协议的多个虚拟路由器使用的组播地址
                                          group4表示使用ipv4格式地址
    }
     

    全局配置示例:

    global_defs {
       notification_email {
            root@localhost
       }
       notification_email_from kaadmin@itab.com
       smtp_server 127.0.0.1
       smtp_connect_timeout 30
       router_id node1
       vrrp_mcast_group4 224.0.100.18
    }
     

    (2) VRRPD CONFIGURATION(VRRP配置)

    虚拟路由配置框架:

    vrrp_sync_group GRP_NAME {    # 规定所有的虚拟路由器的主Master节点都必须在同一台主机上
        ...
    }
    vrrp_instance INST_NAME {     # 配置虚拟路由器实例,可配置多个实例
        ...
    }
     

    常用配置:

    vrrp_instance <string> {     # 配置虚拟路由器实例
        state MASTER | BACKUP    # 当前节点在此虚拟路由器中的初始状态
        interface ETHERCARD      # VRRP实例工作(绑定)的网络接口
        virtual_router_id 51     # 虚拟路由器ID,范围是0-255
        priority 100             # 当前物理节点在此虚拟路由器中的优先级
        advert_int #             # VRRP通告的时间间隔
        
        authentication {         # 认证机制
            # PASS||AH
            # PASS - Simple Passwd (suggested)
            # AH - IPSEC (not recommended))
            auth_type PASS       # 认证类型,推荐使用简单字符串认证(PASS类型)
            # Password for accessing vrrpd.
            # should be the same for all machines.
            # Only the first eight (8) characters are used. ==> 以下认证密码仅前8位字符有效
            auth_pass 1234       # 认证密码(建议使用随机数作为认证密码)
        }
        
        virtual_ipaddress {      # 定义虚拟IP
            <IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPE> label <LABEL>
            192.168.200.17/24 dev eth1
            192.168.200.18/24 dev eth2 label eth2:1
            192.168.200.18/32
        }
        
        track_interface {        # 定义要监控的接口
            eth0
            eth1
            ...
        }
        
        nopreempt                # 工作于非抢占模式(不指定时默认为抢占模式),如果两台路由器
                                   性能相差不大时可以考虑工作于非抢占模式
        preempt_delay 300        # 工作于抢占模式时,设定再次上线的节点(原来为主Master节点)
                                   应该延迟多长时间再抢占
        
        # 通告脚本定义
        notify_master <STRING>|<QUOTED-STRING>    # 当前节点变成主Master节点时使用的通告脚本
        notify_backup <STRING>|<QUOTED-STRING>    # 当前节点变成备Backup节点时使用的通告脚本
        notify_fault <STRING>|<QUOTED-STRING>     # 当前节点故障时使用的通告脚本
        notify <STRING>|<QUOTED-STRING>           # 以上无论哪一个状态发生变化,都使用的通告脚本
    }
     

    虚拟路由器实例配置示例:

    vrrp_instance VI_1 {
        state MASTER
        interface ens33
        virtual_router_id 6
        priority 100
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass 5FfZnxFm
        }   
        virtual_ipaddress {
            192.168.100.66    # VIP地址
        }
        notify_master "/etc/keepalived/notify.sh master"    # 注意要使用双引号
        notify_backup "/etc/keepalived/notify.sh backup"
        notify_fault "/etc/keepalived/notify.sh fault"
    }
     

    通知脚本示例:

    # vim /etc/keepalived/notify.sh 
    
    #!/bin/bash
    #
    contact='root@localhost'
    
    notify() {
        mailsubject="$(hostname) to be $1: vip floating"
        mailbody="$(date +'%F %T'): vrrp transition, $(hostname) change to be $1"
        echo $mailbody | mail -s "$mailsubject" $contact
    }
    
    case $1 in
    master)
        notify master
        ;;
    backup)
        notify backup
        ;;
    fault)
        notify fault
        ;;
    *)
        echo "Usage: $(basename $0) {master|backup|fault}"
        ;;
    esac
     

    注意:通告脚本需要有执行权限。

    # chmod +x /etc/keepalived/notify.sh
     

    (3) LVS CONFIGURATION(LVS配置)

    LVS集群配置框架:

    virtual_server_group VSG_NAME {
        ...
    }
    virtual_server IP port | 
    virtual_server fwmark int {
        protocol TCP
    	...
        real_server <IPADDR> <PORT> {
            ...
        }
        real_server <IPADDR> <PORT> {
            ...
        }
        ...		
    }
     

    常用配置:

    virtual_server IP port |        #==> 通过请求报文的目标IP和目标PORT定义集群服务
    virtual_server fwmark # {       #==> 通过防火墙标记定义集群服务
        lb_algo rr|wrr|lc|wlc|lblc|sh|dh    # 定义负载均衡调度算法
        delay_loop <INT>            # 定义服务轮询时间间隔,即对后端服务的检测时间间隔
        lb_kind NAT|DR|TUN          # 集群的类型
        persistence_timeout <INT>   # 持久连接时长
        protocol TCP                # 服务协议
        virtualhost <STRING>        # 当后端Web服务器上有多台虚拟主机时,可使用此项来指明要检测
                                      的虚拟主机(带上Host首部)。否则,则只向RIP发出请求,并只
                                      由后端Web服务器上的默认虚拟主机响应
        sorry_server <IPADDR> <PORT>     # 所有RS均故障时,提供say sorry的服务器
        real_server <IPADDR> <PORT> {    # 定义RS
            weight <INT>                 # 权重
            notify_up <STRING>|<QUOTED-STRING>        # 节点上线时调用的通知脚本
            notify_down <STRING>|<QUOTED-STRING>      # 节点离线时调用的通知脚本
            # HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK
            # 支持所有的健康状态检测方式
            
            HTTP_GET|SSL_GET {
                url {
                    path <STRING>            # 健康状态检测时请求的资源的URL
                    digest <STRING>          # 基于获取的内容摘要码进行健康状态判定
                    status_code <INT>        # 基于要求返回的状态码进行健康状态判定
                }
                nb_get_retry <INT>           # 尝试的次数
                delay_before_retry <INT>     # 两次尝试之间的时间间隔
                connect_timeout <INTEGER>    # 连接的超时时长
                connect_ip <IP ADDRESS>      # 向此处指定的地址发测试请求(不指定时则向此前指定的RIP发测试请求)
                connect_port <PORT>          # 项此处指定的PORT发测试请求(不指定时则向此前指定的RS的PORT发测试请求)
                bindto <IP ADDRESS>          # 指定测试请求报文的源IP
                bind_port <PORT>             # 指定测试请求报文的源PORT
            }
            TCP_CHECK {
                # 除了不能定义url,其它的配置同HTTP_GET|SSL_GET
            }
        }
    }
     

    LVS集群配置示例:

    virtual_server 192.168.10.7 80 {
        delay_loop 6
        lb_algo rr
        lb_kind DR
        persistence_timeout 50
        protocol TCP
        sorry_server 127.0.0.1 80
    
        real_server 192.168.10.11 80 {
            weight 1
            HTTP_GET {
                url {
                  path /
                  status_code 200
                }
                connect_timeout 3
                nb_get_retry 3
                delay_before_retry 3
            }
        }
        real_server 192.168.10.12 80 {
            weight 1
            HTTP_GET {
                url {
                  path /
                  status_code 200
                }
                connect_timeout 3
                nb_get_retry 3
                delay_before_retry 3
            }
        }
    }
     

    6.2 Keepalived高可用其它服务

    (1) vrrp_script、track_script

    vrrp_script ==> 用于自定义一个资源(或服务)监控脚本;vrrp实例能够将脚本的状态返回值作为判断一个资源(或服务)是否可用的依据。需要公共定义,可被多个vrrp实例调用,因此要定义在vrrp实例之外。

    track_script ==> 用于调用vrrp_script定义的脚本去监控资源(或服务),并能够在监控过程中,一旦发现脚本状态返回值为成功时,则使节点的优先级不变或升高,当发现脚本状态返回值为是失败时,则使节点的优先级降低。而当前节点就可以通过向外通告自身优先级来完成节点角色(主或备)的切换。

    (2) 使用示例1 ==> 当检测到/etc/keepalived/down文件存在时,则进行地址漂移

    vrrp_script chk_down {
        script "[[ -f /etc/keepalived/down ]] && exit 1 || exit 0"
        # 当检测到down文件存在时(成功),定义为失败(状态码为1);而将检测不到down文件存在时(失败),反而定义为成功(状态码为0)
        interval 2    # 每隔2秒执行脚本检测一次
        weight -5	  # 一旦脚本运行失败,则执行该项(将优先级降低5)
    }
    
    vrrp_instance INST_NAME {
        ...
        track_script {
            chk_down    # 调用已定义的vrrp_script
        }
        ...
    }
     

    (3) 使用示例2 ==> 监控具体的服务进程

    vrrp_script chk_httpd {
        script "killall -0 httpd"    # 当httpd进程运行不正常时,则脚本运行失败(状态码为1);
                                       当httpd进程运行正常时,则脚本运行成功(状态码为0)
        interval 2
        weight -5     # 一旦脚本运行失败,则执行该项(将优先级降低5)
    }
    
    vrrp_instance VI_1 {
        ...
        track_script {
            chk_httpd
        }
        ...
    }
     

    注意:

    (1) killall命令使用-0选项时只起探测作用,不会真正杀死进程。

    (2) 调用的脚本中使用的命令必须为已经安装的命令。本示例中的vrrp脚本只有在主机上必须有killall命令时才能执行,如果没有killall命令,则可使用yum安装psmisc。

    问题:如何改进该脚本?

    vrrp_script所实现的监控功能应该更为完整,例如可以在检测不到资源(或服务)时,不要立即调低优先级,而先尝试重启服务,并规定尝试几次,两次尝试之间的时间间隔。当然,在vrrp_script中所实现的功能也可由前面所提到的通告脚本来实现,也就是可以将前面的通告脚本示例再改进一下。改进后的脚本如下。

    #!/bin/bash
    #
    contact='root@localhost'
    
    notify() {
    	mailsubject="$(hostname) to be $1: vip floating"
    	mailbody="$(date +'%F %T'): vrrp transition, $(hostname) change to be $1"
    	echo $mailbody | mail -s "$mailsubject" $contact
    }
    
    case $1 in
    master)
    	notify master
    	systemctl start httpd.service      # 保证服务是启动的
    	;;
    backup)
    	notify backup
    	systemctl restart httpd.service    # 当切换为备节点时,重启一次服务
    	;;
    fault)
    	notify fault
    	systemctl restart httpd.service    # 当节点发生错误时,重启一次服务
    	;;
    *)
    	echo "Usage: $(basename $0) {master|backup|fault}"
    	;;
    esac
  • 相关阅读:
    LoadRunner参数化&关联
    面试题
    Python---Pycharm如何直接上传自己的代码到GitHub
    深入详解美团点评CAT跨语言服务监控(九)CAT管理平台MVC框架
    深入详解美团点评CAT跨语言服务监控(八)报表持久化
    深入详解美团点评CAT跨语言服务监控(七)消息分析器与报表(二)
    深入详解美团点评CAT跨语言服务监控(六)消息分析器与报表(一)
    深入详解美团点评CAT跨语言服务监控(五)配置与数据库操作
    深入详解美团点评CAT跨语言服务监控(四)服务端消息分发
    深入详解美团点评CAT跨语言服务监控(三)CAT客户端原理
  • 原文地址:https://www.cnblogs.com/soymilk2019/p/11053002.html
Copyright © 2011-2022 走看看