高可用集群和heartbeat

继续探索Linux高可用集群

HA集群概念review和扩展

之前我们说过LVS, 虽然可以使用director向后端做健康状态检查, 但是仍然不能把这个系统称作高可用. 首先我们的状态数据会被丢失, 而且director是SPOF对嘛, 我们之前说过这个概念, director是一个单点所在, 所以只要director出现故障, 整个系统将会不可用. 对于电子设备来说, 出现故障的概率是很大的.

我们之前还说过一个公式: 可用性 = 平均故障时间 / 平均故障时间 + 平均修复时间. 而且还说过可用性的百分比概念: 90%, 95%, 99%, 99.9%, 99.99%, 99.999%.

一个典型的高可用方案就是冗余, 比如两台主机, 但是这还远远不够了, 有的时候, 还会有双网线, 双交换机, 双电源等等. 当然了后面的这些已经是比较大的规模了.

而我们现在关心的问题是, 怎么解决判定主机宕机, 或者说服务不可用呢? 而且, 当出现状况了, 怎么进行主机的更换呢?

这样的一种机制, 我们把它叫做heartbeat机制, 也就是心跳机制, 很形象对嘛? 主机之间发送一些极小的报文进行探测, 接着通过回应判断主机当前的状态, 这样的包我们把他们叫做心跳包. 然而, 很多问题需要进行解决: 例如, 如果对方没有回应, 或者说超时了, 我就直接认定为对方下线了吗? 如果后来对方又回来了呢? 这样的原因是很多的, 例如CPU超负载, 网络拥塞等等.

但是先不说细节. 现在我们就可以来说说高可用集群是个啥了, 也就是为了提升系统的可用性而组合多台主机构成的集群.

另外, 向我们之前做的keepalived实验, 假设两台keepalived节点之间出现了问题, 导致无法正常通信. 于是两个keepalived进程都认为对方挂掉了, 所以都主动的成为了Master, 这样就会将这个集群系统分裂开来, 我们把这种状态称为脑裂( split brain ). 集群就变成了partitioned cluster. 这样的话就会造成大量的问题. 比如会造成后端的数据写入紊乱导致整个文件系统损坏的情况就是很可能发生的一件事.

所以, 我们就要想办法解决脑裂的问题, 对于高可用集群而言, 一种解决方法就是, 一旦我要成为主节点, 那么就要确保原本的那个主节点是真的挂掉了, 所以就会想法设法把他搞死, 这样就可以放心的解决资源争用问题. 但是这样又存在一个问题, 这不就自相矛盾了吗? 我们原本为了得到高可用, 为节点添加了双电源的设定, 结果到了这个时候, 双电源反而成为了我们的绊脚石.

先不考虑这个情况, 我们来看另一种状态. 刚刚和以前我们一直都是在说两台director的场景, 这个时候其实到没有这么复杂. 而如果我们的前端负载均衡集群有5个或者更多呢? 这个时候假设主机之前通过心跳机制进行存活宣告, 突然. 节点1,2,3和节点4,5出现了断层: 123之间可以正常通信, 45之间也可以正常通信, 但是他们之间被分割了. 怎么办? 这个时候联想到我们之前说的vrrp协议, 我们需要进行投票和选举. 假如说原本我们的5台主机有一个主持人, 该主持人收集所有的心跳信息, 监控全部的主机. 突然发现一次收到的包只有123的了, 而没有了45的, 而45因为找不到了主持人, 于是他们之间又会互相选举出一个新的主持人, 这样出现两个主持, 对于一开始我们设定的主持人发现现在只有3个主机给自己发消息, 于是就会认定45两个节点是离开了自己的管理. 所以就会想办法把45毙掉. 也就是把他们干掉了.

在这个过程中, 一个核心是我们的vote system. 也就是解决的问题是在发生了脑裂的情况的时候, 怎么判定那些主机仍旧作为集群活动. 一般我们使用的还是少数服从多数的原则. 而且我们一般的节点数量都是奇数, 这样就可以确保不会出现票数一致的情况. 那么如果我确实就是2个节点怎么办? 一般在这种情况下, 我们可以选择一个第三方的公信机构来判定, 比如一个共享硬盘和一个网关都可以. 一旦节点发现共享硬盘可写, 或者网关可以访问就说明另外一边没有过来, 也就是我现在就是主节点.

