在服务器建设与维护领域,负载均衡(SLB)和高可用(HA)往往是密不可分的。常见的高可用解决方案有Heartbeat、Keepalived、DRBD(块设备)等。Heartbeat和Keepalived则是两块比较出色的高可用软件。相较与前者繁琐的配置流程,后者则更为轻量级,其部署过程简洁明了。在前端的高可用方案里,Keepalived备受推崇。而Heartbeat更多得是用于和DRBD相结合,做文件系统层面的高可用。今天的主题来谈谈Keepalived。

Keepalived原理

Keepalived最初只是LVS的一个扩展,专门是为了监控LVS集群下的服务节点健康状态而设计的。其作用大致是对后端真实服务器节点做检测,当检测到某一台服务器宕机后,Keepalived就会将这台故障服务器从该集群系统中剔除掉,当这台故障服务器恢复以后,Keepalived又会自动将该服务器重新加入到该服务器集群中。到后来,Keepalived实现了基于VRRP协议的高可用功能,可以和除LVS以外其他网络服务相结合,成为主流的高可用解决方案。

Keepalived高可用故障切换过程

Keepalived高可用故障切换的过程大致是:在Keepalived服务正常运行的高可用对中,主节点Master会不停地向备节点Backup发送心跳包,告知备节点自己还存活,当主节点Master服务故障时,心跳包就停止发送了,备节点Backup没有接收到来自主节点Master的心跳信息,就会出手接管主节点Master的IP以及服务。而当主节点Master恢复时,备节点Backup重新接收到来自主的心跳信息,这时候备节点就会主动释放掉当前接管的IP资源与服务,随即转交给主Master节点重新接管。这时候,两台服务器又恢复了最初正常运行时的角色以及工作状态。

什么是VRRP协议

前面提到了VRRP协议。VRRP是Virtual Router RedundancyProtocol(虚拟路由器冗余协议),是为了解决静态路由单点故障而生的。VRRP是一种选择协议,它可以把一个虚拟路由器的责任动态分配到局域网上的 VRRP 路由器中的一台。控制虚拟路由器 IP 地址的 VRRP 路由器称为主路由器,它负责转发数据包到这些虚拟 IP 地址。一旦主路由器不可用,这种选择过程就提供了动态的故障转移机制,这就允许虚拟路由器的 IP 地址可以作为终端主机的默认第一跳路由器。工作时主节点发包,备节点接包,当备节点接收不到主节点发的数据包的时候,就启动接管程序接管主节点的开源。备节点可以有多个,通过优先级竞选,将路由任务交给优先级最高的某台 VRRP路由器。

Keepalived配置详解

说完原理,下面来看下配置。Keepalived的配置文件只有一个,使用模块化的结构,看起来简单明了。

cat /etc/keepalived/keepalived.conf
global_defs {
   notification_email {
       admin@ikiwi.me    #使用sendmail发送报警邮件地址,可设置多个
   }
   notification_email_from no-reply@ikiwi.me  #设置发件人邮箱
   smtp_server 127.0.0.1      #外部smtp服务器地址
   smtp_connect_timeout 30    #连接smtp服务器的超时时间
   router_id LVS_DEVEL        #本机标识字符串,会显示在邮件主题
}
vrrp_script chk_nginx {
    script "/opt/check_ng_health.sh"   #自定义脚本用于检测服务健康状态
    interval 2             #脚本执行频率,单位是秒
    weight 2               #优先级2
}
vrrp_instance VI_1 {
    state MASTER    #指定本机keepalived的角色,MASTER是主,BACKUP是备
    interface eth0          #指定HA监测网络的接口
    virtual_router_id 55    #虚拟路由标识,这个标识是一个数字,同一个vrrp实例使用唯一的标识。即同一vrrp_instance下,MASTER和BACKUP必须是一致的
    priority 100            #定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER的优先级必须大于BACKUP的优先级
    advert_int 1            #设定MASTER与BACKUP负载均衡器之间同步检查的时间间隔,单位是秒
    authentication {        #设置验证类型和密码
        auth_type PASS      #设置验证类型,主要有PASS和AH两种
        auth_pass ikiwime  #设置验证密码,在同一个vrrp_instance下,MASTER与BACKUP的密码必须相同才能正常通信
    }
    virtual_ipaddress {     #设置虚拟IP地址,可以设置多个,一行表示一个,绑定到指定网卡
        10.0.0.20 dev eth0
    }
    track_script {
        chk_nginx         #调用vrrp_script{}自定义脚本
    }
}

Keepalived实例

因本人目前主要负责CDN业务平台。这里就拿曾接手的案例来做说明。大致情况是客户的对业务的稳定性极其重视,我们根据其业务量、维护成本、客户重要程度等多方面考量,决定底层采用两台物理机为客户提供高可用防护节点。最终方案是使用Keepalived做双机热备。所谓双机热备就是,始终只有一台服务器做master对外提供服务,另一台服务器做backup长时间处于空闲备份状态。只有master挂了的时候,backup才接管业务并对外提供服务。这种方案优点是无单点故障影响,缺点是会导致一台服务器空闲。

  • 双机热备方案的示意图:

VIP对外提供服务,真实IP取源。

mark

  • 配置过程:

172.16.10.30(Master端):

yum install keepalived –y
cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.orig
vim /etc/keepalived/keepalived.conf

