干货 | 基于keepalived高可用的应用实战

​背景

最近由于监管合规之反洗钱要求,上线了OCR身份证识别系统,但是供应商提供的架构方案中有单点故障的不完美之处,虽然以现有的交易规模和业务模式来讲,单套服务具备承接业务峰值的能力,但是作为集群服务和高可用遍地的互联网时代,高效的架构不仅可以避免单点故障(不会出现某个服务或者某台服务器故障导致整个应用不可使用),还可以提高系统运维质量,确保服务的高可用(High Availability)。


负载均衡

说到高可用,就要先说说负载均衡。常见的互联网架构最外面的F5就是典型的负载均衡处理设备。负载均衡器是数据中心的切入点,处于后续一切服务的关键路径。这部分的应用也很多,如果是比较小的网站(日PV<1000万),用nginx就完全可以了,如果机器也不多,访问量不大,也可以用DNS轮询;大型网站或者重要的服务,可以考虑利用LVS或者商用F5设备。一般四层负载使用LVS软件或F5硬件实现,七层负载使用nginx实现,至于网络四层负载和七层负载的区别以及nginx、LVS和F5等的区别有兴趣的可以研究下。下图便是经典的负载实现架构:


 

高可用

之所以讲负载均衡,是因为我们选择了Keepalived来实现高可用,其设计之初就是专为LVS负载均衡软件设计的,用来管理并监控LVS系统各个服务节点的状态,后来加入了可以实现高可用的VRRP功能。因此Keepalived除了能管理LVS软件外,还可以作为其他服务(例如:Nginx、Haproxy、Mysql等)的高可用解决方案软件。Keepalived的作用是检测服务器的状态(注意是服务器层面不是应用层面),如果有一台web服务器宕机,或工作出现故障,Keepalived将检测到,并将有故障的服务器从系统中剔除,同时使用其他服务器代替该服务器的工作,当服务器工作正常后Keepalived自动将服务器加入到服务器群中,这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的服务器。它能够保证当个别节点宕机时,整个网络可以不间断的运行。


一般来讲,直接在需要实现高可用的服务器中部署Keepalived即可,但是本次的OCR服务是C/S实现的Windows服务,而keepalived是linux的专有软件,所以必须在OCR服务之前架设高可用转发服务,我们选择了nginx的stream转发模块来完整这个处理,并且将原来的一路OCR服务分成多路,通过NAS盘共享存储和nginx负载均衡来达到集群效果。从理论值来做一个架构优化后的对比,假设原单路OCR处理能力是100并发,现在因一台nginx的最大并发量达50000,所以并发限制在分了N路负载决定,处理能力提升N倍,且不会有单点故障(之前的日志分析平台ELK架构中也可以引入改HA模式)。


脑裂问题

但是高可用一般有一个数据安全的隐患就是脑裂问题。在高可用(HA)系统中,当联系两个节点的“心跳线”断开时,本来为一整体动作协调的HA系统,就分裂成为两个独立的个体。由于相互失去了联系,都以为是对方出了故障。两个节点上的HA软件像“裂脑人”一样,争抢“共享资源”、争起“应用服务”,就会发生严重后果,比如共享资源被瓜分两边“服务”都起不来了,或者两边“服务”都起来了,但同时读写“共享存储”,导致数据损坏。


而Keepalived软件同样也有这个问题,它主要是通过VRRP协议实现高可用功能的。VRRP是Virtual Router Redundancy Protocol(虚拟路由冗余协议)的缩写,其用IP组播的方式(默认组播地址: 224.0.0.18), 实现服务节点间的通信,定期向服务器群中的服务器发送一个ICMP的数据包(既Ping程序),如果发现某台服务的IP地址没有激活,Keepalived便报告这台服务器失效, 通过一种竞选机制来将路由任务交给某台VRRP路由器. 工作时主节点发送VRRP协议报文, 备节点接收报文, 若一段时间(默认3个报文发送时间)备节点接收不到主节点发送的报文, 就会启动接管程序接管主节点的资源. 备节点可以有多个, 通过优先级竞选。从原理上也可以看出VRRP协议出现的目的就是为了解决静态路由单点故障问题。


我们从上述工作原理知道, 备节点接收不到报文时, 如两者间的网络不通了, 备节点就会启动接管程序接管主节点的资源, 对外提供服务, 表现形式就是备节点上出现了虚拟IP, 此时主节点也是持有虚拟IP的.出现脑裂问题,对付HA系统“裂脑”的对策,目前大概有以下几种方式:

1)添加冗余的心跳线。例如:双线条线(心跳线也HA),尽量减少“裂脑”发生几率;

2)启用磁盘锁。正在服务一方锁住共享磁盘,“脑裂”发生时,让对方完全“抢不走”共享磁盘资源。但使用锁磁盘也会有一个不小的问题,如果占用共享盘的一方不主动“解锁”,另一方就永远得不到共享磁盘。现实中假如服务节点突然死机或崩溃,就不可能执行解锁命令。后备节点也就接管不了共享资源和应用服务。于是有人在HA中设计了“智能”锁。即:正在服务的一方只在发现心跳线全部断开(察觉不到对端)时才启用磁盘锁。平时就不上锁了。

3)设置仲裁机制。例如设置参考IP(如网关IP),当心跳线完全断开时,2个节点都各自ping一下参考IP,不通则表明断点就出在本端。不仅“心跳”、还兼对外“服务”的本端网络链路断了,即使启动(或继续)应用服务也没有用了,那就主动放弃竞争,让能够ping通参考IP的一端去起服务。更保险一些,ping不通参考IP的一方干脆就自我重启,以彻底释放有可能还占用着的那些共享资源。


实施过程

有了相关理论的调研,我们将知识点和可能碰到的问题梳理清楚便可以实施,主要涉及nginx的安装、keepalived部署及脑裂处理三个步骤

1、Nginx安装:

--检查安装环境,是否符合

nginx默认安装的时候无法加载流stream模块,

需要在启动参数里加上-–with-stream。

./configure --with-stream

make && make install

配置服务并开机启动(systemctl enable nginx)

/lib/systemd/system/nginx.service

[Unit]

Description=nginx

After=network.target

[Service]

Type=forking

ExecStart=/usr/local/nginx/sbin/nginx

ExecReload=/usr/local/nginx/sbin/nginx reload

ExecStop=/usr/local/nginx/sbin/nginx quit

PrivateTmp=true [Install]

WantedBy=multi-user.target

--启动nginx

systemctl start nginx.service  

--结束nginx

systemctl stop nginx.service  

--重启nginx

systemctl rest

2、keepalived部署

HA模式Ip(安全考虑这里为非真实IP)

VIP192.168.1.10

主机(master node)192.168.1.8

备机(backup nod)192.168.1.7

架构图如下

配置yum源(点击参考),如果是离线的挂载ios盘,默认系统安装即可

yum install -y keepalived

主机关键配置(注意keepalived 的global_defs模块中vrrp_strict 参数会严格执行VRRP协议规范,此模式不支持节点单播,如果配置会引起vip无法ping通,建议去掉)

备机关键配置

注.由于keepalived是四层服务,只有ping不通的情况才会切换到备机,当Nginx宕机,会导致用户请求失败,但是keepalived不会进行切换,所以要在主备机的配置中增加一个nginx的脚本监控,防止转发服务不可用。


3、脑裂处理

为了节省实施成本,我们用了仲裁方式和监控来处理。同时关闭节点防火墙或者加入防火墙过滤规则

-A INPUT -s192.168.1.0/24-d224.0.0.18-jACCEPT      #允许组播地址通信

-A INPUT -s192.168.1.0/24-p vrrp -jACCEPT            #允许VRRP(虚拟路由器冗余协)通信 

根据vrrp的原理,在备机添加监控脚本如下(注意脚本的编码格式):

简单解释下处理逻辑,如果备机和主机能ping通,而且在备机上也发现了VIP的漂移,那么就判断为脑裂产生了,关闭keepalived服务,如果备机和主机不能ping通,且在备机上发现了VIP的漂移,我们认为是正常的HA切换。互联网上还有一种方案通过网关仲裁的方式判断,说如果自己的网关参考不通,那么表示脑裂,也不失为一种方案,但是这个我们认为可以纳入服务监控的范畴了,连服务器断网都发生了,脑裂就已经不重要了,不是吗?


综上所述,这里的高可用就好比人行走的两条腿,左脚为主机,右脚为备机,每一次的跨步行走都是流畅的主备切换,如果两条腿同时迈出去肯定会摔倒的,HA的脑裂问题也是如此,技术到后面其实都是向人类智慧靠近

文章来源:微信公众号(思快奇)

参考资料:

CSDN:keepalived是如何解决或者防止脑裂问题的?

百度百科:LVS

其他网络资料

你可能感兴趣的:(干货 | 基于keepalived高可用的应用实战)