事实上, 对现在的高可用集群框架, 也主要分成这两个流派, 其中社区最活跃, 最丰富的一个就是少数服从多数的原则. 对于这个原则我们提出的一个概念就是quorum 也就是法定人数, 法定票数. 而获得多数票数的状态就被称为with quorum. 另外一个的状态就是without quorum.

另外一个流派就是使用仲裁设备的流派, 也就是使用一个quorum disk( qdisk for short ), 或者一个ping node来进行判定. 但是除了这两个, 难道就没有别的吗? 当然不是, 我们前几天玩的那个keepalived, 就不属于这两种的. 我们知道keepalived提供的高可用方案是基于vrrp协议实现的. 当然这不是今天讨论的主题, 就不说了.

现在回到我们说的资源转移的问题, 当一个节点服务不可用( 注意:这里我说的是服务不可用, 机器可能是好的 )的时候, 另一台主机一定是需要将IP地址夺过来, 相同的调度规则, 配置文件保持一致, 甚至需要将保持页面文件的一致. 在这一段时间内, 服务必然是不可用的. 这一转移的过程我们称作fail over. 在原先的节点恢复正常了之后, 如果两台主机的性能一样我也未必需要将资源转移回去, 但是一般我们的主节点的性能都是优于备用节点的嘛, 这一转移回来的过程, 我们把它叫做fail back.

但是, 当一方出现了without quorum的情况下, 这一方的资源该如何处理? 是否应该转移过去? 如果资源是存在在内存中的, 岂不是就不能转移过去了? 这个时候 我们要注意到的一点, 他们的服务是正常的, 也就是说其实仍然可用, 只不过发生了隔离. 所以说对于像这样的状况, 我们有多种方法除了上面的资源: 停止(stop), 忽略(ignore), 冻结(freeze), 自杀(suicide). 所谓冻结其实就是原先建立的连接仍然在上面, 只不过如果有新的连接到了的话, 就去有法定票数的那一方.

对于我们的集群模型, 也分成很多工作模型, 例如常见的A/P, 即两节点模型Active和Passive, 例如A/A, 双主模型, 例如N-M, N个节点M个服务, 通常N>M, 再如, N-N, N节点N服务.

我们进行监控和心跳, 不仅是监测服务是否可用, 还需要想办法监控资源的可用状态, 对于这些资源本身而言, 他们需要意识到自己是否是可用的, 以及自己如何根据高可用集群的心跳机制做出自己的转移决策. 也就是在两个主机都安装相同的服务, 他们工作在同一层, 并且互相通信, 我们就把这一个层面称作高可用集群的集群事务信息层. 有了这么一个层次, 我们就可以面向这个信息层的API进行程序设计使得我们可以实现对资源的探测以及转移决策了

但是, 我们之前不论说nginx, httpd的时候都没有提到过他们有这样的功能呀? 事实就是如此, 如果说想要实现高可用我都要面向这个一个层面去进行编程, 那局限性也太大了. 所以就有人在这个层面的上层进行了一层通用的抽象出现了一个叫做CRM的层面, 也就是cluster resource manager. 这样一来只要这些服务和应用程序纳入manager的管理范围, 我们就可以根据配置, 根据程序特性判定那些硬件资源对于他们来说是优先级更高的. 也就是说, 启动CRM之后, 资源就会被得到监控以及如果出现问题, CRM会帮助他们进行决策和转移.

而且在转移的时候, 各个资源之间还必然存在这先后顺序, 以及依赖关系, 除此之外, 还会有一个资源粘性的概念. 这些顺序和关系一般都这几种:

  • location: 位置约束, 资源更倾向于哪一个节点 ( -00, +00 )
  • colocation: 排列约束, 资源彼此之间的倾向性. ( -00, +00 ). 还可以使用分组的方式来绑定资源
  • order: 顺序约束, 资源在同一个节点上的启动顺序. 在这种情况下, 如果前面的资源无法启动, 后面的也不会启动, 停止亦是如此.