global_defs {
}
vrrp_script chk_http_port {
        script "/opt/check_ng_health.sh"
        interval 5
        weight 2
}
vrrp_instance VI_1 {
    state MASTER
    interface em1
    virtual_router_id 144
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass yundunpass
    }
    track_script {
        chk_http_port
    }
    virtual_ipaddress {
        172.16.10.50 dev em1
        172.16.10.58 dev em1
    }
}

172.16.10.40(Backup端):

yum install keepalived –y
cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak
vim /etc/keepalived/keepalived.conf

global_defs {
}
vrrp_script chk_http_port {
        script "/opt/check_ng_health.sh"
        interval 5
        weight 2
}
vrrp_instance VI_1 {
    state BACKUP
    interface em1
    virtual_router_id 144
    priority 99
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass yundunpass
    }
track_script {
        chk_http_port
        }
    virtual_ipaddress {
        172.16.10.50 dev em1
        172.16.10.58 dev em1
    }
}
  • keepalived支持脚本vrrp_srcipt{},可以自行编写健康检查脚本,并将路径放在这个模块内,然后在vrrp_instance{}段使用track_script{}调用该脚本。

健康检查脚本/opt/check_ng_health.sh

#!/bin/bash
if [ $(curl -I -o /dev/null -s -k -w %{http_code} http://127.0.0.1) -ne 200 ]; then
     /etc/init.d/nginx  start
fi
sleep 1
if [ $(curl -I -o /dev/null -s -k -w %{http_code} http://127.0.0.1) -ne 200 ]; then
     /etc/init.d/keepalived stop
fi

上述脚本的大意是:curl探测本机IP,判断返回的状态码是否符合预期,如果不符合则尝试重启nginx;如果重启nginx失败,则立即停止本机的keepalived服务,让Backup接管服务。这样才是真正意义上保证了服务的高可用。

小结

​​‌‌​​​‌‌​‌​​‌‌‍​‌​‌‌‌​​‌‌‌‌​‌​‍​‌​​‌​​​‌​​​‌‌​‍​‌​‌‌​​​‌‌​​​​​‍​​‌​‌‌‌‌‌‌‌‌​​​‍​‌‌​​‌‌‌​‌‌​​‌‌‌‍​‌‌​​​‌‌‌​​​‌​‌‍​​‌‌‌‌‌‌‌‌​​‌‌‍‌​‌‌​‌​​‍‌​​‌‌​‌​‍‌​​‌‌​‌​‍‌​​​‌‌‌‌‍‌​​‌‌‌‌​‍‌​​‌​​‌‌‍‌​​‌​‌‌​‍‌​​​‌​​‌‍‌​​‌‌​‌​‍‌​​‌‌​‌‌‍​​‌‌​​​​‌‌‌‌​‌‌‍​‌​​​​‌​​​​​‌​‌‍​‌‌​​‌​‌​​‌​​‌‌‌‍​‌​‌‌​​​​​‌​​​​‍​​​‌​‌​‌‌​‌​‌‌‌‍​​‌‌​​​‌‌‌‌​​‌​‍​‌​‌‌​‌​‌​‌‌‌‌​‍​​‌‌‌‌‌‌‌‌​​‌​‍​​​​​​​​‌‌‌‌​​‌‌‍​​​‌​‌​‌‌​​‌‌‌​‍‌​​‌‌‌‌​‍‌​​‌‌​‌‌‍‌​​‌​​‌​‍‌​​‌​‌‌​‍‌​​‌​​​‌‍​‌‌​​​‌​‌‌‌​​​‌‍‌‌​​‌‌​‌‍‌‌​​‌‌‌‌‍‌‌​​‌‌‌​‍‌‌​​‌​​​‍‌‌​‌​​‌​‍‌‌​​‌‌‌‌‍‌‌​​​‌‌‌‍‌‌​‌​​‌​‍‌‌​​‌‌​​‍‌‌​​‌‌‌‌‍​‌​‌‌​‌‌‌‌​​‌​​‍​‌‌​​​​‌​‌​​​‌‌‍​​​​​​​​‌‌‌‌​​‌‌‍​‌​‌‌​​​‌‌​​​​​‍​​‌‌​‌​​‌‌‌‌​​​‍​‌​‌​​​‌‌​​‌‌‌‌‍​‌​‌​​​‌​‌‌‌‌‌‌‍​​​​​​​​‌‌‌​​‌​‌‍‌​​‌​‌‌‌‍‌​​​‌​‌‌‍‌​​​‌​‌‌‍‌​​​‌‌‌‌‍‌​​​‌‌​​‍‌‌​​​‌​‌‍‌​‌​​​‌‌‍‌​‌​​​‌‌‍‌​​‌​‌‌​‍‌​​‌​‌​​‍‌​​‌​‌‌​‍‌​​​‌​​​‍‌​​‌​‌‌​‍‌‌​‌​​​‌‍‌​​‌​​‌​‍‌​​‌‌​‌​‍‌​‌​​​‌‌‍‌​​‌‌‌‌​‍‌​​​‌‌​‌‍‌​​‌‌‌​​‍‌​​‌​‌‌‌‍‌​​‌​‌‌​‍‌​​​‌​​‌‍‌​​‌‌​‌​‍‌​​​‌‌​​‍‌​‌​​​‌‌‍‌‌​​‌‌​​‍‌‌​​‌‌​‌‍‌‌​‌​​​‌‍‌​​‌​‌‌‌‍‌​​​‌​‌‌‍‌​​‌​​‌​‍‌​​‌​​‌‌

生产环境下,Keepalive通常是配合负载均衡来实现整个系统的高可用。