在上一篇博客中部署了基于lvs-dr的集群,并且使用了共享存储,但是在日常的使用中限制一个集群的瓶颈是调度器,调度器的工作效率直接影响到集群的工作效率,而且如果调度器损坏了,那么集群就瘫痪了,所以我们要保证调度器一直在工作。lvs本身是不支持的,所以我们需要其他的软件来协同管理。能够完成这种功能的软件有很多,例如:heartbeat/corosync,是通用解决方案,但是仅仅可以实现Director高可用,后端服务器也有损坏的可能,当后端服务器损坏的时候,调度器应该删掉这台服务器,等其恢复,再加载回来,然而这种解决方案是不管的;还有一种,也就是今天要说的,即:keepalived,lvs的Director高可用 + lvs的RS的健康检测,这个软件能够实现的功能是对调度器进行冗余,当当前正在工作的调度器挂掉之后,立马用备用调度器顶上;而且还会对后端RS服务器进行健康检查,当发现后端服务器无法检测到的时候就将其从lvs服务中移除。下面开始介绍并使用keepalived。

一、VRRP协议

    说keepalived要从高可用说起,系统可用性的计算公式是A=(MTTF/(MTTF+MTTR))*100%,A就是可用性指标,取值在0到1之间,MTTF为平均无故障时间 ,MTTR为平均故障修复时间。在这个公式中,所得A值越大越好,但是提高平均无故障时间总会有一个上限,所以提高可用性的比较有效的方法就是降低MTTR,也就是降低平均故障修复时间,而为了达成这个目的最好的方法就是使用冗余,从而就诞生了相关的协议,有两种,第一种是HSRP,叫做热备份路由器协议,为思科私有,还有一种是VRRP,叫做虚拟冗余路由器协议,是开放的。所以下面会说这个开放的协议,即VRRP:

VRRP协议:Virtual Redundant Router/Routing Protocol,虚拟冗余路由(器)协议
技术术语:
    虚拟路由器:虚拟路由器接口
    VRID:虚拟路由器标识符,描述路由器的分组情况;确定该分组的虚拟MAC地址
    MASTER:虚拟IP地址的拥有者,能够完成数据转发功能的路由器
    BACKUP:不参与数据转发,检测MASTER的健康状态
    VIP:虚拟IP地址,虚拟路由器的IP地址;拥有VIP的就是Master
    VMAC:00-00-5E-00-01-{VRID}
    优先级:选举称为MASTER的主要参考标准,取值范围是0-255
        0:放弃Master选举(只要有一个Master服务器,就不参与竞选)
        255:虚拟IP地址拥有者的优先级
        1-254:越大越有可能成为MASTER
    抢占式:如果MASTER状态为,则BACKUP中会重新选举新的MASTER,此时如果原来MASTER恢复,就立即发起新的选举,成为MASTER
    非抢占式:如果MASTER状态为down,则BACKUP中会重新选举新的MASTER,此时如果原来MASTER恢复,就自动成为BACKUP,直到MASTER状态为down时,重新选举才会成为新的MASTER
VRRP的工作模式:
    单实例:MASTER/BACKUP
    多实例:MASTER/BACKUP、MASTER/MASTER
VRRP的认证方式:
    无认证
    简单字符串
    MD5

集群高可用—keepalived_第1张图片

    如上图所示,虚拟路由器的功能就是承载一个IP,所有的内部网络主机网关均指向这个IP,然后这个IP可以设置到两个真实存在的路由器上,但是每一个时刻,只能有一个路由器使用这个IP,比如当Master使用时,Backup就是自己的IP。这样部署完成之后,首先MASTER进行工作,使用虚拟路由器的IP地址,BACKUP对MASTER进行监控,一旦发现Master停止工作了,就将自己作为工作的路由器,并设置自己的IP为虚拟路由器的IP开始接替MASTER工作,这样就实现了路由器的高可用,即使坏了一个,另外一个也会及时补上,不会出现网络不可访问的情况。

    上面的例子是单实例,即每一时刻仅仅有一台路由器在工作,这就大大浪费了资源,所以就有了多实例,即存在两个虚拟路由器,分别有不同的虚拟IP地址,根据这两个不同的IP地址对应两个不同的实例,在一个实例中为MASTER的路由器在另一个实例中就为BACKUP。

     在说完实例之后,还有一个需要我们了解,那就是如何确定哪一个为MASTER。于是就有了优先级,根据每一台路由器设置的不同优先级,就可以确定谁为MASTER,谁为故障之后为MASTER了。而当一台路由器故障并恢复之后,也可以通过优先级来进行重新选举,选出新的MASTER,如果设置为抢占式,就立刻发起选举,如果设置为非抢占式,就默默的成为BACKUP。选举的意思是向所有路由器发送数据包,进行优先级比对,优先级高的获取MASTER。