除了顺序和关系, 资源还有根据工作模式的不同, 分成很多种类:

  • primitive: 主资源. 只能运行在一个节点上 (native)
  • group: 组资源, 包含一个或者多个资源. 他们可以通过这个资源进行统一调度
  • clone: 克隆资源, 可以在同一个集群的多个节点运行多个克隆
  • master/slave: 主从资源, 在同一个集群内部运行在两个节点, 其中一个为主一个为从.

这样再加上我们的CRM承上启下, 构成一个资源和决策的全貌图. 以上就是我们的高可用集群的一个基础概念了.

这样就完了? 当然不, 其实在我们的CRM上面还有一个层面. 这个层面的存在意义是什么? 先来想这样的问题, 我们启动一个服务就是使用systemctl start/stop XX.service或者service XX start/stop. 但是对于文件系统 , 对于IP地址, 我们就不能进行start/stop了. 如果每一资源都由管理员手动告诉CRM怎么启动, 挂载, 设置. 那也太麻烦了. 所以我们抽象出一个新的层次, 也就是LRM. local resource manager. 这个层面一般都是集群服务提供的. 但是他仍然不能直接做出资源启动关闭的决策, 所以向上再加一个层次, 也就是RA, resource agent. 这个代理能够实现对资源的管理, 一般RA的实现都是通过脚本. 这些脚本其实就是RA.

也就是这样的架构:

ha

说完了整个组成, 之前关于毙掉, 补刀机制 我们没怎么详说, 现在来补充一下, 在高可用集群中, 这种机制被称作资源隔离机制. 隔离也是存在级别的, 比如:

  • 节点隔离 , 最彻底的一种机制: STONITH ( Shooting The Other Node In The Head ) 典型的方案是断电, 通过电源交换机
  • 资源隔离, fencing. 典型的方案是, 关闭共享存储的连接, 例如 FC SAN Switch

HA集群的解决方案

我们将这个HA架构分成了这些层面, 其实每一个层面都会有一个单独的程序来运行, 当然也有全栈的程序. 现在我们就来说说比较有名的一些解决方案:
首先是我们的基础架构层, 也就是信息传递的层面:

  • heartbeat v1 v2 v3, 其中, v1和v2都可以实现全栈的HA解决方案 而v3中, heartbeat分成三个组件, 然而作为信息传递层, heartbeat已经不再具有优势
  • corosync, 是目前比较流行的解决方案, 比heartbeat v3更灵活, 功能更强大
  • cman, 是红帽的集群解决方案(RedHat, RHCS)中的一个部件.
  • 接着还有我们之前玩过的keepalived, 但是这个玩意的工作模式和上面的三个完全不一样, 只不过他同样实现了信息传递的功能.

接着来看一下我们的CRM层:

  • heartbeat v1 haresources, 他的配置接口是通过配置文件, 文件名就是haresoources
  • heartbeat v2 crm (就叫做crm, 在各个节点都会由一个crmd进程, 这样各节点都可以通过crmd完成各个crm的衔接, 配置接口有CLI: crmsh, 还有GUI: hb_gui)
  • heartbeat v3 pacemaker, 从hb中独立出来, 十分受欢迎的一个解决方案, pacemaker可以通过插件或者独立的方式运行, 配置接口CLI: crmsh, pcs. GUI: hawk(webgui))
  • rgmanager, 红帽的套件之一, 配置接口CLI: clustat, cman_tool. GUI: Conga ( luci+ricci ), 可以实现全生命周期管理.

而我们的组合方式有这些:

  • heartbeat v1
  • heartbeat v2
  • heartbeat + pacemaker
  • corosync + pacemaker
  • cman + rgmanager
  • cman + pacemaker

而LRM基本上都是由CRM的子程序提供的.

最后还有一个RA, 主要有这些:

  • heartbeat legacy: heartbeat传统类型的RA, 通常位于/etc/ha.d/haresources.d下
  • LSB: Linux Standard Base, /etc/rc.d/init.d/目录下, 至少接受四种参数: {start|stop|restart|status}
  • OCF
  • STONITH: 转用于实现调用STONITH设备功能的资源, 通常为clone类型.

另外, 我们在之前的keepalived中说道过, 如果是配置HA集群, 要求主机名必须能够解析到IP地址, 所以推荐把主机名和IP地址写到hosts中, 另外, 现在我们有了上面的概念, 再次补充两条不过只是建议罢了, 首先我们的节点之间root用户能够使用密钥进行认证, 还有如果是偶数节点考虑是否会用到仲裁设备.

