KeepAliveD in AWS

KeepAliveD in AWS

需求

在AWS环境,已有两台服务器安装Mysql,并配置为主主模式(Active/Active)。要求实现一种方案,当一个Mysql故障后,能自动切换到另一Mysql服务器,提供服务的高可用。

操作系统要求: ubuntu14.04

前期调研

想在AWS 环境实现数据库的高可用,考虑了方案:

  • RDS -- AWS服务,使用DNS 实现服务切换,耗时1分钟-- 时间太长,不满足需求
  • ELB -- AWS服务,本质是实现负载均衡。不能实现Active/Passive 模式 -- 不满足需求
  • Haproxy -- 使用 Active/Passive模式,能够实现Mysql服务的切换,切换耗时15秒。但这个方案需要一个新的VM,在解决一个问题的同时,引入了一个新的单点故障。 -- 放弃
  • Veritas -- 传统的HA方案,是商业软件,需要额外付费。配置的时候需要双网卡来配置心跳检测网络。这种网卡冗余方案在公有云中不合时宜——先跳过,如果其他方案不可行,再回过头来看。
  • HeartBeat -- 需要单独网络做心跳检查 -- 先跳过。
  • KeepAliveD -- 公司其他部门使用KeepAliveD+Apache实现Web高可用,是一套成熟,可靠的方案。而且服务切换只需要3-5秒,效率很高。

选择方案

最后考虑 AWS 环境中部署keepalived + Mysql 实现高可用。

KeepAliveD 工作原理

Keepalived是一个免费开源的,用C编写的类似于layer3, 4 & 7交换机制软件,具备我们平时说的第3层、第4层和第7层交换机的功能。主要提供loadbalancing(负载均衡)和 high-availability(高可用)功能,负载均衡实现需要依赖Linux的虚拟服务内核模块(ipvs),而高可用是通过VRRP协议实现多台机器之间的故障转移服务。

简单来说,只需要把它当作路由器即可!

VRRP协议

网络在设计的时候必须考虑到冗余容灾,包括线路冗余,设备冗余等,防止网络存在单点故障,那在路由器或三层交换机处实现冗余就显得尤为重要,在网络里面有个协议就是来做这事的,这个协议就是VRRP协议,Keepalived就是巧用VRRP协议来实现高可用性(HA)的。

遇到的问题:

    1. 通过命令 “apt install keepalived” 安装包不可用。
    1. 亚马逊云不支持KeepAliveD中的组播模式。主备之间的VRRP包互相发不通。
    1. 在AWS环境中,所有的ARP广播都被禁止了。这样KeepAliveD的IP欺骗机制基本上也就不可行了。在资源服务器上配置的Virtual IP,应用服务器没有办法访问。
      VIP的默认配置是不生效的:(AWS 中,只有本机认可,没有广播,其他服务器不知道)

解决办法:

    1. 需要下载源码包,并针对ubuntu 做修改(源码适用redhat)。
    1. 切换KeepAliveD到单播模式,在配置中增加单播机器的IP:

unicast_src_ip 172.*.*.1 #localIp

unicast_peer {
172.*.*.124 #Resource-02

}

还有一点需要特别注意,VRRP协议既不属于TCP也不属于UDP,在做防火墙策略的时候,在协议类型选项需要选“All traffice”的选项来防止由于防火墙原因造成通信问题。

    1. 用 AWS CLI 来实现 VIP 指向的切换
    • 3.1.1 如果使用private IP作为 VIP,则:两个服务器配置三个IP 地址,其中一个是 Secondary private IP,它作为内网的VIP使用。这个配置是基础配置。也就是说,如果一个IP指向这台服务器,可是这台服务器上的网卡不认为自己拥有这个IP是不行的。

    • 3.1.2 如果Public IP (EIP) 作为 VIP,配置相对简单,可以跳过Secondary private IP

    • 3.2 在两台服务器上安装亚马逊云自己的客户端工具(awscli) 并配置(Authentication,IP 切换时使用)

    • 3.3 在KeepAliveD认为自己获取到Master权限的时候,调用awscli命令让Virtual IP实际指向本服务器。这个逻辑是核心逻辑。亚马逊云虽然不允许广播ARP,但可以用命令行指定网卡(ENI)的Secondary-private-ip-address。这个命令的具体形式如下:


su - ubuntu -c "aws ec2 assign-private-ip-addresses --network-interface-id $ENI --private-ip-addresses $VIP --allow-reassignment"
ip address add $VIP/20 dev eth0


