嵌入式系统使用keepalived实现双机热备功能

2019-07-12 23:31发布

嵌入式系统使用keepalived实现双机热备功能


双机热备

双机热备指基于高可用系统中的两台服务器的热备(或高可用),其工作原理是实现故障隔离,简单的讲,高可用(热备)就是一种利用故障点转移的方式来保障业务连续性。其业务的恢复不是在原服务器,而是在备用服务器。热备不具有修复故障服务器的功能,而只是将故障隔离。热备功能现在技术相对比较成熟,在国内外有许多软件可以实现双机热备的功能,这里我们采用开源的keepalived来实现我们设备的双机热备。

Keepalived

Keepalived 是一个基于VRRP协议来实现的服务器高可用方案,可以利用其来避免单点故障。一个双机系统至少会有2台服务器运行Keepalived,一台为主服务器(MASTER),一台为备份服务器(BACKUP),但是对外表现为一个虚拟IP(VIP),主服务器会周期发送vrrp组播报文给备份服务器,当备份服务器收不到这个消息的时候,即主服务器宕机的时候,备份服务器就会接管虚拟IP,继续提供服务,从而保证了高可用性。
图1.1 keepalived网络拓扑图 图1.1 keepalived网络拓扑图

VRRP

简介

Keepalived是vrrp协议的完美实现。
VRRP (Virtual Router Redundancy Protocol)虚拟路由冗余协议,在现实的网络环境中,两台需要通信的主机大多数情况下并没有直接的物理连接。对于这样的情况,它们之间路由怎样选择?主机如何选定到达目的主机的下一跳路由,这个问题通常的解决方法有二种: ●在主机上使用动态路由协议(RIP、OSPF等)
● 在主机上配置静态路由
很明显,在主机上配置动态路由是非常不切实际的,因为管理、维护成本以及是否支持等诸多问题。配置静态路由就变得十分流行,但路由器(或者说默认网关default gateway)却经常成为单点故障。VRRP的目的就是为了解决静态路由单点故障问题,VRRP通过一竞选(election)协议来动态的将路由任务交给LAN中虚拟路由器中的某台VRRP路由器。

Vrrp工作流程

(1).初始化:

路由器启动时,如果路由器的优先级是255(最高优先级,路由器拥有路由器地址),要发送VRRP通告信息,并发送广播ARP信息通告路由器IP地址对应的MAC地址为路由虚拟MAC,设置通告信息定时器准备定时发送VRRP通告信息,转为MASTER状态。否则进入BACKUP状态,设置定时器检查定时检查是否收到MASTER的通告信息。

(2).Master

  • 设置定时通告定时器。
  • 用VRRP虚拟MAC地址响应路由器IP地址的ARP请求。
  • 转发目的MAC是VRRP虚拟MAC的数据包。
  • 如果是虚拟路由器IP的拥有者,将接受目的地址是虚拟路由器IP的数据包,否则丢弃。
  • 当收到shutdown的事件时删除定时通告定时器,发送优先权级为0的通告包,转初始化状态。
  • 如果定时通告定时器超时时,发送VRRP通告信息。
  • 收到VRRP通告信息时,如果优先权为0,发送VRRP通告信息。否则判断数据的优先级是否高于本机,或相等而且实际IP地址大于本地实际IP,设置定时通告定时器,复位主机超时定时器,转BACKUP状态。否则的话,丢弃该通告包。

(3).Backup

  • 设置主机超时定时器。
  • 不能响应针对虚拟路由器IP的ARP请求信息。
  • 丢弃所有目的MAC地址是虚拟路由器MAC地址的数据包。
  • 不接受目的是虚拟路由器IP的所有数据包。
  • 当收到shutdown的事件时删除主机超时定时器,转初始化状态。
  • 主机超时定时器超时的时候,发送VRRP通告信息,广播ARP地址信息,转MASTER状态。
  • 收到VRRP通告信息时,如果优先权为0,表示进入MASTER选举。否则判断数据的优先级是否高于本机,如果高的话承认MASTER有效,复位主机超时定时器。否则的话,丢弃该通告包。

Keepalived安装过程

Keepalived官网:http://www.keepalived.org
安装前先查看官方文档了解软件的一些基本原理和安装需求。或者下载解压软件包之后查看keepalived-1.2.13中的README、COPYING、INSTALL等文件。
在INSTALK文件中指出:
Libraries dependency
In order to compile Keepalived needs the following libraries :
* OpenSSL,
* popt
Installation
安装keepalived的依赖库有OpenSSL和popt,这里我们只需安装OpenSSL库不用装popt库。
所以我们需要安装的有OpenSSL库和keepalived软件。