另外, 作为集群服务的资源, 绝对不能开机自动启动, 他们是由crm管理的.

基于Heartbeat v1实现HA Cluster

之前说过, heartbeat其实现在热度不是很高, 所以选择CentOS6作为我们的节点. 在epel源上有我们的heartbeat,, 所以可以直接使用yum安装.

安装过程很简单, 我就省略了.

安装完成之后我们来看一下,:

1
2
3
4
5
6
[root@VM-node3 ~]# cd /etc/ha.d/
[root@VM-node3 ha.d]# ls
harc rc.d README.config resource.d shellfuncs
[root@VM-node3 ha.d]# ls resource.d/
apache db2 Filesystem ICP IPaddr IPsrcaddr LinuxSCSI MailTo portblock SendArp WAS Xinetd
AudibleAlarm Delay hto-mapfuncs ids IPaddr2 IPv6addr LVM OCF Raid1 ServeRAID WinPopup

在他的配置目录/etc/ha.d下, 我们需要用到的文件默认一个也没有, 但是我们是可以从resource.d中看到heartbeat用来进行资源代理的脚本.

heartbeat所需要的配置文件有三个: ha.cf 这个是主配置文件, 用来定义各个节点上的heartbeat HA集群的基本属性, authkeys 这个是用来鉴别心跳信息的, 也就是个签名罢了, 使用的是单向加密算法, 即指纹, haresource 并不是必须的, 为heartbeat v1提供的资源管理器接口.

在安装完成的文件中, 有生成的hb配置文件的样例, 我们把他们复制出来看一下:

1
2
3
[root@VM-node3 ha.d]# cp /usr/share/doc/heartbeat-3.0.4/{authkeys,haresources,ha.cf} /etc/ha.d/
[root@VM-node3 ha.d]# ls
authkeys ha.cf harc haresources rc.d README.config resource.d shellfuncs

接下来要说一点, 我们的authkeys必须将权限设置成600才可以, 否则集群会直接拒绝启动.

1
[root@VM-node3 ha.d]# chmod 600 authkeys 

好了, 现在从authkey开始, 我们来配置一下我们的heartbeat. 通过使用不同的算法来指定密钥. auth关键字指定使用哪种方式的密钥.

1
2
3
4
auth 2
#1 crc
2 sha1 CPdolTm2dLkGUg
#3 md5 Hello!

可以使用openssl生产随机字串:

1
2
[root@VM-node3 ha.d]# openssl rand -base64 10
CPdolTm2dLkGUg==

这样就可以了. 接着我们来看一下主角 – ha.cf :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
debugfile /var/log/ha-debug # debug信息的输出
logfile /var/log/ha-log # 日志文件位置
logfacility local0 # rsyslog的facility属性, 如果指明了日志文件这个就不用说明了
keepalive 2 # 发送心跳包的时间间隔
deadtime 30 # 死亡时间: 宣言对方主机死亡的时间间隔
warntime 10 # 警告时间: 没有收到心跳包之后多久发送
initdead 120 # 首次死亡时间, 最小应该是死亡时间的2倍 (考虑刚启动的时候网络服务启动)
udpport 694 # UDP端口, 该694是标准
baud 19200 # 使用串口的频率
serial /dev/ttyS0 # 串口位置
bcast eth1 eth2 # 广播的网卡, 可以写多个
mcast eth0 225.0.0.1 694 1 0 # 组播, 值有: 接口 地址 端口 ttl 是否循环
ucast eth0 192.168.1.2 # 也支持单播
auto_failback on # 是否开启自动资源回滚
node ken3 # 集群中有哪些节点 这里的值需要和hostname一致
ping 10.10.10.254 # ping node, 仲裁设备之ping node
ping_group group1 10.10.10.254 10.10.10.253 # 如果一个不够可以指定一组
compression bz2 # 是否压缩, 以及使用哪种算法
compression_threshold 2 # 压缩的门槛, 单位是Kb.

主要就是上面的那些配置, 注释都直接写上了.