二、环境配置

    虽然VRRP是针对路由器所设计的协议,但是我们也可以将其拿过来放到调度器上进行使用, keepalived 是VRRP协议在Linux中的软件实现,最初设计的目的就是为了高可用ipvs服务,在某些场合可能简称为:ka。keepalived可以为VIP所在的节点通过ipvs的系统调用,自动生成ipvs规则;所有的这些都是定义在 keepalived配置文件中,keepalived还可以为各RS进行健康状态检测,keepalived可以基于脚本调用接口通过执行脚本完成脚本中所定义的功能。下面开始说keepalived的使用,但是在使用之前,我们要注意以下几点:

1.各个节点之间时间必须同步;如有必要可以使用时间服务器(ntp或者chrony(CentOS 7))

2.各个节点之间可以通过主机名互相通信(对于ka并非必须)(修改hosts或构建DNS)

3.确保iptables和SELinux不会阻碍各个节点之间的数据通信

4.为了安全考虑,各个节点之间的root用户可以基于密钥认证的ssh互相通信(对于ka并非必须)


   然后基于上一次博客中的实验——lvs-nat的架构方式构建这次试验环境,如图所示:

集群高可用—keepalived_第2张图片

    总共需要五台主机(MySQL可以不要,或者将其作为验证功能的主机),在新加入的一个调度器上进行配置,将其配置成一台可以使用的调度器,并验证其功能可以实现(记得删除已经存在的调度器的配置):

    参考前头的博客:http://11142243.blog.51cto.com/11132243/1974868

集群高可用—keepalived_第3张图片

集群高可用—keepalived_第4张图片

    在验证之后我们就可以使用命令来将规则清除了,因为keepalived会自动添加规则的:

~]# ipvsadm -C

    但是,这几台服务器的时间不一样,所以我们可以先构建一个时间服务器,然后在别的主机上通过命令来于这台服务器进行时间同步:

        首先在一台CentOS 7(CentOS 6总是报错)服务器中ntpd的配置文件“/etc/ntp.conf”中添加两行:

restrict 172.16.0.0 mask 255.255.0.0 nomodify    #这是允许哪个网段的主机进行时间同步
servcer 127.127.1.0 iburst                       #这是让这台服务器与自己进行时间同步

        然后在时间服务器上启动时间服务:

~]# systemctl start ntpd

        最后使用Xshell的向所有shell会话同时发送命令的功能同步时间(一个一个输命令也可以):

~]# ntpdate 172.16.7.100      #172.16.7.100是作为时间服务器的主机

            这样,所有服务器的时间都已同步,并且实验环境也已经配置好了。

三、keepalived

    使用命令分别在两台调度器上安装keepalived程序包:

~]# yum -y install keepalived

    安装完成之后就会产生主配置文件“/etc/keepalived/keepalived.conf”,配置文件中的大致内容如下:

#GLOBAL CONFIGURATION
Global definitions
        global_defs
        {
            notification_email  
              {
                root@localhost  //接收通知的邮件地址;
              }
            notification_email_from keepalived@localhost //通知邮件的发件人地址;
            smtp_server 127.0.0.1 //邮件服务器地址;
            router_id drct1 //设置路由器ID,仅为了区别不同设备而已;如不修改不影响服务;
            vrrp_mcast_group4 224.100.100.18 //发送vrrp通告的目的IPv4组播地址;
        }
        
