内容简介
Heartbeat是一款开源程序,负责将集群基础设施容量——包括集群成员与消息收发——交付至客户服务器。Hearbeat在高可用性服务器基础设施当中扮演着关键性角色。我们通常需要将Heartbeat与Pacemaker等集群资源管理器(简称CRM)相结合,从而实现完整的高可用性设置。不过在今天的教程中,我们将演示如何利用Heartbeat与DigitalOcean Floating IP轻松创建一套双节点高可用性服务器设置。
如果大家希望进一步提升可用性水平,不妨尝试Corosync与Pacemaker这一组合或者Keepalived。
目标设定
在完成之后,这套高可用性设置将由两台Ubuntu 14.04服务器建立的主动/被动配置构成。要实现这项目标,我们需要借助Floating IP——负责指定用户访问服务或者网站的实际方式——以指向主服务器或者说活动服务器,除非其检测到该服务器存在故障。一旦Hearbeat服务发现主服务器不可用,第二台服务器将自动运行一套脚本以将Floating IP通过DigitalOcean API重新分配给自己。如此一来,指向Floating IP的后续网络流量将会被定向至我们的辅助服务器,并在主服务器恢复正常之前由其担任活动服务器的角色(在主服务器恢复正常后,其同样会将Floating IP分配给自己以实现切换)。
备注:今天的教程只涉及在网关层级设置主动/被动高可用性体系,其中包含Floating IP以及负载均衡服务器——主服务器与副服务器。此外,出于演示的目的,我们不会为每台服务器配置反向代理负载均衡器,而是通过简单配置使其分别响应对应的主机名与公共IP地址。
为实现这一目标,我们将采取以下步骤:
创建2个Droplet用于接收流量
创建Floating IP并将其分别给其中1个Droplet
创建DNS A记录并指向Floating IP(可选)
在2个Droplet上安装Heartbeat
配置Heartbeat以运行Floating IP重新分配服务
创建Floating IP重新分配服务
测试故障转移效果
先决条件
为了实现Floating IP的自动重新分配,我们必须使用DigitalOcean API。这意味着大家需要生成一条个人访问令牌(简称PAT),该API令牌能够用于认证我们的DigitalOcean账户,并根据API指南部分《如何生成个人访问令牌》(https://www.digitalocean.com/community/tutorials/how-to-use-the-digitalocean-api-v2#how-to-generate-a-personal-access-token)章节的指导实现读取与写入访问。大家的PAT将通过脚本进行使用,而该脚本则被添加至集群中的两台服务器内,从而确保其安全访问DIgitalOcean账户以供引用。
除了该API,这分教程还将采用以下DigitalOcean元素:
Floating IPs(https://www.digitalocean.com/community/tutorials/how-to-use-floating-ips-on-digitalocean)
Metadata(https://www.digitalocean.com/community/tutorials/an-introduction-to-droplet-metadata)
用户数据(云配置脚本)(https://www.digitalocean.com/community/tutorials/an-introduction-to-cloud-config-scripting)
大家可以点击对应链接了解更多与之相关的细节信息。
创建Droplet
第一步是在同一数据中心之内创建2个Ubuntu Droplet,二者将分别作为之前所提到的主、副服务器。在我们的示例设置当中,二者将分别被命名为“primary”与“secondary”以便于引用。我们将在2个Droplet上分别安装Nginx并利用其惟一标识信息替换掉其索引页。通过这种方式,我们能够轻松证明这套高可用性设置是否实际起效。在真实设置当中,大家的服务器应当根据实际需求运行Web服务器或者负载均衡器。
创建2个Ubuntu 14.04 Droplet,分别为primary与secondary,而以下bash脚本则作为用户数据:
用户数据示例:
#!/bin/bash
apt-get -y update
apt-get -y install nginx
export HOSTNAME=$(curl -s http://169.254.169.254/metadata/v1/hostname)
export PUBLIC_IPV4=$(curl -s http://169.254.169.254/metadata/v1/interfaces/public/0/ipv4/address)
echo Droplet: $HOSTNAME, IP Address: $PUBLIC_IPV4 > /usr/share/nginx/html/index.html
此脚本将安装Nginx并利用该Droplet的主机名称与IP地址(通过引用Metadata服务)替换index.html的内容。在通过公共IP地址进行访问时,对应Droplet将显示一套包含该Droplet主机名称与IP地址的基本页面,帮助用户测试任意时段内该Floating IP指向哪个Droplet。
创建Floating IP
在DigitalOcean控制面板中,点击顶部菜单中的“Networking”,接下来在后续菜单中选定“Floating IPs”。
为我们的primary Droplet分配一个Floating IP,而后点击“Assign Floating IP”按钮。
在Floating IP分配完成后,通过网络浏览器对该IP进行访问,以确认其被正确分配至既定Droplet。
http://your_floating_ip
这时大家应该能够看到自己的primary Droplet索引页。
配置DNS(可选)
如果大家希望通过域名访问自己的主可用性设置,则可在DNS当中创建一条A记录,其负责将域名指向对应的Floating IP地址。如果大家的域名使用DigitalOcean的域名服务器,则可遵循《如何利用DigitalOcean设置一项主机名称》教程中的第三步指引(https://www.digitalocean.com/community/tutorials/how-to-set-up-a-host-name-with-digitalocean#step-three%E2%80%94configure-your-domain)。设置完成后,大家即可通过该域名访问自己的活动服务器。
在这里我们使用的示例域名为example.com。如果大家暂时没有域名可用,则应使用Floating IP地址。
安装Heartbeat
下一步是在两台服务器上安装Heartbeat。最简单的Heartbeat安装方式自然是使用apt-get:
sudo apt-get update
sudo apt-get install heartbeat
Heartbeat现在已经安装完成,不过我们需要对其进行配置才能让它正常发挥作用。
配置Heartbeat
为了保证集群正常启动与运行,我们必须在/etc/ha.d目录下的文件中进行Heartbeat配置——两台服务器均采用同样的配置方式:
ha.cf: Heartbeat集群的全局配置,包括其各成员节点。
authkeys: 添加一个安全密钥以保证集群对节点进行验证。
haresources: 指定由集群管理的服务以及作为该服务持有者的对应节点。需要注意,我们在通过Pacemaker等CRM方案进行设置时无需使用此文件。
我们还需要提供一套脚本,负责在primary Droplet的可用性发生变更时执行Floating IP重新分配。
收集节点信息
在对ha.cf进行配置之前,我们应当首先查看各节点名称。Heartbeat要求每个节点的名称与其对应的uname -n输出结果相匹配。
在两台服务器上运行以下命令,旨在查找对应的节点名称:
* uname -n
请注意该命令的输出结果。示例中的节点名称为“primary”与“secondary”,与我们的Droplet命名完全匹配。
我们还需要查看各个节点用于同集群内其它节点进行通信的网络接口与IP地址,从而了解当前哪些节点处于可用状态。大家可以使用任意网络接口,只要确保集群内各节点的相互通信能力即可。在这里我们使用Droplet的公共接口,恰好为eth0。
在两台服务器上,使用以下命令以查找eth0接口的IP地址(或者通过DigitalOcean控制面板进行查看):
* ip addr show eth0
ip addr show eth0 output:
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 04:01:76:a5:45:01 brd ff:ff:ff:ff:ff:ff
inet 104.236.6.11/18 brd 104.236.63.255 scope global eth0
valid_lft forever preferred_lft forever
inet 10.17.0.28/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::601:76ff:fea5:4501/64 scope link
valid_lft forever preferred_lft forever
请注意该网络接口的IP地址(在本示例中以高亮显示)。确保获取两台服务器的对应IP地址。
创建ha.cf文件
在两台服务器上利用大家熟悉的编辑器打开/etc/ha.d/ha.cf文件。我们在这里使用vi:
* sudo vi /etc/ha.d/ha.cf
该文件的内容此次应当为空。我们需要向其中添加集群内各节点的网络接口与名称。
将该配置复制并粘贴到此文件当中,而后利用前面查找到的对应主机名称与IP地址替换其中的具体值。在本次示例中,primary的IP地址为104.236.6.11,而secondary的IP地址为104.236.6.22:
node primary
ucast eth0 104.236.6.11
node secondary
ucast eth0 104.236.6.22
保存并退出。接下来,我们将设置这套集群的验证密钥。
创建authkeys文件
验证密钥的作用是允许各集群成员加入集群。出于这一目的,我们可以轻松创建一条随机密钥。
在primary节点当中运行以下命令,从而在名为AUTHKEY的环境变量当中生成一条合适的验证密钥:
if [ -z "${AUTH_KEY}" ]; then
export AUTH_KEY="$(command dd if='/dev/urandom' bs=512 count=1 2>'/dev/null' \
| command openssl sha1 \
| command cut --delimiter=' ' --fields=2)"
fi
后来利用以下命令编写/etc/ha.d/authkeys 文件:
sudo bash -c "{
echo auth1
echo 1 sha1 $AUTH_KEY
} > /etc/ha.d/authkeys"
通过以下命令检查该authkeys文件内容:
* sudo cat /etc/ha.d/authkeys
执行结果应该如下所示(只是具体验证密钥有所区别):
/etc/ha.d/authkeys example:
auth1
1 sha1 d1e6557e2fcb30ff8d4d3ae65b50345fa46a2faa
确保该文件只可供root读取:
sudo chmod 600 /etc/ha.d/authkeys
现在将该/etc/ha.d/authkeys 文件从primary节点复制到我们的secondary节点当中。大家可以通过手动方式或者利用scp实现。
在secondary服务器上,确保对该authkeys文件的权限进行设置:
sudo chmod 600 /etc/ha.d/authkeys
现在两台服务器应该已经拥有相同的/etc/ha.d/authkeys 文件了。
创建haresources文件
这里的haresources文件负责指定与集群所管理的各项服务对应的preferred host。所谓preferred host即首选主机,指服务在对应节点处于可用状态时应优先选择的运行选项。如果首选主机不可用,即无法由集群接入,则另一节点则将接掌其职责。换言之,secondary服务器将在primary服务器发生故障时顶替其角色。
在两台服务器上通过大家熟悉的编辑器打开该haresources文件。在这里我们使用vi:
sudo vi /etc/ha.d/haresources
现在将以下一行添加至该文件中,并将我们自己的primary节点名称替换进去:
/etc/ha.d/haresources
primary floatip
保存并退出。现在该primary服务器已经被配置为floatip服务的首选主机,不过floatip服务本身尚未进行定义。因此下一步任务就是设置floatip服务。
创建Floating IP重新分配服务
我们的Heartbeat集群的配置目标在于保证floatip服务能够始终正常运行,其中一个节点用于将Floating IP分配给自身。不过这项服务本身也需要单独创建。在设置服务本体之前,我们首先创建一套脚本,用于通过DigitalOcean API将该Floating IP分配至其运行所在的节点。接下来,我们将创建负责运行该Floating IP重新分配脚本的floatip服务。
创建assign-ip脚本
在示例中,我们将下载一套基础Python脚本以利用DigitalOcean API向给定Droplet ID分配一个Floating IP。
在两台服务器上下载该assign-ip Python脚本:
sudo curl -L -o /usr/local/bin/assign-ip http://do.co/assign-ip
在两台服务器上为其提供执行权限:
sudo chmod +x /usr/local/bin/assign-ip
使用assign-ip脚本还需要注意以下细节:
Floating IP: 该脚本中的第一项参数,指定需要分配的Floating IP。
Droplet ID: 该脚本中的第二项参数,指定该Floating IP被分配到的Droplet ID。
DigitalOcean PAT (API令牌): 作为环境变量DOTOKEN进行传递,即我们的读取/写入DigitalOcean PAT。
在进行下一步之前,请大家认真审查这部分脚本内容。
现在我们已经做好了创建floatip服务的一切准备。
创建floatip服务
要创建floatip服务,我们需要首先创建一个init脚本以调用此前编写完成的assign-ip脚本,同时响应start与stop子命令。该init脚本将负责通过Droplet Metadata服务查找服务器的Droplet ID。另外,该脚本还需要获取被分配Floating IP以及DigitalOcean API令牌(即我们在先决条件部分中提到过的个人访问令牌)。
在两台服务器上,利用编辑器打开/etc/init.d/floatip :
sudo vi /etc/init.d/floatip
而后将以下内容复制并粘贴到init脚本当中,同时利用大家自己的DigitalOcean API密钥与需要分配的Floating IP替换其中的高亮部分:
/etc/init.d/floatip
#!/bin/bash
param=$1
export DO_TOKEN='b7d03a6947b217efb6f3ec3bd3504582'
IP='45.55.96.8'
ID=$(curl -s http://169.254.169.254/metadata/v1/id)
if [ "start" == "$param" ] ; then
python /usr/local/bin/assign-ip $IP $ID
exit 0
elif [ "stop" == "$param" ] ; then
exit 0;
elif [ "status" == "$param" ] ; then
exit 0;
else
echo "no such command $param"
exit 1;
fi
保存并退出。
为该脚本提供执行权限。
sudo chmod u+x /etc/init.d/floatip
当该floatip服务启动时,其会直接调用assign-ip Python脚本并将指定的Floating IP分配至执行该脚本的Droplet。在正常运行情况下,该脚本供secondary服务器使用以将Floating IP分配给自身,从而实现primary服务器的故障转移能力。同样的,该脚本亦可在primary重新加入集群后被其用于将Floating IP重新分配给自身。
启动Heartbeat
现在Heartbeat已经配置完成,而其运行所需要的全部脚本亦已准备就绪——我们可以马上启动这套Heartbeat集群了!
在两台服务器上运行以下命令以启动Heartbeat:
sudo service heartbeat start
大家应该看到以下输出结果:
Heartbeat output:
Starting High-Availability services: Done.
我们的高可用性设置已经完成!接下来是对其工作状态进行测试。
测试高可用性
对高可用性设置的工作状态进行测试非常重要,因此我们这就着手开始。
目前,该Floating IP被分配至primary节点。我们可以通过IP地址或者指向它的域名对Floating IP加以访问,并由此查看primary服务器的索引页面。如果大家使用示例提供的用户数据脚本,则显示结果应如下所示:
Floating IP is pointing to primary server
Droplet: primary, IP Address: 104.236.6.11
这意味着该Floating IP实际上被分配至primary Droplet处。
现在让我们打开终端,并使用curl以1秒循环访问该Floating IP。大家可使用以下命令实现这一目标,不过请注意将URL部分替换成各位的实际域名或者Floating IP地址:
while true; do curl http://example.com; sleep 1; done
目前其会输出同样的Droplet名称与primary服务器IP地址。如果我们让primary服务器处于不可用状态——例如将其关闭或者停止Heartbeat服务,则会看到Floating IP被重新分配至secondary服务器。
现在让我们关闭primary服务器。大家可以通过DigitalOcean控制面板或者在primary服务器上运行以下命令将其关闭:
sudo poweroff
片刻之后,该primary服务器将不再可用。需要注意运行在终端内的curl循环的输出结果。大家应该会看到以下输出内容:
curl loop output:
Droplet: primary, IP Address: 104.236.6.11
...
curl: (7) Failed to connect to example.com port 80: Connection refused
Droplet: secondary, IP Address: 104.236.6.22
Droplet: secondary, IP Address: 104.236.6.22
...
这时Floating IP地址应该被重新分配至secondary服务器的IP地址,也就是说我们的高可用性设置已经正常起效,即成功实现了自动化故障转移功能。
大家可能会发现一项Connection refused错误——当然也可能不会,原因在于大家的Floating IP访问尝试发生在primary服务器故障与该Floating IP重新分配完成这两个事件之间。
现在大家可以通过DigitalOcean控制面板重新启动自己的primary Droplet。由于Heartbeat在配置当中将primary Droplet作为preferred host以运行Floating IP重新分配脚本,因此该Floating IP会在可用性恢复后自动重新指向primary服务器。
总结
恭喜大家!现在我们已经拥有了一套利用Heartbeat与DigitalOcean Floating IP实现的基础高可用性服务器设置。
如果大家希望进一步提高可用性水平,亦可考虑使用Corosync与Pacemaker组合或者Keepalived。
如果大家希望扩展自己的Heartbeat设置,那么下一步工作就是利用反向代理负载均衡器替代示例中的Nginx设置。大家也可以使用Nginx或者HAProxy实现同样的效果。需要注意的是,大家需要将该负载均衡器绑定至另一个IP地址,从而确保用户只能够通过Floating IP地址访问服务器(而非通过各服务器的公共IP地址)。