我最后的配置结果是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
logfile /var/log/ha-log
keepalive 2
deadtime 10
warntime 5
initdead 20
mcast eth0 225.1.206.1 694 1 0
auto_failback on
node VM-node3
node VM-node4
ping 192.168.206.2
compression bz2
compression_threshold 4

OK, 接下来就是最后一个配置了, 我们来瞅瞅haresource:

1
#just.linux-ha.org      135.9.216.3/28/eth0/135.9.216.12 httpd

文件很短, 核心就是这样的配置, 现在我们先简单的配置一下, 更复杂的语法过会说, 这里配置的就是:

节点名 IP地址/子网掩码/网卡接口/广播地址 服务

这个是存在顺序的, 也就是从左到右顺序执行.

那么对于我们的情况应该这样配置:

1
VM-node3        192.168.206.11/24/eth0/192.168.206.255  httpd

现在就可以启动了. 但是别急, 我们需要另一台主机也保持几乎一样的配置才行, 所以先复制过去:

1
2
3
4
[root@VM-node3 ha.d]# scp authkeys ha.cf haresources VM-node4:/etc/ha.d/
authkeys 100% 655 0.6KB/s 00:00
ha.cf 100% 200 0.2KB/s 00:00
haresources 100% 5959 5.8KB/s 00:00

接着, 由于另一边的网卡名称不一样, 所以我稍作了修改.

接着两边就可以启动服务了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@VM-node3 ha.d]# tail /var/log/ha-log 
harc(default)[11491]: 2017/10/21_22:10:20 info: Running /etc/ha.d//rc.d/ip-request-resp ip-request-resp
ip-request-resp(default)[11491]: 2017/10/21_22:10:20 received ip-request-resp 192.168.206.11/24/eth0/192.168.206.255 OK yes
ResourceManager(default)[11512]: 2017/10/21_22:10:20 info: Acquiring resource group: vm-node3 192.168.206.11/24/eth0/192.168.206.255 httpd
/usr/lib/ocf/resource.d//heartbeat/IPaddr(IPaddr_192.168.206.11)[11539]: 2017/10/21_22:10:20 INFO: Resource is stopped
ResourceManager(default)[11512]: 2017/10/21_22:10:20 info: Running /etc/ha.d/resource.d/IPaddr 192.168.206.11/24/eth0/192.168.206.255 start
IPaddr(IPaddr_192.168.206.11)[11663]: 2017/10/21_22:10:20 INFO: Adding inet address 192.168.206.11/24 with broadcast address 192.168.206.255 to device eth0
IPaddr(IPaddr_192.168.206.11)[11663]: 2017/10/21_22:10:20 INFO: Bringing device eth0 up
IPaddr(IPaddr_192.168.206.11)[11663]: 2017/10/21_22:10:20 INFO: /usr/libexec/heartbeat/send_arp -i 200 -r 5 -p /var/run/resource-agents/send_arp-192.168.206.11 eth0 192.168.206.11 auto not_used not_used
/usr/lib/ocf/resource.d//heartbeat/IPaddr(IPaddr_192.168.206.11)[11637]: 2017/10/21_22:10:21 INFO: Success
ResourceManager(default)[11512]: 2017/10/21_22:10:21 info: Running /etc/init.d/httpd start
[root@VM-node3 ha.d]# ss -tnl
Recv-Q Send-Q Local Address:Port Peer Address:Port
0 128 :::80 :::*

httpd服务也自动启动了.

访问试试:

1
2
3
4
5
6
7
C:\Users\lenovo
λ curl 192.168.206.11
<h1>It works! (From node3)</h1>

C:\Users\lenovo
λ curl 192.168.206.11
<h1>It works! (From node3)</h1>

现在我们把第一个节点的heartbeat服务停掉, 继续访问, 几乎没有延迟:

1
2
3
4
5
6
7
C:\Users\lenovo
λ curl 192.168.206.11
<h1>web on Node4</h1>

C:\Users\lenovo
λ curl 192.168.206.11
<h1>web on Node4</h1>

也可以看到夺取资源相关的日志记录:

1
2
3
4
5
6
7
8
9
10
11
[root@VM-node4 ha.d]# tail /var/log/ha-log 
IPaddr(IPaddr_192.168.206.11)[8311]: 2017/10/21_22:14:19 INFO: Bringing device eth2 up
IPaddr(IPaddr_192.168.206.11)[8311]: 2017/10/21_22:14:19 INFO: /usr/libexec/heartbeat/send_arp -i 200 -r 5 -p /var/run/resource-agents/send_arp-192.168.206.11 eth2 192.168.206.11 auto not_used not_used
/usr/lib/ocf/resource.d//heartbeat/IPaddr(IPaddr_192.168.206.11)[8285]: 2017/10/21_22:14:19 INFO: Success
ResourceManager(default)[8160]: 2017/10/21_22:14:19 info: Running /etc/init.d/httpd start
mach_down(default)[8134]: 2017/10/21_22:14:19 info: /usr/share/heartbeat/mach_down: nice_failback: foreign resources acquired
mach_down(default)[8134]: 2017/10/21_22:14:19 info: mach_down takeover complete for node vm-node3.
Oct 21 22:14:19 VM-node4 heartbeat: [8018]: info: mach_down takeover complete.
Oct 21 22:14:29 VM-node4 heartbeat: [8018]: WARN: node vm-node3: is dead
Oct 21 22:14:29 VM-node4 heartbeat: [8018]: info: Dead node vm-node3 gave up resources.
Oct 21 22:14:29 VM-node4 heartbeat: [8018]: info: Link vm-node3:eth2 dead.

这个时候我们回复Node3的服务, 由于设置了fail back, 所以资源会重新夺回来才对:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[root@VM-node3 ha.d]# service heartbeat start && tail -f /var/log/ha-log 
Starting High-Availability services: INFO: Resource is stopped
Done.

Oct 21 22:17:33 VM-node3 heartbeat: [12105]: info: Configuration validated. Starting heartbeat 3.0.4
Oct 21 22:17:33 VM-node3 heartbeat: [12106]: info: heartbeat: version 3.0.4
Oct 21 22:17:34 VM-node3 heartbeat: [12106]: info: Heartbeat generation: 1508594079
Oct 21 22:17:34 VM-node3 heartbeat: [12106]: info: glib: UDP multicast heartbeat started for group 225.1.206.1 port 694 interface eth0 (ttl=1 loop=0)
Oct 21 22:17:34 VM-node3 heartbeat: [12106]: info: glib: ping heartbeat started.
Oct 21 22:17:34 VM-node3 heartbeat: [12106]: info: G_main_add_TriggerHandler: Added signal manual handler
Oct 21 22:17:34 VM-node3 heartbeat: [12106]: info: G_main_add_TriggerHandler: Added signal manual handler
Oct 21 22:17:34 VM-node3 heartbeat: [12106]: info: G_main_add_SignalHandler: Added signal handler for signal 17
Oct 21 22:17:34 VM-node3 heartbeat: [12106]: info: Local status now set to: 'up'
Oct 21 22:17:34 VM-node3 heartbeat: [12106]: info: Link 192.168.206.2:192.168.206.2 up.
Oct 21 22:17:34 VM-node3 heartbeat: [12106]: info: Status update for node 192.168.206.2: status ping
Oct 21 22:17:36 VM-node3 heartbeat: [12106]: info: Link vm-node4:eth0 up.
Oct 21 22:17:36 VM-node3 heartbeat: [12106]: info: Status update for node vm-node4: status active
harc(default)[12118]: 2017/10/21_22:17:36 info: Running /etc/ha.d//rc.d/status status
Oct 21 22:17:36 VM-node3 heartbeat: [12106]: info: Comm_now_up(): updating status to active
Oct 21 22:17:36 VM-node3 heartbeat: [12106]: info: Local status now set to: 'active'
Oct 21 22:17:37 VM-node3 heartbeat: [12106]: info: remote resource transition completed.
Oct 21 22:17:37 VM-node3 heartbeat: [12106]: info: remote resource transition completed.
Oct 21 22:17:37 VM-node3 heartbeat: [12106]: info: Local Resource acquisition completed. (none)
Oct 21 22:17:37 VM-node3 heartbeat: [12106]: info: vm-node4 wants to go standby [foreign]
Oct 21 22:17:38 VM-node3 heartbeat: [12106]: info: standby: acquire [foreign] resources from vm-node4
Oct 21 22:17:38 VM-node3 heartbeat: [12137]: info: acquire local HA resources (standby).
ResourceManager(default)[12150]: 2017/10/21_22:17:38 info: Acquiring resource group: vm-node3 192.168.206.11/24/eth0/192.168.206.255 httpd
/usr/lib/ocf/resource.d//heartbeat/IPaddr(IPaddr_192.168.206.11)[12177]: 2017/10/21_22:17:38 INFO: Resource is stopped
ResourceManager(default)[12150]: 2017/10/21_22:17:38 info: Running /etc/ha.d/resource.d/IPaddr 192.168.206.11/24/eth0/192.168.206.255 start
IPaddr(IPaddr_192.168.206.11)[12301]: 2017/10/21_22:17:38 INFO: Adding inet address 192.168.206.11/24 with broadcast address 192.168.206.255 to device eth0
IPaddr(IPaddr_192.168.206.11)[12301]: 2017/10/21_22:17:38 INFO: Bringing device eth0 up
IPaddr(IPaddr_192.168.206.11)[12301]: 2017/10/21_22:17:38 INFO: /usr/libexec/heartbeat/send_arp -i 200 -r 5 -p /var/run/resource-agents/send_arp-192.168.206.11 eth0 192.168.206.11 auto not_used not_used
/usr/lib/ocf/resource.d//heartbeat/IPaddr(IPaddr_192.168.206.11)[12275]: 2017/10/21_22:17:38 INFO: Success
ResourceManager(default)[12150]: 2017/10/21_22:17:38 info: Running /etc/init.d/httpd start
Oct 21 22:17:38 VM-node3 heartbeat: [12137]: info: local HA resource acquisition completed (standby).
Oct 21 22:17:38 VM-node3 heartbeat: [12106]: info: Standby resource acquisition done [foreign].
Oct 21 22:17:38 VM-node3 heartbeat: [12106]: info: Initial resource acquisition complete (auto_failback)
Oct 21 22:17:39 VM-node3 heartbeat: [12106]: info: remote resource transition completed.