#VRRPD CONFIGURATION
    VRRP synchronization group(s)
    VRRP instance(s)

    vrrp_instance inside_network {  //定义vrrp示例及示例名称;
        state MASTER //指定当前设备的vrrp状态;
        interface eno16777736 //被vrrp协议绑定的网络接口,即通过哪个接口发送vrrp通告;
        virtual_router_id 51  //虚拟路由器ID,用于确定vrrp组;
        priority 100  //指定当前节点的优先级,1-254之间整数,数字越大越有可能称为MASTER;
        advert_int 1  //发送vrrp通告的时间间隔;
        authentication {
          auth_type PASS  //设置验证方式为简单密码验证;
          auth_pass Hudlnej7  //设置验证密码,不超过8个字符长度;
        }
        virtual_ipaddress {
          172.16.72.101/32 brd 172.16.72.101 dev eno16777736 label eno16777736:0
             //指定虚拟IP地址及其配置的位置;
        }
        nopreempt //设定当前节点为非抢占模式;
        preempt_delay 300 //抢占开始前的延迟时间;
        notify_master |
        notify_backup |
        notify_fault |
        //设置发生状态改变时,所触发的脚本文件路径及相关参数;
}

    配置示例:

172.16.128.12中的“/etc/keepalived/keepalived.conf”:

! Configuration File for keepalived

global_defs {
   notification_email {
        [email protected]            #邮箱随便写
   }
   notification_email_from [email protected]
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id drct2                    #调度器标记,随便写
   vrrp_mcast_group4 224.200.100.18
}

vrrp_instance VI_1 {
    state BACKUP                  #指定这个调度器的身份,在同一个实例中只能有一个MASTER
    interface eth0                #指定接口
    virtual_router_id 51          #这个数值要和另外一台调度器保持一致,不同的数字表示不同的实例组
    priority 80                   #这个数值备份的调度器要比主调度器小
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass qwer1234        #密码八位即可,随便设
    }
    virtual_ipaddress {
        172.16.128.128/32 brd 172.16.128.128 dev eth0 label eth0:0    #虚拟调度器IP
    }
}

172.16.128.17中的“/etc/keepalived/keepalived.conf”:

! Configuration File for keepalived

global_defs {
   notification_email {
        [email protected]
   }
   notification_email_from [email protected]
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id drct1
   vrrp_mcast_group4 224.200.100.18
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass qwer1234
    }
    virtual_ipaddress {
        172.16.128.128/32 brd 172.16.128.128 dev eth0 label eth0:0
    }
}

    在上面的配置文件修改完成之后,重启keepalived服务,然后使用下面的命令即可看到keepalived的输出信息(如果是CentOS 7可以直接通过systemctl命令的status选项查看):

~]# watch -n 0.2 tail -20 /var/log/messages

集群高可用—keepalived_第5张图片

     然后我们先在作为备用调度器的172.16.128.17上启动服务,再在主调度器上启动服务,就会发现,备用调度器首先开始调度,然后当其发现了主调度其开始工作之后,就将位置让给了它:

集群高可用—keepalived_第6张图片

    而且我们还可以通过“ifconfig”命令来查看,当备份调度器启动时,能够看到出现了IP为172.16.128.128的eth0:0,而当主调度器启动时,它的这个接口就被移除了:

集群高可用—keepalived_第7张图片

集群高可用—keepalived_第8张图片

集群高可用—keepalived_第9张图片

    当我们使用一台测试主机,IP为:172.16.128.16来ping调度器时,也可以保持无缝衔接:

集群高可用—keepalived_第10张图片

    到了这一步,就说明单实例的高可用已经部署成功了,但是这样的配置会造成一台调度器一直在等另外一台调度器的情况,这就是极大的资源浪费,所以我们最好配置成多实例的高可用,即两个实例使用两个虚拟接口,在一个实例中为MASTER的调度器在另外一个实例中为BACKUP,这样,两个调度器就可以同时工作。配置的方法和配置单实例相似,示例配置如下(原来的可以保持不变,变动的是后面再加上一个实例,需要改动的我已经在示例中标注出来了):


172.16.128.12中的“/etc/keepalived/keepalived.conf”:

! Configuration File for keepalived

global_defs {
   notification_email {
        [email protected]         
   }
   notification_email_from [email protected]
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id drct2                  
   vrrp_mcast_group4 224.200.100.18
}

