Multiple HA resources based on same service / Heartbeat httpmon RA

Preface

During a failback proces of a HA cluster based on Heartbeat 3.x I faced a issue with moving resources from a node to another, let me explain why.
There are three Nodes in cluster

  • Node_Alpha – Apache with VIP 10.10.10.10
  • Node_Beta – Apache with VIP 10.10.10.11
  • Node_Gamma – Apache with VIP 10.10.10.12

Each node should run a Web resource based on Apache. Each node can failover to any other node in the cluster.

Configuration

Heartbeat is configured to not auto failback. To manage Apache resource I used ocf:heartbeat:apache RA.
Here is some kind of template I used to configure web resource and group on each node:

primitive VIP_10.10.10.X ocf:heartbeat:IPaddr \
    params ip="10.10.10.X" nic="eth0" cidr_netmask="255.255.255.0" \
    op monitor interval="5s" enabled="true" role="Started" timeout="20s" start-delay="1s"
primitive apache_xxx ocf:heartbeat:apache \
    params port="80" configfile="/etc/httpd/conf/httpd.conf" statusurl="http://10.10.10.X/server-status" \
        testurl="http://10.10.10.X/test.php" testregex10="ok" \
    op monitor interval="15" timeout="20" on-fail="standby" start-delay="15" OCF_CHECK_LEVEL="10"
group gr_apache_xxx VIP_10.10.10.X apache_xxx \
    meta target-role="Started" ordered="true" collocated="true" is-managed="true"

Note that in this configuration, in case if Apache will fail the whole node will go to standby. Lets name a group for each node:

  • Node_Alpha – gr_apache_alpha
  • Node_Beta – gr_apache_beta
  • Node_Gamma – gr_apache_gamma

Unexpected Issue

For some reason Node_Alpha went down and gr_apache_alpha failed over to Node_Beta. Now we have two web resources running on same node: gr_apache_alpha and gr_apache_beta. After a while Node_Alpha came back online and it is able now to run this resource. We are trying to move gr_apache_alpha it back:

crm resource move Node_Alpha

But for some reason gr_apache_beta failed and node went into standby. The reason of failure was the fact that both resources were using same instance of Apache. While gr_apache_alpha was moved back to Node_Alpha Apache was stopped, monitoring of gr_apache_beta showed that Apache is not running ( failed ) and it put node in standby mode. And this will happen every time I will try to move a gr_apache_* from where there are two or more such resources. There is workaround for this: make all gr_apache_* ( except for group you want to move ) unamanged, restart apache after move and make remained gr_apache_* managed. But this workaround can not give us 100% that a human will not make a mistake ( forget to unmanage a group ).

Solution

The only solution I see is to make Apache resource not a part of group but a clone:

primitive apache ocf:heartbeat:apache \
    params port="80" configfile="/etc/httpd/conf/httpd.conf" statusurl="http://localhost/server-status" \
    op monitor interval="15" timeout="20" on-fail="standby" start-delay="15"
clone clone_apache apache \
    meta globally-unique="false" clone-max="4" clone-node-max="1" target-role="Started"

Then to define an RA that is used just for monitoring a resource and nothing more. There is no such RA os I had to develop it by myself. As base script I took ocf:heartbeat:apache. You can find it in my Heartbeat resources repository: https://github.com/dotNox/heartbeat_resources . It’s name is httpmon ( as suggested in Linux-HA mailing list ) :). This RA can do almost the same as ocf:heartbeat:apache, but I added the ability to specify user/password for HTTP authentication ( in ocf:heartbeat:apache this is accomplished via an external configuration file which I consider not very practical … ). Here are meta parameters that are available at the time of writing this article:

  • url – URL to check
  • http_user – User for HTTP Auth ( if there is any )
  • http_password –  Password for HTTP Auth ( if there is any ) should be specified with http_user otherwise a default password “password” will be used
  • client – Client to use ( curl, wget or other ) for curl and wget there are predefined client options that are used by default
  • client_opts – Client Addition opts
  • match – Output match regular expression

The primitive definition template will look like:

primitive web_xxx ocf:heartbeat:httpmon \
    params utl="http://10.10.10.X/test.php" match='test string' \
    op monitor interval="5s" enabled="true" role="Started" timeout="20s" start-delay="5s"

And of course group which consist of VIPs and web_xxx resources:

primitive fs_var_www_nfs_client ocf:heartbeat:fs_nfs_client \
    params server="10.10.1.10" server_directory="/var/www" directory="/var/www" \
        statusfile_prefix="nfs/.fs_nfs_client_ha" \
        options="rw,soft,async,retrans=5,noatime,rsize=32768,wsize=32768,proto=udp" \
    op monitor interval="30" timeout="60" on-fail="restart" start-delay="10" OCF_CHECK_LEVEL="20" \
    meta is-managed="true"
group gr_apache_xxx web_xxx VIP_10.10.10.X \
    meta target-role="Started" ordered="true" collocated="true" is-managed="true"
Posted in HA, Heatbeat Resource Agents, httpmon, RA | Leave a comment