交叉编译环境准备

开发板执行:$uname –a Linux localhost 3.15.0-xilinx #100 SMP PREEMPT Mon Aug 28 20:38:23 CST 2017 armv7l GNU/Linux 所以我们需要安装arm-xilinx-linux交叉编译工具链。
xilinx-2011.09-50-arm-xilinx-linux-gnueabi.bin下载地址:https://pan.baidu.com/s/1hr5FFO4
然后在虚拟机terminal中进入到软件包地址
使用./xilinx-2011.09-50-arm-xilinx-linux-gnueabi.bin执行安装程序,默认安装。
最后工具链默认安装路径在/root/CodeSourcery/Sourcery_CodeBench_Lite_for_Xilinx_GNU_Linux/。然后将工具链导入到系统PATH。
在terminal输入arm-xilinx-linux-gnueabi-gcc –v显示工具链相关信息证明工具链安装成功。

交叉编译OpenSSL

进入OpenSSL源码包路径执行 ./config no-asm shared --prefix= /usr/local/openssl/ --cross-compile-prefix=/root/CodeSourcery/Sourcery_CodeBench_Lite_for_Xilinx_GNU_Linux/arm-xilinx-linux-gnueabi/ 执行./config -h可以查看一些配置选项。
部分参数介绍:
  • no-asm 在交叉编译过程中不使用汇编代码代码加速编译过程。原因是它的汇编代码是对arm格式不支持
  • shared 生成动态连接库
  • ––prefix 指定安装目录即lib bin include等编译成果物放置的路径
  • ––cross-compile-prefix 指定编译器的路径。/root/CodeSourcery/Sourcery_CodeBench_Lite_for_Xilinx_GNU_Linux/arm-xilinx-linux-gnueabi/是我们刚才安装的交叉编译链的路径
配置执行完成后,修改生成的Makefile文件
CC= $(CROSS_COMPILE) arm-xilinx-linux-gnueabi-gcc
AR=$(CROSS_COMPILE) arm-xilinx-linux-gnueabi-ar $(ARFLAGS) r
RANLIB=$(CROSS_COMPILE) arm-xilinx-linux-gnueabi-ranlib
NM= $(CROSS_COMPILE) arm-xilinx-linux-gnueabi-nm
然后make && make install

交叉编译keepalived

下载并解压keepalived源码包。
针对/mnt目录只读的开发板在源码部分有几处需要修改的地方。
  • keepalived-1.2.13keepalivedcoremain.c
    Line 266 int debug = 0; => int debug = 1;#打开调试模式,可以在程序运行的时候直接在控制台看到日志信息。
  • keepalived-1.2.13keepalivedcoredaemon.c
    line 65 - 67
dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); 注释掉。这几句话是往dev/null里写一些错误信息,注释了没有影响,但如果不注释就会影响程序运行,因为由于开发板特性,我们没有dev/null。
  • keepalived-1.2.13keepalived-1.2.13keepalivedincludepidfile.h
    line 34 – 38 :
#define KEEPALIVED_PID_FILE "/var/run/keepalived.pid" #define KEEPALIVED_VRRP_PID_FILE "/var/run/keepalived_vrrp.pid" #define KEEPALIVED_CHECKERS_PID_FILE "/var/run/keepalived_checkers.pid" #define VRRP_PID_FILE "/var/run/vrrp.pid" #define CHECKERS_PID_FILE "/var/run/checkers.pid" 把/var/run都改成/home/run。是因为我们系统目录/var只读。如果不改进程就不能创建。 执行./configure –h查看所有的配置选项。我们这里需要执行 ./configure --prefix=/usr/local/keepalived-arm --disable-lvs-syncd --disable-lvs --host=arm-xilinx-linux-gnueabi CC=arm-xilinx-linux-gnueabi-gcc 部分参数介绍:
  • ––prefix 指定安装目录
  • ––disable-lvs-syncd –disable-lvs 我们设备的双机热备不需要用到LVS所以这里不编译跟LVS相关的代码。
  • –host 指定编译执行器
  • CC 指定特定的gcc
    然后执行会报错:
configure: error: !!! OpenSSL is not properly installed on your system. !!! !!! Can not include OpenSSL headers files. !!! 是因为我们没有把编译好的OpenSSL配置到PATH,导致执行配置文件的时候找不到跟OpenSSL相关的头文件和库。
执行: export LDFLAGS="-L/usr/local/openssl/lib" export CPPFLAGS="-I/usr/local/openssl/include" 然后重新执行上面的./configure语句。
make && make install
Make时如果报错:
undefined reference to `rpl_malloc’
是交叉编译时autotools认为我们的工具链的libc中不包含malloc和realloc,然后把malloc和realloc替换成了rpl_malloc和rpl_realloc。去/keepalived-1.2.13/lib/config.h中把: #define malloc rpl_malloc #define realloc rpl_realloc 注释掉,再重新编译(make)。

烧录程序

将交叉编译成果物拷贝到目标机器。
方式多样,建议采用winscp软件。选择SCP文件协议,输入目标机器IP,输入用户名,密码。
把虚拟机/usr/local/openssl/拷贝到目标机器/home下。
把虚拟机/usr/local/keepalived-arm/拷贝到目标机器/home下。
然后执行以下; export LDFLAGS="-L/home/openssl/lib" export CPPFLAGS="-I/home/openssl/include" export LD_LIBRARY_PATH=/home/openssl/lib:$LD_LIBRARY_PATH cd /home/keepalived-arm/sbin/ chmod +x keepalived ./keepalived -D --use-file=/home/keepalived/etc/keepalived/keepalived.conf 以上操作过程是先把openssl头文件和库导入PATH中,然后执行时带–use-file参数指定keepalived使用的配置文件。
在terminal我们可以看到一些keepalived打印的一些日志。
执行ps –ef | grep keepalived | grep –v grep可以查看keepalived进程状态。

Keepalived的配置文件

默认配置文件/usr/etc/keepalived/keepalievd.conf执行时使用参数—use-file可以指定配置文件路径。
Keepalived的配置文件分三个配置区域:
  • 全局配置
  • VRRPD配置
  • LVS配置(非集群高可用不需要配置)

全局配置

global_defs { notification_email { admin@example.com#接受报警信息邮件地址,可以是多个 } notification_email_from admin@example.com #发件人邮箱 smtp_server 192.168.200.1#邮件发送服务器 smtp_connect_timeout 30#邮件服务器建立连接的时长 router_id lnmp_node1 #物理节点标识符,在局域网内应该是唯一的。master和backup是不一样的 }

VRRPD配置

VRRPD配置包括三个类
  • VRRP同步组(vrrp_sync_group)#这里我们不需要配置
  • VRRP实例(vrrp_instance)
  • VRRP脚本(vrrp_script)
vrrp_script chk_ntpd { #VRRP脚本 script "killall -0 ntpd" #检查ntpd进程是否存在。是返回0否返回1 interval 2 #脚本执行间隔(单位/s) weight -100 #返回1目标机器权重-100(可以通过调整优先级数值实现master和backup切换) } vrrp_script chk_down { script "[[ -f /etc/keepalived/down ]] && exit 1 || exit 0" #[ -f /etc/keepalived/down ]检查是否有down这个文件,如果存在返回0,上面脚本会exit 1,如果不存在返回1,上面脚本会exit 0 # commadn1 && command2 只有在 && 左边的命令返回真(命令返回值 $? == 0),&& 右边的命令才会被执行 # commadn1 || command2 只有在 || 左边的命令返回假(命令返回值 $? == 1),|| 右边的命令才会被执行。 interval 1 weight -100 #只要上面exit 1,weight就-100,下面的priority-100 = 100 比BACKUP的190少了,优先级降低,转成备用状态了,再次检测如果down没了,权重会恢复200,就又变成MASTER了。这样就可以手动干预vip在节点间切换 } vrrp_instance lnmp #VRRP实例配置 { state MASTER #状态只有MASTER和BACKUP两种,并且必须大写,MASTER为主机,BACKUP是备机。 interface eth1 #虚拟网址配置到哪个网口 eth0 eth1 或者 eth2 virtual_router_id 100 #虚拟路由标识。同一个工作组的master和backup的值一样 priority 200 #优先级(0-255)即权重,master大于backup。通过调整priority可以调整主从状态。 advert_int 5 #master和backup之间检测的时间间隔(单位/s) track_interface { #跟踪接口,设置额外的监控,里面任意一块网卡出现问题,都会进入故障(FAULT)状态 eth1 eth2 } authentication #设置认证 { auth_type PASS # 验证方式,有PASS和AH。通常使用PASS auth_pass 123456 #验证密码,master和backup密码相同才能通信 } virtual_ipaddress #虚拟ip地址,可以有多个地址,每个地址占一行,不需要子网掩码 { 192.168.0.200 } track_script #调用上面自定义的脚本 { chk_down check_ntpd } notify_master "/home/run/notify_master.sh"#节点转为master时执行 notify_backup "/home/run/notify_backup.sh"#节点转为backup时执行 notify_fault "/home/run/notify_fault.sh "#节点转为fault(故障状态)时执行 }