$ENI指的是网卡的ID,$VIP是虚拟IP,分配Private IP后,必须用ip命令把它启用(OS 能识别出这个变化) (具体原因的官方解释)

【已知问题】keepalived 被停掉后,因script 无法被调用,导致本机VIP无法被删除,于是本机的VIP连接继续指向本地,其它服务器不受影响。也就是说本机Mysql继续认为自己是主服务器,但由于没有外部数据写入,虽然它是错的,但也没有实质的影响。

【注】使用EIP无此问题。(直接从AWS云平台获取Public IP,没有到OS这一级)

如果把外网EIP作为VIP,则:

aws ec2 disassociate-address --public-ip $EIP
aws ec2 associate-address --public-ip $EIP --instance-id $INSTANCE_ID

EIP(Elastic IP) 是外网IP,先释放,再分给某个instance

安装步骤

在ubuntu14平台,两台Mysql Server所在的服务器都安装和配置KeepAliveD。

安装依赖

$ sudo apt update
$ sudo apt install libssl-dev gcc make awscli daemon

下载源包并编译

$ wget http://www.keepalived.org/software/keepalived-1.3.9.tar.gz
$ tar zxf keepalived-1.3.9.tar.gz
$ cd keepalived-1.3.9
$ ./configure --prefix=/usr/local/keepalived --sysconf=/etc

编译结果:

Keepalived configuration
------------------------
Keepalived version       : 1.3.9
Compiler                 : gcc
Preprocessor flags       :
Compiler flags           : -Wall -Wunused -Wstrict-prototypes -Wextra -g -O2
Linker flags             :
Extra Lib                :  -lcrypto  -lssl
Use IPVS Framework       : Yes
IPVS use libnl           : No
IPVS syncd attributes    : No
IPVS 64 bit stats        : No
fwmark socket support    : Yes
Use VRRP Framework       : Yes
Use VRRP VMAC            : Yes
Use VRRP authentication  : Yes
With ip rules/routes     : Yes
SNMP vrrp support        : No
SNMP checker support     : No
SNMP RFCv2 support       : No
SNMP RFCv3 support       : No
DBUS support             : No
SHA1 support             : No
Use Debug flags          : No
Use Json output          : No
Stacktrace support       : No
Memory alloc check       : No
libnl version            : None
Use IPv4 devconf         : No
Use libiptc              : No
Use libipset             : No
init type                : upstart
Build genhash            : Yes
Build documentation      : No
*** WARNING - this build will not support IPVS with IPv6. Please install libnl/libnl-3 dev libraries to support IPv6 with IPVS.

Install

$ make
$ sudo make install

针对ubuntu 修改配置:

$ sudo cp keepalived/etc/init.d/keepalived /etc/init.d
$ sudo vi /etc/init.d/keepalived

修改启动脚本 /etc/init.d/keepalived

. /etc/rc/d/init.d/functions #注释这句,新增下行
. /lib/lsb/init-functions
daemon keepalived ${KEEPALIVED_OPTIONS} #注释该行,新增下行
daemon keepalived start

$ sudo mkdir -p /var/lock/subsys

拷贝运行的核心文件

$ sudo cp /usr/local/keepalived/sbin/keepalived /usr/sbin/

$ sudo vi /etc/keepalived/keepalived.conf #运行的配置文件

For master:

配置分为三部分:
global_defs 全局配置
vrrp_script 服务健康检查脚本
vrrp_instance 完成keepalived 服务健康检查,VIP切换

global_defs {
    router_id backup_cluster # 标识本节点的字符串,通常为hostname,但不一定非得是hostname,故障发生时,邮件通知会用到
}
vrrp_script chk_mysql {
    script "killall -0 mysqld"     # 监控服务脚本,尽量简单,判断返回值0 或非0
    interval 2   # check every 2 seconds
    fall 2       # require 2 failures for KO
    rise 2       # require 2 successes for OK
}
vrrp_instance VI_1 {  # 实例名称
    state BACKUP      # 可以是MASTER或BACKUP,不过当其他节点keepalived启动时会将priority比较大的节点选举为MASTER
    interface eth0    # 节点固有IP(非VIP)的网卡,用来发VRRP包做心跳检测
    priority 100      # 用来选举master的,要成为master那么这个选项的值最好高于其他机器50个点,该项取值范围是1-255(在此范围之外会被识别成默认值100)
    nopreempt       # 服务恢复后成为backup, 不会抢回master避免频繁切换
    virtual_router_id 51 # 虚拟路由ID,取值在0-255之间,用来区分多个instance的VRRP组播,同一网段内ID不能重复;主备必须为一样;
    unicast_src_ip 172.31.19.247  # AWS中组播被禁,采用点对点通信。 这是本机IP
    unicast_peer {
    172.31.21.194  # 这是另一台keepalive server IP
    }
    advert_int 1      # 检查间隔默认为1秒,即1秒进行一次master选举
    authentication {  # 认证区域,认证类型有PASS和HA(IPSEC),推荐使用PASS(密码只识别前8位)
        auth_type PASS  # 默认是PASS认证
        auth_pass MrUse # PASS认证密码
    }
    track_script {
        chk_mysql
    }
    notify   /etc/keepalived/failover.sh
 }