vrrp_instance VI_1 {
    state BACKUP              
    interface eth0               
    virtual_router_id 51         
    priority 80
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass qwer1234        
    }
    virtual_ipaddress {
        172.16.128.128/32 brd 172.16.128.128 dev eth0 label eth0:0    
    }
}
    
vrrp_instance VI_2 {
    state MASTER                  #改这里
    interface eth0               
    virtual_router_id 52           #改这里   
    priority 100                   #改这里  
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass qwer1234        
    }
    virtual_ipaddress {
        172.16.128.129/32 brd 172.16.128.129 dev eth0 label eth0:1    #改这里
    }
}

172.16.128.17中的“/etc/keepalived/keepalived.conf”:

! Configuration File for keepalived

global_defs {
   notification_email {
        [email protected]
   }
   notification_email_from [email protected]
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id drct1
   vrrp_mcast_group4 224.200.100.18
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass qwer1234
    }
    virtual_ipaddress {
        172.16.128.128/32 brd 172.16.128.128 dev eth0 label eth0:0
    }
}

vrrp_instance VI_2 {
    state BACKUP                    #改这里
    interface eth0
    virtual_router_id 52            #改这里
    priority 80                     #改这里
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass qwer1234
    }
    virtual_ipaddress {
        172.16.128.129/32 brd 172.16.128.129 dev eth0 label eth0:1       #该这里
    }
}

     此时,分别在两台调度器上使用“ifconfig”命令即可看到两台调度器各持有一个IP:

集群高可用—keepalived_第11张图片

    而当有一台调度器发生故障时,另一台调度器会同时持有两个IP:

集群高可用—keepalived_第12张图片

    下面开始配置RS,还是在刚才的配置文件中,在最底下加上下面这个示例(两个调度器都一样):

virtual_server 172.16.128.128 80 {
    delay_loop 6
    lb_algo rr
    lb_kind DR
    nat_mask 255.255.0.0
    protocol TCP
    sorry_server 127.0.0.1 80
    real_server 172.16.128.18 80 {
        weight 1
        HTTP_GET {
            url {
              path /index.html
              status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }
    real_server 172.16.128.19 80 {
        weight 2
        HTTP_GET {
            url {
              path /index.html
              status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }
}

    然后保存退出,再次使用“ifconfig”命令,可以发现此时172.16.128.12所在调度器正在工作,持有172.16.128.128IP,而且再使用“ipvsadm -ln”命令还可以看到自动生成了调度规则:

集群高可用—keepalived_第13张图片

    此时我们将在172.16.128.12的keepalived服务关闭来模拟调度器挂掉,即可发现,172.16.128.17调度器及时的接过了工作,并继续提供服务:

集群高可用—keepalived_第14张图片

    当我们在后台关闭一个网页服务器来模拟网页服务器发生故障的时候,keepalived也会及时的将其从调度规则中去除:

集群高可用—keepalived_第15张图片

    此时,我们仅仅只能对172.16.128.128进行,要想把172.16.128.129也加进来需要更改调度器的配置文件,把上面提到的对服务器的配置复制一份改成172.16.128.129,然后在网页服务器上添加对172.16.128.129的支持:

virtual_server 172.16.128.129 80 {
    delay_loop 6
    lb_algo rr
    lb_kind DR
    nat_mask 255.255.0.0
    protocol TCP
    sorry_server 127.0.0.1 80
    real_server 172.16.128.18 80 {
        weight 1
        HTTP_GET {
            url {
              path /index.html
              status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }
    real_server 172.16.128.19 80 {
        weight 2
        HTTP_GET {
            url {
              path /index.html
              status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }
}

    修改配置并保存之后,我们需要到网页服务器上使用如下命令添加对172.16.128.129的支持:

~]# ifconfig lo:1 172.16.128.129 netmask 255.255.255.255  broadcast 172.16.128.129 up

~]# route add -host 172.16.128.129 dev lo:1

    回到调度器上重启服务之后就可以看到调度规则了:

集群高可用—keepalived_第16张图片

    到这里,高可用就基本完成了,我们不管是通过172.16.128.128还是通过172.16.128.129,访问的都是同一个集群,而且不管是当调度器宕机还是WEB服务器宕机,我们都能够有足够的时间来对其进行维护,而不是直接丧失这部分功能。