HA Storage servers and clients with DRBD, NFS and Heartbeat

Setup description

HA Cluster with three nodes with following properties ( some of them ):

  • Storage Sub-Cluster – two nodes woth DRBD mirroring and NFS Server
  • Storage Clients: NFS Client
Nodes in cluster:
  • Node_Alpha
  • Node_Beta
  • Node_Gamma
Node_Alpha
  • Default resources: NFS Client
  • Failovers to: /dev/null
  • IP Addresses:  eth0: 192.168.10.10, eth1: 10.10.1.1
Node_Beta
  • Default resources: DRBD Primary, NFS Server
  • Failovers to: Node_Gamma
  • IP Addresses:  eth0: 192.168.10.11, eth1: 10.10.1.2
Node_Gamma
  • Default resources: DRBD Secondary, NFS Client
  • Failovers to: /dev/null
  • IP Addresses:  eth0: 192.168.10.12, eth1: 10.10.1.3
VIPs
  • NFS Server:  10.10.1.10

DRBD Configuration

DRBD Mirroring is configure between Node_Beta and Node_Gamma. By default DRBD devices on both nodes will be in Secondary role, only heartbeat will bring device on correct node into Primary role and will mount the partition.
DRBD configuration (Version used: 8.3.x):

global {
    usage-count no;
}
resource repdata {
    protocol C;
    startup {
        wfc-timeout 0;
        degr-wfc-timeout 100;
    }
    disk {
        on-io-error detach;
        no-disk-barrier;
        no-disk-flushes;
        no-md-flushes;
    }
    net {
        sndbuf-size 0;
        cram-hmac-alg "sha1";
        shared-secret "secret_code";
        data-integrity-alg "crc32c";
    }
    syncer {
        rate 85M;
        verify-alg "crc32c";
        csums-alg "crc32c";
    }
    on Node_Beta {
        device /dev/drbd0;
        disk /dev/sda8;
        address 10.10.1.2:7788;
        meta-disk internal;
    }
    on Node_Gamma {
        device /dev/drbd0;
        disk /dev/sda8;
        address 10.10.1.3:7788;
        meta-disk internal;
    }
}

NFS Server and Client configurtaion

NFSv3 over UDP is used for performance. Almost nothing to configure the only thing you can do is to increase nfs daemons on server side.

Heartbeat ( HA Resources ) configuration

Heartbeat Version 3.x with Pacemaker 1.x is used for a better management and configuration. crm_cli is used for configuration.
The first thing I faced with, was Filesystem plugin, that is a part of Heartbeat package. I noticed an issue in it: when it checks a mount it looks only at mount point and not at file system or anything else that could identify the correct mount. In my setup both DRBD device and NFS Clients were mounting in same place: /var/www; so heartbeat had issues to determine if the correct mount for resource is running. To solve this issue I had to write my own check plugin: Filesystem_nfs_client; it is based on standart Filesystem plugin but designed only for NFS mounts. You can find it in my Heartbeat resources repository: https://github.com/dotNox/heartbeat_resources

NFS Server resource configuration
primitive VIP_10.10.1.10 ocf:heartbeat:IPaddr \
    params ip="10.10.1.10" nic="eth1" cidr_netmask="255.255.255.0" \
    op monitor interval="5s" enabled="true" role="Started" timeout="20s" start-delay="1s"
primitive var_www_nfs_server ocf:heartbeat:Filesystem \
    params device="/dev/drbd0" directory="/var/www" fstype="ext3" \
        options="noatime" statusfile_prefix="nfs/.fs_nfs_server_ha" \
    op monitor interval="20" timeout="60" on-fail="restart" start-delay="10"
primitive nfs_server lsb:nfs \
    op monitor interval="10" timeout="15" on-fail="restart" start-delay="15"
group gr_storage_server VIP_10.10.1.10 var_www_nfs_server nfs_server \
    meta ordered="true" collocated="true" is-managed="true"
NFS Client resource configuration
primitive fs_var_www_nfs_client ocf:heartbeat:fs_nfs_client \
    params server="10.10.1.10" server_directory="/var/www" directory="/var/www" \
        statusfile_prefix="nfs/.fs_nfs_client_ha" \
        options="rw,soft,async,retrans=5,noatime,rsize=32768,wsize=32768,proto=udp" \
    op monitor interval="30" timeout="60" on-fail="restart" start-delay="10" OCF_CHECK_LEVEL="20" \
    meta is-managed="true"
clone clone_storage_client fs_var_www_nfs_client \
    meta globally-unique="false" clone-max="2" clone-node-max="1"

You just will have to adjust clone-max to reflect the number of nodes you will have NFS mount on.
And of course constraints, as in our case an NFS server can not run on same machine with NFS Client.

colocation colo_storage -inf: clone_storage_client gr_storage_server

References

Hearbeat and Pacemaker repository and documentation: http://clusterlabs.org/
DRBD Sources/Packages and documentation: 
http://www.drbd.org/

Posted in HA, NFS | Leave a comment