内容


使用简单的 5 个步骤设置 Web 服务器集群

使用 Linux Virtual Server 和 Linux-HA.org 的 Heartbeat 进行构建和运行

Comments

通过在多个处理器之间分担工作负载并采用多种软件恢复技术,能够提供高度可用的环境并提高环境的总体 RAS(可靠性、可用性和可服务性)。可以得到的好处包括:更快地从意外中断中恢复运行,以及将意外中断对终端用户的影响降至最低。

为了更好地理解这篇文章,您需要熟悉 Linux 和连网的基本知识,还需要配置好 Apache 服务器。本文的示例基于标准的 SUSE Linux Enterprise Server 10 (SLES10) 安装,但是使用其他版本的明智用户也应该可以采用文中展示的方法。

本文展示了健壮的 Apache Web 服务器堆栈,它拥有 6 个 Apache 服务器节点(虽然 3 个节点就足以支持文中阐述的步骤),以及 3 个 Linux Virtual Server (LVS) 控制器。我们使用 6 个 Apache 服务器节点,可以在测试时实现更高的工作负载吞吐量,从而模拟更大型的部署。文中展示的架构应该可以支持更多的控制器和后端 Apache 服务器(在资源允许的情况下),但是我们并未进行更深入的尝试。图 1 展示了使用 Linux Virtual Server 和 linux-ha.org 组件的实现。

图 1. Linux Virtual Servers 和 Apache
Linux Virtual Servers 和 Apache
Linux Virtual Servers 和 Apache

如图 1 所示,外部客户机向单个 IP 地址发送通信量,而该 IP 地址可能存在于某个 LVS 控制器机器上。控制器机器积极地监控接收其发送工作的 Web 服务器池。

注意,图 1 左侧的工作负载进程指向右侧。此集群的浮动资源地址在一个给定时间将位于某个 LVS 控制器实例上。可以使用一个图形化的配置工具手动地移动服务地址,或者(这种方法更常见)自行管理服务地址,视 LVS 控制器的状态而定。如果某个控制器变得不合格(由于连接丢失、软件故障或类似原因),那么服务地址将自动地被重新分配给一个合格的控制器。

浮动服务地址必须跨越两个或多个离散的硬件实例,以便在一个物理机器连接丢失的情况下继续操作。使用本文展示的配置决策,每个 LVS 控制器都可以将包转发给任何的实际 Apache Web 服务器,并且与服务器的物理位置或服务器与提供浮动服务地址的活动控制器的接近程度无关。本文展示了每个 LVS 控制器如何积极地监控 Apache 服务器,以确保只向正常运作的后端服务器发送请求。

使用这种配置,技术人员可以成功地让整个 Linux 实例失效,而且不会中断在浮动服务地址上启用的用户服务(通常是 http 和 https Web 请求)。

您可以使用一个完全开源的软件组合复制这些配置,该软件组合包括,linux-ha.org 所提供的 Heartbeat 技术组件,以及通过 mon 和 Apache 进行监控的服务器。正如前面提到的,我们将使用 SUSE Linux Enterprise Server 测试配置。

LVS 场景中使用的所有机器都位于同一个子网中,使用的是 Network Address Translation (NAT) 配置。在 Linux Virtual Server Web 站点(请参阅 参考资料)上描述了很多其他网络结构;为简便起见我们使用 NAT。为了更加安全,您应该限制穿过防火墙的通信量,只允许浮动 IP 地址在 LVS 控制器之间传递。

Linux Virtual Server 套件提供了几种不同的方法以完成透明的 HA 后端基础设施。每种方法都各有利弊。LVS-NAT 操作控制器服务器的方式是,获取发往特定配置的端口的引入包,并动态地在包的头部重写目的地址。控制器本身并不处理包的数据内容,而是将其传给 realserver。包中的目的地址被重写为指向集群中的一个给定的 realserver。然后将包放回网络中以传递给 realserver,而 realserver 并没有意识到发生了什么情况。对于 realserver,它只是直接从外部接收请求。接着,realserver 的回复被发回控制器,在控制器中重写回复,使其具有客户机所指向的浮动 IP 地址的源地址,然后再发往原始客户机。

使用 LVS-NAT 方法意味着 realserver 需要简单的 TCP/IP 功能。LVS 操作的其他模式,即 LVS-DR 和 LVS-Tun,需要更加复杂的连网概念。选择 LVS-NAT 的最主要的好处是只需对 realserver 配置做很少量的更改。实际上,最难的部分是牢记适当地设置路由语句。

步骤 1:构建 realserver 图像

以构建 Linux 服务器实例池开始,每个实例运行 Apache Web 服务器,并确保服务器按预想的情况运作,将 Web 浏览器指向每个 realserver 的 IP 地址。通常,标准安装被配置为在自己的 IP 地址上侦听 80 端口(换言之,为每个 realserver 使用不同的 IP)。

接下来,在每个服务器上配置默认的 Web 页面以显示一个静态页面,其中包含了为页面提供服务的机器的主机名。这确保了您可以一直了解测试期间您所连接的机器。

为防万一,检查在这些系统上转发的 IP 是否为 OFF,方法是发出以下命令:

# cat /proc/sys/net/ipv4/ip_forward

如果不是 OFF 并且您需要禁用它,请发出以下命令:

# echo "0" >/proc/sys/net/ipv4/ip_forward

确保每个 realserver 都正常地侦听 http 端口 (80) 的一个简单方法是,使用外部系统并执行扫描。在一些与您的服务器连网的其他系统中,可以使用 nmap 工具以确保服务器执行侦听操作。

清单 1. 使用 nmap 确保服务器执行侦听操作
# nmap -P0 192.168.71.92