再次访问也可以看出来:

1
2
3
4
5
6
7
C:\Users\lenovo
λ curl 192.168.206.11
<h1>It works! (From node3)</h1>

C:\Users\lenovo
λ curl 192.168.206.11
<h1>It works! (From node3)</h1>

OK, 以上就是heartbeat基本的设定和一个简单的实现.

现在,我们继续. 假设网页文件来源于一个NFS怎么样呢?

开启一台新的主机作为共享存储. 首先我们先进行一下NFS的相关设定, 接着试着用Web主机进行挂载, 接着直接访问IP试试:

1
2
3
4
5
6
7
[root@VM-node3 ~]# mount -t nfs 192.168.206.9:/data/web /var/www/html/
[root@VM-node3 ~]# mount
...(omitted)
192.168.206.9:/data/web on /var/www/html type nfs (rw,vers=4,addr=192.168.206.9,clientaddr=192.168.206.22)
[root@VM-node3 ~]# service httpd restart
Stopping httpd: [ OK ]
Starting httpd: [ OK ]

访问的结果:

1
2
3
C:\Users\lenovo
λ curl 192.168.206.22
<h1>Web Page on NFS</h1>

行了, 另外一个节点也可以做这样的操作试试. 试完了之后一定要记得把服务停止, 卸载NFS.

接着我们来编辑一下haresource, 可是文件系统的挂载怎么写啊? 在/etc/ha.d/resource.d中有一个脚本叫做Filesystem, 这就是为了挂载文件系统的:

1
VM-node3        192.168.206.11/24/eth0/192.168.206.255  Filesystem::192.168.206.9:/data/web::/var/www/html::nfs httpd

另外一边要保持一致.

接着开启服务 ( 开启之前要确定httpd服务关闭, 并且没有挂载到NFS )

1
2
3
C:\Users\lenovo
λ curl 192.168.206.11
<h1>Web Page on NFS</h1>

访问是正常的, 而且可以看到node4没有挂载到NFS,只有node3绑定IP, 挂载上了NFS. 接着尝试关闭node3的heartbeat服务, 可以发现, 挂载自动消失, 另外一边(node4)已经挂载上了NFS, 并且也工作正常. 当服务恢复的时候, 资源被夺回, node4上的挂载也消失了.