For Backup:


global_defs {
    router_id backup_cluster # 标识本节点的字符串,通常为hostname,但不一定非得是hostname,故障发生时,邮件通知会用到
}
vrrp_script chk_mysql {
    script "killall -0 mysqld"
    interval 2
}
vrrp_instance VI_1 {  # 实例名称
    state BACKUP      # 可以是MASTER或BACKUP,不过当其他节点keepalived启动时会将priority比较大的节点选举为MASTER
    interface eth0    # 节点固有IP(非VIP)的网卡,用来发VRRP包做心跳检测
    priority 40      # 用来选举master的,要成为master那么这个选项的值最好高于其他机器50个点,该项取值范围是1-255(在此范围之外会被识别成默认值100)
    virtual_router_id 51 # 虚拟路由ID,取值在0-255之间,用来区分多个instance的VRRP组播,同一网段内ID不能重复;主备必须为一样;
    unicast_src_ip 172.31.21.194  # 跟master 设置反过来
    unicast_peer {
    172.31.19.247
    }
    advert_int 1      # 检查间隔默认为1秒,即1秒进行一次master选举
    authentication {  # 认证区域,认证类型有PASS和HA(IPSEC),推荐使用PASS(密码只识别前8位)
        auth_type PASS  # 默认是PASS认证
        auth_pass MrUse # PASS认证密码
    }
    track_script {
        chk_mysql
    }
    notify   /etc/keepalived/failover.sh
    #notify_master /etc/keepalived/master.sh
    #notify_backup /etc/keepalived/backup.sh
    #notify_fault     /etc/keepalived/fault.sh
    
}

Keepalived notify脚本

notify脚本是keepalived集群管理脚本,当keepalived角色state状态发生变化时都会执行这个脚本。 AWS中默认方法不可行,只能靠它来实现IP切换。

例子

配置aws cli:

aws cli 认证方法

获取网卡 eni 信息:

$ aws ec2 describe-instances --instance-ids i-0f530d6377bcd4db9 --query Reservations[].Instances[].NetworkInterfaces[].NetworkInterfaceId
[
    "eni-ee4c45c6"
]

or

 $ aws ec2 describe-instances --instance-ids i-0f530d6377bcd4db9 | grep eni

网页上也能查到:

KeepAliveD in AWS_第1张图片
Snip20180611_3.png

VIP 切换脚本:

failover.sh


#!/bin/bash
VIP=172.31.31.31
ENI=eni-8df310ac  ## 这是本机eth0 网卡的ID,另一server不同
LOG=/etc/keepalived/failover.log
TYPE=$1
NAME=$2
STATE=$3
echo -e "\n##### failover to $STATE status ######" >> ${LOG}
date >> ${LOG}
case $STATE in
    "MASTER")
        su - ubuntu -c "/usr/bin/aws ec2 assign-private-ip-addresses --network-interface-id $ENI --private-ip-addresses $VIP --allow-reassignment" >> ${LOG} 2>&1
        ip address add $VIP/20 dev eth0 >> ${LOG} 2>&1
        echo -e "##### complete master script for ${NAME} ######\n" >> ${LOG}
          ;;
    "BACKUP"|"FAULT")
        ip address del $VIP/20 dev eth0 >> ${LOG} 2>&1
        echo -e "#####  complete $STATE script for VRRP ${TYPE} ${NAME} ######\n" >> ${LOG}
          ;;
    *)
        echo "unknown state ${STATE} for VRRP ${TYPE} ${NAME}"
        exit 1
        ;;
esac

后续服务启动和检查

添加为系统服务

$ sudo update-rc.d keepalived defaults

启动keepalived

$ sudo /etc/init.d/keepalived start

查看keepalived 日志

$ tail -f /var/log/syslog

查看自定义脚本生成的日志

$ tail /etc/keepalived/failover.sh

mysql 连接测试

$ mysql -uhive -phive -h172.31.31.31

你可能感兴趣的:(KeepAliveD in AWS)