Starting nmap 3.70 ( http://www.insecure.org/nmap/ ) at 2006-01-13 16:58 EST
Interesting ports on 192.168.71.92:
(The 1656 ports scanned but not shown below are in state: closed)
PORT    STATE    SERVICE
22/tcp  open     ssh
80/tcp  filtered http
111/tcp open     rpcbind
631/tcp open     ipp

要注意的是,某些组织不赞成使用端口扫描工具,如 nmap:在使用工具之前请获取组织的批准。

接下来,将 Web 浏览器指向每个 realserver 的实际 IP 地址,从而确保每个 realserver 按照预期为相应页面提供服务。完成此操作后请转到步骤 2。

步骤 2:安装和配置 LVS 控制器

现在,您可以构建所需的 3 个 LVS 控制器实例。如果您第一次为每个 LVS 控制器安装 SUSE Linux Enterprise Server 10,在初始安装时,请确保选择与 heartbeat、ipvsadm 和 mon 相关的高可用性包。如果您拥有现有的安装,您就可以一直使用包管理工具,如 YAST,在完成基础安装之后添加这些包。强烈建议您将每个 realserver 添加到 /etc/hosts 文件中。这将确保为引入请求提供服务时,不会产生 DNS 相关的延迟。

此时,再次检查每个目录是否都能对每个 realserver 执行即时的 ping 操作:

清单 2. 对 realserver 执行 Ping 操作
# ping -c 1 $REAL_SERVER_IP_1

 # ping -c 1 $REAL_SERVER_IP_2

 # ping -c 1 $REAL_SERVER_IP_3

 # ping -c 1 $REAL_SERVER_IP_4

 # ping -c 1 $REAL_SERVER_IP_5

 # ping -c 1 $REAL_SERVER_IP_6

完成此操作后,从服务器中的本地包管理工具中安装 ipvsadm、Heartbeat 和 mon。回想一下,Heartbeat 将被用于控制器内部通信,而 mon 将被每个控制器用于维护关于每个 realserver 的状态信息。

步骤 3:在控制器上安装和配置 Heartbeat

如果您以前使用过 LVS,请记住,在 SLES10 上配置 Heartbeat Version 2 与在 SLES9 上配置 Heartbeat Version 1 截然不同。其中,Heartbeat Version 1 使用的文件(haresource、ha.cf 和 authkey)存储在 /etc/ha.d/ 目录中,而 Version 2 使用新的基于 XML 的 Cluster Information Base (CIB)。推荐的升级方法是使用 haresource 文件生成新的 cib.xml 文件。典型的 ha.cf 文件的内容如清单 3 所示。

我们从 SLES9 系统中获取 ha.cf 文件,并且为 Version 2 添加底部的 3 行(respawnpingdcrm)。如果您拥有现有的 version 1 配置,您也可以选择执行同样的操作。如果您要使用这些指令执行新安装,您可以复制清单 3 并进行修改以适应您的生产环境。

清单 3. /etc/ha.d/ha.cf config 文件样例
 # Log to syslog as facility "daemon"
 use_logd on
 logfacility daemon

 # List our cluster members (the realservers)
 node litsha22
 node litsha23
 node litsha21

 # Send one heartbeat each second
 keepalive 3

 # Warn when heartbeats are late
 warntime 5

 # Declare nodes dead after 10 seconds
 deadtime 10

 # Keep resources on their "preferred" hosts - needed for active/active
 #auto_failback on


 # The cluster nodes communicate on their heartbeat lan (.68.*) interfaces
 ucast eth1 192.168.68.201
 ucast eth1 192.168.68.202
 ucast eth1 192.168.68.203

 # Failover on network failures
 # Make the default gateway on the public interface a node to ping
 # (-m) -> For every connected node, add <integer> to the value set
 #  in the CIB, * Default=1
 # (-d) -> How long to wait for no further changes to occur before
 #  updating the CIB with a changed attribute
 # (-a) -> Name of the node attribute to set,  * Default=pingd
 respawn hacluster /usr/lib/heartbeat/pingd -m 100 -d 5s

 # Ping our router to monitor ethernet connectivity
 ping litrout71_vip

 #Enable version 2 functionality supporting clusters with  > 2 nodes
 crm yes

respawn 指令在运行时指定某个程序的运行和监控。如果此程序退出时的退出码不是 100,程序将自动重启。第一个参数是运行程序的用户 id,第二个参数是要运行的程序。-m 参数将 pingd 属性设为从当前机器可获得的 ping 节点数的 100 倍,而 -d 参数在修改 CIB 中的 pingd 属性之前将延迟 5 秒。ping 指令用于声明 Heartbeat 的 PingNode,而 crm 指令指定了 Heartbeat 应运行 1.x-style 集群管理器或 2.x-style 集群管理器,后者支持 2 个以上的节点。

对于所有的控制器这个文件都应该相同。适当地设置权限使 hacluster 守护程序可以读取文件也绝对重要。否则将导致日志文件中出现大量难于调试的警告。

对于某个版本的 1-style Heartbeat 集群,haresources 文件指定了节点名和连网信息(浮动 IP、关联接口和广播)。对我们而言,此文件仍然没有变化:

litsha21 192.168.71.205/24/eth0/192.168.71.255

此文件将只用于生成 cib.xml 文件。

authkeys 文件指定了一个共享的密匙以允许控制器之间进行通信。共享密钥就是一个密码,所有的 heartbeat 节点都知道这个密码并使用它进行相互通信。密钥的使用避免了无关方对 heartbeat 服务器节点的影响。此文件也没有变化:

auth 1

1 sha1 ca0e08148801f55794b23461eb4106db

接下来的几步将向您展示如何将 version 1 的 haresources 文件转换为 version 2 的基于 XML 的配置格式 (cib.xml)。虽然可以直接复制并使用清单 4 中的配置文件作为起点,但是强烈建议您针对自己的部署进行配置调整。

为了将文件格式转换为部署中使用的基于 XML 的 CIB (Cluster Information Base) 文件,请发出以下命令:

python /usr/lib64/heartbeat/haresources2cib.py /etc/ha.d/haresources > /var/lib/heartbeat/crm/test.xml

将会生成一个类似清单 4 所示的配置文件,并置于 /var/lib/heartbeat/crm/test.xml 中。

清单 4. CIB.xml 样例文件
 <cib admin_epoch="0" have_quorum="true" num_peers="3" cib_feature_revision="1.3"
  generated="true" ccm_transition="7" dc_uuid="114f3ad1-f18a-4bec-9f01-7ecc4d820f6c"
  epoch="280" num_updates="5205" cib-last-written="Tue Apr  3 16:03:33 2007">
    <configuration>
      <crm_config>
        <cluster_property_set id="cib-bootstrap-options">
          <attributes>
            <nvpair id="cib-bootstrap-options-symmetric_cluster"
                   name="symmetric_cluster" value="true"/>
            <nvpair id="cib-bootstrap-options-no_quorum_policy"
                   name="no_quorum_policy" value="stop"/>
            <nvpair id="cib-bootstrap-options-default_resource_stickiness"
                   name="default_resource_stickiness" value="0"/>
            <nvpair id="cib-bootstrap-options-stonith_enabled"
                   name="stonith_enabled" value="false"/>
            <nvpair id="cib-bootstrap-options-stop_orphan_resources"
                   name="stop_orphan_resources" value="true"/>
            <nvpair id="cib-bootstrap-options-stop_orphan_actions"
                   name="stop_orphan_actions" value="true"/>
            <nvpair id="cib-bootstrap-options-remove_after_stop"
                   name="remove_after_stop" value="false"/>
            <nvpair id="cib-bootstrap-options-transition_idle_timeout"
                   name="transition_idle_timeout" value="5min"/>
            <nvpair id="cib-bootstrap-options-is_managed_default"
                   name="is_managed_default" value="true"/>
          <attributes>
        <cluster_property_set>
      <crm_config>
      <nodes>
        <node uname="litsha21" type="normal" id="01ca9c3e-8876-4db5-ba33-a25cd46b72b3">
          <instance_attributes id="standby-01ca9c3e-8876-4db5-ba33-a25cd46b72b3">
            <attributes>
              <nvpair name="standby" id="standby-01ca9c3e-8876-4db5-ba33-a25cd46b72b3"
                     value="off"/>
            <attributes>
          <instance_attributes>
        <node>
        <node uname="litsha23" type="normal" id="dc9a784f-3325-4268-93af-96d2ab651eac">
          <instance_attributes id="standby-dc9a784f-3325-4268-93af-96d2ab651eac">
            <attributes>
              <nvpair name="standby" id="standby-dc9a784f-3325-4268-93af-96d2ab651eac"
                     value="off"/>
            <attributes>
          <instance_attributes>
        <node>
        <node uname="litsha22" type="normal" id="114f3ad1-f18a-4bec-9f01-7ecc4d820f6c">
          <instance_attributes id="standby-114f3ad1-f18a-4bec-9f01-7ecc4d820f6c">
            <attributes>
              <nvpair name="standby" id="standby-114f3ad1-f18a-4bec-9f01-7ecc4d820f6c"
                     value="off"/>
            <attributes>
          <instance_attributes>
        <node>
      <nodes>
      <resources>
        <primitive class="ocf" provider="heartbeat" type="IPaddr" id="IPaddr_1">
          <operations>
            <op id="IPaddr_1_mon" interval="5s" name="monitor" timeout="5s"/>
          <operations>
          <instance_attributes id="IPaddr_1_inst_attr">
            <attributes>
              <nvpair id="IPaddr_1_attr_0" name="ip" value="192.168.71.205"/>
              <nvpair id="IPaddr_1_attr_1" name="netmask" value="24"/>
              <nvpair id="IPaddr_1_attr_2" name="nic" value="eth0"/>
              <nvpair id="IPaddr_1_attr_3" name="broadcast" value="192.168.71.255"/>
            <attributes>
          <instance_attributes>
        <primitive>
      <resources>
      <constraints>
        <rsc_location id="rsc_location_IPaddr_1" rsc="IPaddr_1">
          <rule id="prefered_location_IPaddr_1" score="200">
            <expression attribute="#uname" id="prefered_location_IPaddr_1_expr"
                   operation="eq" value="litsha21"/>
          <rule>
        <rsc_location>
        <rsc_location id="my_resource:connected" rsc="IPaddr_1">
          <rule id="my_resource:connected:rule" score_attribute="pingd">
            <expression id="my_resource:connected:expr:defined" attribute="pingd"
                   operation="defined"/>
          <rule>
        <rsc_location>
      <constraints>
    <configuration>
  <cib>

一旦生成配置文件后,将 test.xml 移到 cib.xml 中,将所有者改为 hacluster,将组改为 haclient,然后重启 heartbeat 进程。

现已完成 heartbeat 配置,对 heartbeat 进行设置,使其在每个控制器的引导阶段启动。为此,在每个控制器上发出以下命令(或相对您的发行版的等效命令):

# chkconfig heartbeat on

重启每个 LVS 控制器以确保 heartbeat 服务在引导阶段正常启动。通过首先暂停保存浮动资源 IP 地址的机器,您可以等候其他 LVS Director 映像建立 quorum,然后在几秒钟内实例化最新选择的主节点上的服务地址。当您将暂停的控制器映像重新联机时,机器将在所有的节点间重新建立 quorum,此时浮动资源 IP 可能传输回来。整个过程只会耗费几秒钟。

另外,此时,您可能希望使用图形化工具处理 heartbeat 进程 hb_gui(如图 2 所示),手动地将 IP 地址在集群中移动,方法是将各种节点设置为备用或活动状态。多次重试这些步骤,禁用并重新启用活动的或不活动的各种机器。因为先前选中了配置策略,只要可以建立 quorum,并且至少有一个节点合格,那么浮动资源 IP 地址就保持正常运作。在测试期间,您可以使用简单的 ping 确保不会发生丢失包的情况。当您完成试验后,应该对配置的健壮性有一个深刻的体会。在继续操作之前请确保浮动资源 IP 的 HA 配置适当。

图 2. 用于 heartbeat 进程的图形化配置工具 hb_gui
图 2. 用于 heartbeat 进程的图形化配置工具 hb_gui
图 2. 用于 heartbeat 进程的图形化配置工具 hb_gui

图 2 展示了登录后的图形控制台的外观,上面显示了托管资源和相关的配置选项。注意,当您首次启动应用程序时,必须登录到 hb_gui 控制台;使用何种凭证将取决于您的部署。

注意,图 2 中 litsha2* 系统集群中的每个节点都处于运行状态。标记为 litsha21 的系统目前是活动节点,如 (IPaddr_1) 正下方锯齿状的附加资源所示。

另外要注意标记为 “No Quorum Policy” 的选项的值为 “stop”。这指的是任何单独的节点将释放它所拥有的资源。这个决策的含义是,在任何给定时间,必须有 2 个 heartbeat 节点是活动状态,以便建立 quorum(换言之,一种 “少数服从多数” 的投票规则)。即使只有一个节点是活动的,完全运行的节点也会由于网络故障丢失它与同级系统之间的连接,或者,如果两个非活动的同级系统同时暂停,资源将被自动释放。

步骤 4:使用 ipvsadm 命令创建 LVS 规则

下一步是获取浮动资源 IP 地址并在其上进行构建。因为 LVS 要求对远端 Web 浏览器客户机透明,所以所有的 Web 请求都必须经过控制器过滤并传给一个 realserver。然后,所有结果都需要传回控制器,后者向发出 Web 页面请求的客户机返回响应。

为了完成上述的请求和响应流程,首先配置每个 LVS 控制器,从而发出以下命令启用 IP 转发(因此允许将请求传给 realserver):

# echo "1" >/proc/sys/net/ipv4/ip_forward

# cat /proc/sys/net/ipv4/ip_forward

如果所有的操作都成功,那么第二个命令将返回一个 “1” 作为终端输出。要永久性地添加此选项,请添加:

'' IP_FORWARD="yes"

到 /etc/sysconfig/sysctl 中。

接下来,要通知控制器将引入的 HTTP 请求传递给 HA 浮动 IP 地址,接着再传给 realserver,使用 ipvsadm 命令。

首先,清除旧的 ipvsadm 表:

# /sbin/ipvsadm -C

在配置新表之前,您需要决定希望 LVS 控制器使用何种工作负载分配。收到来自客户机的连接请求后,控制器根据一个 “进度表” 将 realserver 指派给客户机,然后使用 ipvsadm 命令设置调度程序类型。可用的调度程序包括:

  • Round Robin (RR):新的引入连接被依次指派给每个 realserver。
  • Weighted Round Robin (WRR):使用附加的权重因子进行 RR 调度以补偿各种 realserver 功能(如附加 CPU、更多内存等)的差异。
  • Least Connected (LC):新连接指向具有最少连接数量的 realserver。不要求是最空闲的 realserver,但是以此为方向。
  • Weighted Least Connection (WLC):带权重的 LC。

使用 RR 调度进行测试是个不错的方法,因为易于确认。您可能希望将 WRR 和 LC 添加到测试例程中以确认它们能够按预期运作。此处给出的示例使用 RR 调度及类似调度。

接下来,创建脚本以启用转发至 realserver 的 ipvsadm 服务,并且在每个 LVS 控制器中放置一个副本。当完成 mon 的后续配置以自动监控活动的 realserver 后,就不需要再使用这个脚本,但在此之前它会有助于测试 ipvsadm 组件。请记住在执行此脚本之前重新检查网络和 http/https 与每个 realserver 之间的连接是否正常。

清单 5. HA_CONFIG.sh 文件
 #!/bin/sh

 # The virtual address on the director which acts as a cluster address

 VIRTUAL_CLUSTER_ADDRESS=192.168.71.205

 REAL_SERVER_IP_1=192.168.71.220

 REAL_SERVER_IP_2=192.168.71.150

 REAL_SERVER_IP_3=192.168.71.121

 REAL_SERVER_IP_4=192.168.71.145

 REAL_SERVER_IP_5=192.168.71.185

 REAL_SERVER_IP_6=192.168.71.186

 # set ip_forward ON for vs-nat director (1 on, 0 off).

 cat /proc/sys/net/ipv4/ip_forward

 echo "1" >/proc/sys/net/ipv4/ip_forward

 # director acts as the gw for realservers

 # Turn OFF icmp redirects (1 on, 0 off), if not the realservers might be clever and

 #  not use the director as the gateway!

 echo "0" >/proc/sys/net/ipv4/conf/all/send_redirects

 echo "0" >/proc/sys/net/ipv4/conf/default/send_redirects

 echo "0" >/proc/sys/net/ipv4/conf/eth0/send_redirects

 # Clear ipvsadm tables (better safe than sorry)

 /sbin/ipvsadm -C

 # We install LVS services with ipvsadm for HTTP and HTTPS connections with RR

 #  scheduling

 /sbin/ipvsadm -A -t $VIRTUAL_CLUSTER_ADDRESS:http -s rr

 /sbin/ipvsadm -A -t $VIRTUAL_CLUSTER_ADDRESS:https -s rr

 # First realserver

 # Forward HTTP to REAL_SERVER_IP_1 using LVS-NAT (-m), with weight=1

 /sbin/ipvsadm -a -t $VIRTUAL_CLUSTER_ADDRESS:http -r $REAL_SERVER_IP_1:http -m -w 1

 /sbin/ipvsadm -a -t $VIRTUAL_CLUSTER_ADDRESS:https -r $REAL_SERVER_IP_1:https -m -w 1

 # Second realserver

 # Forward HTTP to REAL_SERVER_IP_2 using LVS-NAT (-m), with weight=1

 /sbin/ipvsadm -a -t $VIRTUAL_CLUSTER_ADDRESS:http -r $REAL_SERVER_IP_2:http -m -w 1

 /sbin/ipvsadm -a -t $VIRTUAL_CLUSTER_ADDRESS:https -r $REAL_SERVER_IP_2:https -m -w 1

 # Third realserver

 # Forward HTTP to REAL_SERVER_IP_3 using LVS-NAT (-m), with weight=1

 /sbin/ipvsadm -a -t $VIRTUAL_CLUSTER_ADDRESS:http -r $REAL_SERVER_IP_3:http -m -w 1

 /sbin/ipvsadm -a -t $VIRTUAL_CLUSTER_ADDRESS:https -r $REAL_SERVER_IP_3:https -m -w 1

 # Fourth realserver

 # Forward HTTP to REAL_SERVER_IP_4 using LVS-NAT (-m), with weight=1

 /sbin/ipvsadm -a -t $VIRTUAL_CLUSTER_ADDRESS:http -r $REAL_SERVER_IP_4:http -m -w 1

 /sbin/ipvsadm -a -t $VIRTUAL_CLUSTER_ADDRESS:https -r $REAL_SERVER_IP_4:https -m -w 1

 # Fifth realserver

 # Forward HTTP to REAL_SERVER_IP_5 using LVS-NAT (-m), with weight=1

 /sbin/ipvsadm -a -t $VIRTUAL_CLUSTER_ADDRESS:http -r $REAL_SERVER_IP_5:http -m -w 1

 /sbin/ipvsadm -a -t $VIRTUAL_CLUSTER_ADDRESS:https -r $REAL_SERVER_IP_5:https -m -w 1

 # Sixth realserver

 # Forward HTTP to REAL_SERVER_IP_6 using LVS-NAT (-m), with weight=1

 /sbin/ipvsadm -a -t $VIRTUAL_CLUSTER_ADDRESS:http -r $REAL_SERVER_IP_6:http -m -w 1

 /sbin/ipvsadm -a -t $VIRTUAL_CLUSTER_ADDRESS:https -r $REAL_SERVER_IP_6:https -m -w 1

 # We print the new ipvsadm table for inspection

 echo "NEW IPVSADM TABLE:"

 /sbin/ipvsadm

如清单 5 中所示,脚本只是启用了 ipvsadm 服务,然后实际上使用了相同的代码节以便将 Web 和 SSL 请求转发给每个单个的 realserver。我们使用了 -m 选项指定 NAT,并给每个 realserver 赋以权重 1(-w 1)。使用正常的轮循调度时,指定的权重会出现冗余(因为默认的权重总是 1)。显示此选项的惟一目的是让您倾向于选择加权的轮循。 为此,在关于使用轮循的注释下的 2 个连续的行中将 rr 改为 wrr,当然不要忘了相应地调整权重。有关各种调度程序的更多信息,请查询 ipvsadm 手册。

您现在已经配置了每个控制器,可以处理引入的对浮动服务 IP 的 Web 和 SSL 请求,方法是重写这些请求并连续地将工作传递给 realserver。但是为了从 realserver 收回通信量,并且为了在将请求返回给发出请求的客户机之前执行相反的过程,您需要对控制器更改几个连网设置。其原因是需要在平面网络拓扑结构中实现 LVS 控制器和 realserver(即,同一子网上的所有组件)。我们需要执行以下步骤以强制 Apache 通过控制器返回响应通信量,而不是自己直接应答:

echo "0" > /proc/sys/net/ipv4/conf/all/send_redirects
echo "0" > /proc/sys/net/ipv4/conf/default/send_redirects
echo "0" > /proc/sys/net/ipv4/conf/eth0/send_redirects

执行此操作的目的是为了防止活动的 LVS 控制器通知 realserver 和浮动服务 IP 直接相互通信,从而获取 TCP/IP 捷径(因为它们位于同一个子网中)。一般情况下,重定向是有用的,因为它们通过清除网络连接中不必要的中间件提高了性能。但是此时,它可能阻碍了响应通信量的重写,而这又是对客户机透明所必需的。实际上,如果在 LVS 控制器上没有禁用重定向,那么从 realserver 直接发往客户机的通信量将被客户机视为未被请求的网络响应而被丢弃。

此时,可将每个 realserver 的默认路由设为指向服务的浮动 IP 地址,从而确保所有的响应都被传回控制器以进行包重写,然后再传回最初发出请求的客户机。

一旦在控制器上禁用重定向,并且 realserver 被配置为通过浮动服务 IP 发送所有的通信量,那么您可能需要测试 HA LVS 环境。要测试迄今为止所做的工作,可让一个远端客户机上的 Web 浏览器指向 LVS 控制器的浮动服务地址。

为了在实验室进行测试,我们使用的是基于 Gecko 的浏览器(Mozilla),但是任何其他浏览器也可以满足要求。为了确保部署成功,在浏览器中禁用缓存,并多次单击刷新按钮。在每次刷新时,您应看见显示的 Web 页面是 realserver 上配置的一个自识别页面。如果您要使用 RR 调度,您应可以看到连续通过每个 realserver 的页面循环。

您是否正在思考确保 LVS 配置在引导时自动启动?现在千万别这样做!还有一个步骤尚未完成(步骤 5),此步骤将执行 realserver 的活动监控(因此保留一个动态 Apache 节点列表,其中的节点可以为工作请求提供服务)。

步骤 5:在 LVS 控制器上安装和配置 mon

迄今为止,您已经建立了一个高度可用的服务 IP 地址,并将其绑定到 realserver 实例池。但是在任何给定时间您决不能信任任何单个的 Apache 服务器是正常运作的。通过选择 RR 调度,如果任何给定的 realserver 被禁用,或者以一种即时的方式停止响应网络通信量,那么 1/6 的 HTTP 请求将会失败!

因此有必要实施 realserver 对每个 LVS 控制器的监控,以便动态地将其添加到服务池中或从中删除。另一个著名的称为 mon 的开源包很适合这项任务。

mon 解决方案一般用于监控 LVS 真实节点。Mon 的配置相对容易,并且对于熟悉 shell 脚本编程的人而言可扩展性很好。让所有组件正常运作大致分以下三个主要步骤:安装、服务监控配置和警报创建。使用包管理工具处理 mon 的安装。完成安装后,您只需要调整监控配置,并创建一些警报脚本。当监视器确定 realserver 已经脱机或恢复联机时,将触发警报脚本。

注意,安装 heartbeat v2 后,监控 realserver 可通过构建所有的 realserver 服务资源来完成。 或者,您可以使用 Heartbeat ldirectord 包。

默认情况下,mon 附带了几个可以直接使用的监视器机制。我们修改了 /etc/mon.cf 中的样例配置文件以使用 HTTP 服务。

在 mon 配置文件中,确保标题可以反映正确的路径。SLES10 是一个 64 位的 Linux 图像,但是随附的样例配置用于默认的(31 位或 32 位)位置。配置文件样例假定警报和监视器位于 /usr/lib 中,这对于我们的特定安装而言并不正确。我们修改的参数如下:

alertdir = /usr/lib64/mon/alert.d
mondir = /usr/lib64/mon/mon.d

如您所见,我们只是将 lib 更改为 lib64。对于您所使用的版本可能不需要这种更改。

对配置文件的下一个更改是指定要监控的 realserver 列表。这可以通过以下 6 个指令完成:

清单 6. 指定要监控的 realserver
 hostgroup litstat1 192.168.71.220 # realserver 1

 hostgroup litstat2 192.168.71.150

 hostgroup litstat3 192.168.71.121

 hostgroup litstat4 192.168.71.145

 hostgroup litstat5 192.168.71.185

 hostgroup litstat6 192.168.71.186 # realserver 6

如果您希望添加额外的 realserver,直接在此添加额外的条目即可。

一旦您处理好所有的定义,就需要告知 mon 如何查看故障,以及如何处理故障。为此,添加以下的监视器段(分别针对每个 realserver)。完成后,您需要将 mon 配置文件和警报置于每个 LVS heartbeat 节点之上,启用每个 heartbeat 集群节点以独立地监控所有的 realserver。

清单 7. /etc/mon/mon.cf 文件
 #
 # global options
 #
 cfbasedir    = /etc/mon
 alertdir     = /usr/lib64/mon/alert.d
 mondir       = /usr/lib64/mon/mon.d
 statedir     = /var/lib/mon
 logdir       = /var/log
 maxprocs     = 20
 histlength   = 100
 historicfile = mon_history.log
 randstart    = 60s
 #
 # authentication types:
 #   getpwnam      standard Unix passwd, NOT for shadow passwords
 #   shadow        Unix shadow passwords (not implemented)
 #   userfile      "mon" user file
 #
 authtype = getpwnam
 #
 # downtime logging, uncomment to enable
 #  if the server is running, don't forget to send a reset command
 #  when you change this
 #
 #dtlogfile = downtime.log
 dtlogging = yes
 #
 # NB:  hostgroup and watch entries are terminated with a blank line (or
 #  end of file).  Don't forget the blank lines between them or you lose.
 #
 #
 # group definitions (hostnames or IP addresses)
 # example:
 #
 # hostgroup servers www mail pop server4 server5
 #
 # For simplicity we monitor each individual server as if it were a "group"
 #  so we add only the hostname and the ip address of an individual node for each.
 hostgroup litstat1 192.168.71.220
 hostgroup litstat2 192.168.71.150
 hostgroup litstat3 192.168.71.121
 hostgroup litstat4 192.168.71.145
 hostgroup litstat5 192.168.71.185
 hostgroup litstat6 192.168.71.186
 #
 # Now we set identical watch definitions on each of our groups. They could be
 #  customized to treat individual servers differently, but we have made the
 #  configurations homogeneous here to match our homogeneous LVS configuration.
 #
  watch litstat1
      service http
         description http check servers
         interval 6s
         monitor http.monitor -p 80 -u /index.html
         allow_empty_group
         period wd {Mon-Sun}
             alert dowem.down.alert -hupalert dowem.up.alert -h
             alertevery 600s
                 alertafter 1
  watch litstat2
      service http
         description http check servers
         interval 6s
         monitor http.monitor -p 80 -u /index.html
         allow_empty_group
         period wd {Mon-Sun}
             alert dowem.down.alert -h
             upalert dowem.up.alert -h
             alertevery 600s
                 alertafter 1
  watch litstat3
      service http
         description http check servers
         interval 6s
         monitor http.monitor -p 80 -u /index.html
         allow_empty_group
         period wd {Mon-Sun}
             alert dowem.down.alert -h
             upalert dowem.up.alert -h
             alertevery 600s
                 alertafter 1
  watch litstat4
      service http
         description http check servers
         interval 6s
         monitor http.monitor -p 80 -u /index.html
         allow_empty_group
         period wd {Mon-Sun}
             alert dowem.down.alert -h
             upalert dowem.up.alert -h
             alertevery 600s
                 alertafter 1
  watch litstat5
      service http
         description http check servers
         interval 6s
         monitor http.monitor -p 80 -u /index.html
         allow_empty_group
         period wd {Mon-Sun}
             alert dowem.down.alert -h
             upalert dowem.up.alert -h
             alertevery 600s
                 alertafter 1
  watch litstat6
      service http
         description http check servers
         interval 6s
         monitor http.monitor -p 80 -u /index.html
         allow_empty_group
         period wd {Mon-Sun}
             alert dowem.down.alert -h
             upalert dowem.up.alert -h
             alertevery 600s
                 alertafter 1

清单 7 告知 mon 使用 http.monitor,默认情况下它由 mon 附带。另外,指定使用端口 80。清单 7 还提供了要请求的特殊页面;您可能会选择为 Web 服务器传输一小段更有效率的 html 作为操作成功的证明,而不是传输一个复杂的默认 html 页面。

alertupalert 行调用的脚本必须置于配置文件顶部指定的 alertdir 中。其目录通常是发行版所默认的目录,比如 “/usr/lib64/mon/alert.d”。警报负责告知 LVS 将 Apache 服务器添加到合格的列表中或从中删除(方法是调用 ipvsadm 命令,我们很快就要介绍到)。

当一个 realserver 的 http 测试失败时,dowem.down.alert 将由 mon 使用几个参数自动执行。同样地,当监视器确定 realserver 已经恢复联机时,mon 进程使用大量的参数自动执行 dowem.up.alert。您可以随意地修改警报脚本的名称以适应您的部署。

保存此文件,在 alertdir 中创建警报(使用简单的 bash 脚本编程)。清单 8 展示了一个 bash 脚本警报,重新建立 realserver 连接时由 mon 调用。

清单 8. 简单警报:已连接上
 #! /bin/bash

 #   The h arg is followed by the hostname we are interested in acting on

 #   So we skip ahead to get the -h option since we don't care about the others

 REALSERVER=192.168.71.205

 while [ $1 != "-h" ] ;

 do

         shift

 done

 ADDHOST=$2

 # For the HTTP service

 /sbin/ipvsadm -a -t $REALSERVER:http -r $ADDHOST:http -m -w 1

 # For the HTTPS service

 /sbin/ipvsadm -a -t $REALSERVER:https -r $ADDHOST:https -m -w 1

清单 9 展示了一个 bash 脚本警报,当 realserver 连接丢失时由 mon 调用。

清单 9. 简单警报:连接已丢失
 #! /bin/bash

 #   The h arg is followed by the hostname we are interested in acting on

 #   So we skip ahead to get the -h option since we dont care about the others

 REALSERVER=192.168.71.205

 while [ $1 != "-h" ] ;

 do

         shift

 done

 BADHOST=$2

 # For the HTTP service

 /sbin/ipvsadm -d -t $REALSERVER:http -r $BADHOST

 # For the HTTPS service

 /sbin/ipvsadm -d -t $REALSERVER:https -r $BADHOST

这两组脚本都使用 ipvsadm 命令行工具动态地将 realserver 添加到 LVS 表中或从中删除。注意,这些脚本远谈不上完美。mon 只对于简单的 Web 请求监控 http 端口,此处阐述的架构在下述情形中容易受到攻击:给定的 realserver 对于 http 请求可能正常运作,但对于 SSL 请求却不行。在这些情况下,我们将无法从 https 备选列表中删除有问题的 realserver。当然,除了为 mon 配置文件中的每个 realserver 启用另一个 https 监视器外,构建更多专门针对每种类型的 Web 请求的高级警报也可以轻松地解决这个问题。这可以留给读者作为练习。

为确保监视器已被激活,依次为每个 realserver 启用并禁用 Apache 进程,观察每个控制器对事件的反应。只有当您确认每个控制器正常地监控每个 realserver 后,您才可以使用 chkconfig 命令确保 mon 进程可以在引导时自动启动。使用的特定命令为 chkconfig mon on,但是这可能随发行版的不同而有所区别。

完成这个最后的部分后,您就已完成构建跨系统的高度可用的 Web 服务器基础设施的任务。当然,您现在可能想要执行一些更高级的工作。例如,您可能已经注意到,mon 守护程序本身没有被监控(heartbeat 项目可以为您监控 mon),但是最后的步骤已为此打下基础。

故障诊断

活动节点在一个 HA 集群中不能正常运作有多种原因,自愿的或非自愿的。节点可能丢失与其他节点的网络连接,heartbeat 进程可能被停止,可能出现任何环境事件等等。要故意地让活动节点失效,您可以要求该节点暂停,或将其设为备用模式,方法是使用 hb_gui(完全关闭)命令。如果您希望测试环境的健壮性,您可能需要一些更激进的方式。

指示器和故障恢复

系统管理员可以使用两种日志文件指示器配置 Linux HA heartbeat 系统。日志文件与系统是否为浮动资源 IP 地址的接收方有关。没有接收浮动资源 IP 地址的集群成员的日志结果类似于:

清单 10. 落选者的日志结果
 litsha21:~ # cat  /var/log/messages

 Jan 16 12:00:20 litsha21 heartbeat: [3057]: WARN: node litsha23: is dead

 Jan 16 12:00:21 litsha21 cib: [3065]: info: mem_handle_event: Got an event

  OC_EV_MS_NOT_PRIMARY from ccm

 Jan 16 12:00:21 litsha21 cib: [3065]: info: mem_handle_event: instance=13, nodes=3,

  new=1, lost=0, n_idx=0, new_idx=3, old_idx=6

 Jan 16 12:00:21 litsha21 crmd: [3069]: info: mem_handle_event: Got an event

  OC_EV_MS_NOT_PRIMARY from ccm

 Jan 16 12:00:21 litsha21 crmd: [3069]: info: mem_handle_event: instance=13, nodes=3,

  new=1, lost=0, n_idx=0, new_idx=3, old_idx=6

 Jan 16 12:00:21 litsha21 crmd: [3069]: info: crmd_ccm_msg_callback:callbacks.c Quorum

  lost after event=NOT PRIMARY (id=13)

 Jan 16 12:00:21 litsha21 heartbeat: [3057]: info: Link litsha23:eth1 dead.

 Jan 16 12:00:38 litsha21 ccm: [3064]: debug: quorum plugin: majority

 Jan 16 12:00:38 litsha21 ccm: [3064]: debug: cluster:linux-ha, member_count=2,

  member_quorum_votes=200

 Jan 16 12:00:38 litsha21 ccm: [3064]: debug: total_node_count=3,

  total_quorum_votes=300

                    .................. Truncated For Brevity ..................

 Jan 16 12:00:40 litsha21 crmd: [3069]: info: update_dc:utils.c Set DC to litsha21

  (1.0.6)

 Jan 16 12:00:41 litsha21 crmd: [3069]: info: do_state_transition:fsa.c litsha21:

  State transition S_INTEGRATION ->

 S_FINALIZE_JOIN [ input=I_INTEGRATED cause=C_FSA_INTERNAL

  origin=check_join_state ]

 Jan 16 12:00:41 litsha21 crmd: [3069]: info: do_state_transition:fsa.c All 2 cluster

  nodes responded to the join offer.

 Jan 16 12:00:41 litsha21 crmd: [3069]: info: update_attrd:join_dc.c Connecting to

  attrd...

 Jan 16 12:00:41 litsha21 cib: [3065]: info: sync_our_cib:messages.c Syncing CIB to

  all peers

 Jan 16 12:00:41 litsha21 attrd: [3068]: info: attrd_local_callback:attrd.c Sending

  full refresh

                    .................. Truncated For Brevity ..................

 Jan 16 12:00:43 litsha21 pengine: [3112]: info: unpack_nodes:unpack.c Node litsha21

  is in standby-mode

 Jan 16 12:00:43 litsha21 pengine: [3112]: info: determine_online_status:unpack.c Node

  litsha21 is online

 Jan 16 12:00:43 litsha21 pengine: [3112]: info: determine_online_status:unpack.c Node

  litsha22 is online

 Jan 16 12:00:43 litsha21 pengine: [3112]: info: IPaddr_1

         (heartbeat::ocf:IPaddr): Stopped

 Jan 16 12:00:43 litsha21 pengine: [3112]: notice: StartRsc:native.c  litsha22

    Start IPaddr_1

 Jan 16 12:00:43 litsha21 pengine: [3112]: notice: Recurring:native.c litsha22

       IPaddr_1_monitor_5000

 Jan 16 12:00:43 litsha21 pengine: [3112]: notice: stage8:stages.c Created transition

  graph 0.

                    .................. Truncated For Brevity ..................

 Jan 16 12:00:46 litsha21 mgmtd: [3070]: debug: update cib finished

 Jan 16 12:00:46 litsha21 crmd: [3069]: info: do_state_transition:fsa.c litsha21:

  State transition S_TRANSITION_ENGINE ->

  S_IDLE [ input=I_TE_SUCCESS cause=C_IPC_MESSAGE origin=do_msg_route ]

 Jan 16 12:00:46 litsha21 cib: [3118]: info: write_cib_contents:io.c Wrote version

  0.53.593 of the CIB to disk (digest: 83b00c386e8b67c42d033a4141aaef90)

如清单 10 所示,获取了一份名单,有足够的 quorum 成员可以投票。获取投票,不需要执行其他操作即可恢复正常运作。

相反,接收了浮动资源 IP 地址的集群成员的日志结果如下:

清单 11. 资源持有者的日志文件
 litsha22:~ # cat  /var/log/messages

 Jan 16 12:00:06 litsha22 syslog-ng[1276]: STATS: dropped 0

 Jan 16 12:01:51 litsha22 heartbeat: [3892]: WARN: node litsha23: is dead

 Jan 16 12:01:51 litsha22 heartbeat: [3892]: info: Link litsha23:eth1 dead.

 Jan 16 12:01:51 litsha22 cib: [3900]: info: mem_handle_event: Got an event

  OC_EV_MS_NOT_PRIMARY from ccm

 Jan 16 12:01:51 litsha22 cib: [3900]: info: mem_handle_event: instance=13, nodes=3,

  new=3, lost=0, n_idx=0, new_idx=0, old_idx=6

 Jan 16 12:01:51 litsha22 crmd: [3904]: info: mem_handle_event: Got an event

  OC_EV_MS_NOT_PRIMARY from ccm

 Jan 16 12:01:51 litsha22 crmd: [3904]: info: mem_handle_event: instance=13, nodes=3,

  new=3, lost=0, n_idx=0, new_idx=0, old_idx=6

 Jan 16 12:01:51 litsha22 crmd: [3904]: info: crmd_ccm_msg_callback:callbacks.c Quorum

  lost after event=NOT PRIMARY (id=13)

 Jan 16 12:02:09 litsha22 ccm: [3899]: debug: quorum plugin: majority

 Jan 16 12:02:09 litsha22 crmd: [3904]: info: do_election_count_vote:election.c

  Election check: vote from litsha21

 Jan 16 12:02:09 litsha22 ccm: [3899]: debug: cluster:linux-ha, member_count=2,

  member_quorum_votes=200

 Jan 16 12:02:09 litsha22 ccm: [3899]: debug: total_node_count=3,

  total_quorum_votes=300

 Jan 16 12:02:09 litsha22 cib: [3900]: info: mem_handle_event: Got an event

  OC_EV_MS_INVALID from ccm

 Jan 16 12:02:09 litsha22 cib: [3900]: info: mem_handle_event: no mbr_track info

 Jan 16 12:02:09 litsha22 cib: [3900]: info: mem_handle_event: Got an event

  OC_EV_MS_NEW_MEMBERSHIP from ccm

 Jan 16 12:02:09 litsha22 cib: [3900]: info: mem_handle_event: instance=14, nodes=2,

  new=0, lost=1, n_idx=0, new_idx=2, old_idx=5

 Jan 16 12:02:09 litsha22 cib: [3900]: info: cib_ccm_msg_callback:callbacks.c

  LOST: litsha23

 Jan 16 12:02:09 litsha22 cib: [3900]: info: cib_ccm_msg_callback:callbacks.c

  PEER: litsha21

 Jan 16 12:02:09 litsha22 cib: [3900]: info: cib_ccm_msg_callback:callbacks.c

  PEER: litsha22

                    .................. Truncated For Brevity ..................

 Jan 16 12:02:12 litsha22 crmd: [3904]: info: update_dc:utils.c Set DC to litsha21

  (1.0.6)

 Jan 16 12:02:12 litsha22 crmd: [3904]: info: do_state_transition:fsa.c litsha22:

  State transition S_PENDING -> S_NOT_DC [ input=I_NOT_DC cause=C_HA_MESSAGE

  origin=do_cl_join_finalize_respond ]

 Jan 16 12:02:12 litsha22 cib: [3900]: info: cib_diff_notify:notify.c Update (client:

  3069, call:25): 0.52.585 ->

 0.52.586 (ok)

                    .................. Truncated For Brevity ..................

 Jan 16 12:02:14 litsha22 IPaddr[3998]: INFO: /sbin/ifconfig eth0:0 192.168.71.205

  netmask 255.255.255.0 broadcast 192.168.71.255

 Jan 16 12:02:14 litsha22 IPaddr[3998]: INFO: Sending Gratuitous Arp for

  192.168.71.205 on eth0:0 [eth0]

 Jan 16 12:02:14 litsha22 IPaddr[3998]: INFO: /usr/lib64/heartbeat/send_arp -i 500 -r

  10 -p

 /var/run/heartbeat/rsctmp/send_arp/send_arp-192.168.71.205 eth0 192.168.71.205 auto

  192.168.71.205 ffffffffffff

 Jan 16 12:02:14 litsha22 crmd: [3904]: info: process_lrm_event:lrm.c LRM operation

  (3) start_0 on IPaddr_1 complete

 Jan 16 12:02:14 litsha22 kernel: send_arp uses obsolete (PF_INET,SOCK_PACKET)

 Jan 16 12:02:14 litsha22 kernel: klogd 1.4.1, ---------- state change ----------

 Jan 16 12:02:14 litsha22 kernel: NET: Registered protocol family 17

 Jan 16 12:02:15 litsha22 crmd: [3904]: info: do_lrm_rsc_op:lrm.c Performing op

  monitor on IPaddr_1 (interval=5000ms, key=0:f9d962f0-4ed6-462d-a28d-e27b6532884c)

 Jan 16 12:02:15 litsha22 cib: [3900]: info: cib_diff_notify:notify.c Update (client:

  3904, call:18): 0.53.591 ->

 0.53.592

  (ok)

 Jan 16 12:02:15 litsha22 mgmtd: [3905]: debug: update cib finished

如清单 11 所示,/var/log/messages 文件展示了此节点已经获得了浮动资源。ifconfig 行显示将动态创建 eth0:0 设备以维持服务。

如清单 11 所示,获取了一份名单,有足够的 quorum 成员可以投票。获取投票后,发出的 ifconfig 命令索要浮动资源 IP 地址。

另外一种指示何时发生故障的方法是,您可以登录到任何一个集群成员并执行 hb_gui 命令。使用这种方法,您可以通过亲自查找拥有浮动资源的系统来确定故障发生时间。

最后,如果我们不展示一个非 quorum 情形的样例日志文件似乎有些说不过去。如果某个单一节点无法与任何一个其他节点进行通信,那么它就丢失了 quorum(因为在 3 个成员的投票中 2/3 是多数)。在这种情况下,节点获悉已丢失 quorum,然后调用 no quorum policy 处理程序。清单 12 展示了一个来自这类事件的日志文件示例。丢失 quorum 时,日志条目将会有所显示。显示此日志条目的集群节点认为自己不具有浮动资源。ifconfig down 语句将释放资源。

清单 12. 显示丢失 quorum 的日志条目
 litsha22:~ # cat /var/log/messages

 ....................

 Jan 16 12:06:12 litsha22 ccm: [3899]: debug: quorum plugin: majority

 Jan 16 12:06:12 litsha22 ccm: [3899]: debug: cluster:linux-ha, member_count=1,

  member_quorum_votes=100

 Jan 16 12:06:12 litsha22 ccm: [3899]: debug: total_node_count=3,

  total_quorum_votes=300

                    .................. Truncated For Brevity ..................

 Jan 16 12:06:12 litsha22 crmd: [3904]: info: crmd_ccm_msg_callback:callbacks.c Quorum

  lost after event=INVALID (id=15)

 Jan 16 12:06:12 litsha22 crmd: [3904]: WARN: check_dead_member:ccm.c Our DC node

  (litsha21) left the cluster

                    .................. Truncated For Brevity ..................

 Jan 16 12:06:14 litsha22 IPaddr[5145]: INFO: /sbin/route -n del -host 192.168.71.205

 Jan 16 12:06:15 litsha22 lrmd: [1619]: info: RA output: (IPaddr_1:stop:stderr)

  SIOCDELRT: No such process

 Jan 16 12:06:15 litsha22 IPaddr[5145]: INFO: /sbin/ifconfig eth0:0 192.168.71.205

  down

 Jan 16 12:06:15 litsha22 IPaddr[5145]: INFO: IP Address 192.168.71.205 released

 Jan 16 12:06:15 litsha22 crmd: [3904]: info: process_lrm_event:lrm.c LRM operation

  (6) stop_0 on IPaddr_1 complete

 Jan 16 12:06:15 litsha22 cib: [3900]: info: cib_diff_notify:notify.c Update (client:

  3904, call:32): 0.54.599 ->

 0.54.600 (ok)

 Jan 16 12:06:15 litsha22 mgmtd: [3905]: debug: update cib finished

如清单 12 所示,当某个给定节点丢失 quorum 时,它将放弃所有资源,因为选择了 no quorum policy 配置。是否选择 no quorum policy 完全取决于您自己。

Fail-back 动作和消息

正确配置的 Linux HA 系统的一个更有趣的含义是,您不需要执行任何操作就可重新实例化集群成员。只需要激活 Linux 实例即可让节点自动地重新加入其他节点。如果您配置了一个主节点(即,一个可以优先于其他节点获得浮动资源的节点),它将自动重新获得浮动资源。非优先的系统将只是加入合格节点池并正常运作。

将其他的 Linux 实例往回添加到池中将使每个节点获得通知,并且如果可能的话,重新建立 quorum。如果可以重新建立 quorum,那么将在某个节点上重新建立浮动资源。

清单 13. 重新建立 Quorum
 litsha22:~ # tail -f /var/log/messages

 Jan 16 12:09:02 litsha22 heartbeat: [3892]: info: Heartbeat restart on node litsha21

 Jan 16 12:09:02 litsha22 heartbeat: [3892]: info: Link litsha21:eth1 up.

 Jan 16 12:09:02 litsha22 heartbeat: [3892]: info: Status update for node litsha21:

  status init

 Jan 16 12:09:02 litsha22 heartbeat: [3892]: info: Status update for node litsha21:

  status up

 Jan 16 12:09:22 litsha22 heartbeat: [3892]: debug: get_delnodelist: delnodelist=

 Jan 16 12:09:22 litsha22 heartbeat: [3892]: info: Status update for node litsha21:

  status active

 Jan 16 12:09:22 litsha22 cib: [3900]: info: cib_client_status_callback:callbacks.c

  Status update: Client litsha21/cib now has status [join]

 Jan 16 12:09:23 litsha22 heartbeat: [3892]: WARN: 1 lost packet(s) for [litsha21]

  [36:38]

 Jan 16 12:09:23 litsha22 heartbeat: [3892]: info: No pkts missing from litsha21!

 Jan 16 12:09:23 litsha22 crmd: [3904]: notice:

  crmd_client_status_callback:callbacks.c Status update: Client litsha21/crmd now has

  status [online]

 ....................

 Jan 16 12:09:31 litsha22 crmd: [3904]: info: crmd_ccm_msg_callback:callbacks.c Quorum

  (re)attained after event=NEW MEMBERSHIP (id=16)

 Jan 16 12:09:31 litsha22 crmd: [3904]: info: ccm_event_detail:ccm.c NEW MEMBERSHIP:

  trans=16, nodes=2, new=1, lost=0 n_idx=0, new_idx=2, old_idx=5

 Jan 16 12:09:31 litsha22 crmd: [3904]: info: ccm_event_detail:ccm.c     CURRENT:

  litsha22 [nodeid=1, born=13]

 Jan 16 12:09:31 litsha22 crmd: [3904]: info: ccm_event_detail:ccm.c     CURRENT:

  litsha21 [nodeid=0, born=16]

 Jan 16 12:09:31 litsha22 crmd: [3904]: info: ccm_event_detail:ccm.c     NEW:

      litsha21 [nodeid=0, born=16]

 Jan 16 12:09:31 litsha22 cib: [3900]: info: cib_diff_notify:notify.c Local-only

  Change (client:3904, call: 35):

 0.54.600 (ok)

 Jan 16 12:09:31 litsha22 mgmtd: [3905]: debug: update cib finished

 ....................

 Jan 16 12:09:34 litsha22 crmd: [3904]: info: update_dc:utils.c Set DC to litsha22

  (1.0.6)

 Jan 16 12:09:35 litsha22 cib: [3900]: info: sync_our_cib:messages.c Syncing CIB to

  litsha21

 Jan 16 12:09:35 litsha22 crmd: [3904]: info: do_state_transition:fsa.c litsha22:

  State transition S_INTEGRATION ->

  S_FINALIZE_JOIN [ input=I_INTEGRATED cause=C_FSA_INTERNAL origin=check_join_state ]

 Jan 16 12:09:35 litsha22 crmd: [3904]: info: do_state_transition:fsa.c All 2 cluster

  nodes responded to the join offer.

 Jan 16 12:09:35 litsha22 attrd: [3903]: info: attrd_local_callback:attrd.c Sending

  full refresh

 Jan 16 12:09:35 litsha22 cib: [3900]: info: sync_our_cib:messages.c Syncing CIB to

  all peers

 .........................

 Jan 16 12:09:37 litsha22 tengine: [5119]: info: send_rsc_command:actions.c Initiating

  action 4: IPaddr_1_start_0 on litsha22

 Jan 16 12:09:37 litsha22 tengine: [5119]: info: send_rsc_command:actions.c Initiating

  action 2: probe_complete on litsha21

 Jan 16 12:09:37 litsha22 crmd: [3904]: info: do_lrm_rsc_op:lrm.c Performing op start

  on IPaddr_1 (interval=0ms,

  key=2:c5131d14-a9d9-400c-a4b1-60d8f5fbbcce)

 Jan 16 12:09:37 litsha22 pengine: [5120]: info: process_pe_message:pengine.c

  Transition 2: PEngine Input stored in: /var/lib/heartbeat/pengine/pe-input-72.bz2

 Jan 16 12:09:37 litsha22 IPaddr[5196]: INFO: /sbin/ifconfig eth0:0 192.168.71.205

  netmask 255.255.255.0 broadcast 192.168.71.255

 Jan 16 12:09:37 litsha22 IPaddr[5196]: INFO: Sending Gratuitous Arp for

  192.168.71.205 on eth0:0 [eth0]

 Jan 16 12:09:37 litsha22 IPaddr[5196]: INFO: /usr/lib64/heartbeat/send_arp -i 500 -r

  10 -p

  /var/run/heartbeat/rsctmp/send_arp/send_arp-192.168.71.205 eth0 192.168.71.205 auto

  192.168.71.205 ffffffffffff

 Jan 16 12:09:37 litsha22 crmd: [3904]: info: process_lrm_event:lrm.c LRM operation

  (7) start_0 on IPaddr_1 complete

 Jan 16 12:09:37 litsha22 cib: [3900]: info: cib_diff_notify:notify.c Update (client:

  3904, call:46): 0.55.607 -> 0.55.608 (ok)

 Jan 16 12:09:37 litsha22 mgmtd: [3905]: debug: update cib finished

 Jan 16 12:09:37 litsha22 tengine: [5119]: info: te_update_diff:callbacks.c Processing

  diff (cib_update): 0.55.607 -> 0.55.608

 Jan 16 12:09:37 litsha22 tengine: [5119]: info: match_graph_event:events.c Action

  IPaddr_1_start_0 (4) confirmed

 Jan 16 12:09:37 litsha22 tengine: [5119]: info: send_rsc_command:actions.c Initiating

  action 5: IPaddr_1_monitor_5000 on litsha22

 Jan 16 12:09:37 litsha22 crmd: [3904]: info: do_lrm_rsc_op:lrm.c Performing op

  monitor on IPaddr_1 (interval=5000ms, key=2:c5131d14-a9d9-400c-a4b1-60d8f5fbbcce)

 Jan 16 12:09:37 litsha22 cib: [5268]: info: write_cib_contents:io.c Wrote version

  0.55.608 of the CIB to disk (digest: 98cb6685c25d14131c49a998dbbd0c35)

 Jan 16 12:09:37 litsha22 crmd: [3904]: info: process_lrm_event:lrm.c LRM operation

  (8) monitor_5000 on IPaddr_1 complete

 Jan 16 12:09:38 litsha22 cib: [3900]: info: cib_diff_notify:notify.c Update (client:

  3904, call:47): 0.55.608 -> 0.55.609 (ok)

 Jan 16 12:09:38 litsha22 mgmtd: [3905]: debug: update cib finished

在清单 13 中,您可以看见 quorum 已被重新建立。重新建立 quorum 后,执行投票,而 litsha22 将变为具有浮动资源的活动节点。

结束语

高可用性被视为一系列挑战,本文介绍的解决方案描述了第一个步骤。从这里开始,在您的开发环境中有多种方法可以继续操作:您可以选择安装冗余的网络、集群文件系统以支持 realserver,或安装更高级的中间件直接支持集群。


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Linux, Open source, Web development
ArticleID=255753
ArticleTitle=使用简单的 5 个步骤设置 Web 服务器集群
publish-date=09172007