+The primary requirement for an Active/Active cluster is that the data
+required for your services is available, simultaneously, on both
+machines. Pacemaker makes no requirement on how this is achieved, you
+could use a SAN if you had one available, however since DRBD supports
+multiple Primaries, we can also use that.
+
+The only hitch is that we need to use a cluster-aware filesystem. The
+one we used earlier with DRBD, ext4, is not one of those. Both OCFS2
+and GFS2 are supported, however here we will use GFS2 which comes with
+Fedora 13.
+
+We'll also need to use CMAN for Cluster Membership and Quorum instead
+of our Corosync plugin.
+
+
+== Adding CMAN Support ==
+
+http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html-single/Cluster_Suite_Overview/index.html#s2-clumembership-overview-CSO[CMAN v3] is a Corsync plugin that monitors the names and number of active
+cluster nodes in order to deliver membership and quorum information to
+clients (such as the Pacemaker daemons).
+
+In a traditional Corosync-Pacemaker cluster, a Pacemaker plugin is
+loaded to provide membership and quorum information. The motivation
+for wanting to use CMAN for this instead, is to ensure all elements of
+the cluster stack are making decisions based on the same membership
+and quorum data.
+footnote:[A failure to do this can lead to what is called internal
+split-brain - a situation where different parts of the stack disagree
+about whether some nodes are alive or dead - which quickly leads to
+unnecssary down-time and/or data corruption.]
+
+In the case of GFS2, the key pieces are the dlm_controld and
+gfs_controld helpers which act as the glue between the filesystem and
+the cluster software. Supporting CMAN enables us to use the versions
+already being shipped by most distributions (since CMAN has been
+around longer than Pacemaker and is part of the Red Hat cluster
+stack).
+
+[WARNING]
+=========
+Ensure Corosync and Pacemaker are stopped on all nodes before continuing
+=========
+
+[WARNING]
+=========
+Be sure to disable the Pacemaker plugin before continuing with this
+section. In most cases, this can be achieved by removing
+/etc/corosync/service.d/pcmk and stopping Corosync.
+=========
+
+
+=== Installing the required Software ===
+
+[source,Bash]
+-----
+# yum install -y cman gfs2-utils gfs2-cluster
+Loaded plugins: auto-update-debuginfo
+Setting up Install Process
+Resolving Dependencies
+--> Running transaction check
+---> Package cman.x86_64 0:3.1.7-1.fc15 will be installed
+--> Processing Dependency: modcluster >= 0.18.1-1 for package: cman-3.1.7-1.fc15.x86_64
+--> Processing Dependency: fence-agents >= 3.1.5-1 for package: cman-3.1.7-1.fc15.x86_64
+--> Processing Dependency: openais >= 1.1.4-1 for package: cman-3.1.7-1.fc15.x86_64
+--> Processing Dependency: ricci >= 0.18.1-1 for package: cman-3.1.7-1.fc15.x86_64
+--> Processing Dependency: libSaCkpt.so.3(OPENAIS_CKPT_B.01.01)(64bit) for package: cman-3.1.7-1.fc15.x86_64
+--> Processing Dependency: libSaCkpt.so.3()(64bit) for package: cman-3.1.7-1.fc15.x86_64
+---> Package gfs2-cluster.x86_64 0:3.1.1-2.fc15 will be installed
+---> Package gfs2-utils.x86_64 0:3.1.1-2.fc15 will be installed
+--> Running transaction check
+---> Package fence-agents.x86_64 0:3.1.5-1.fc15 will be installed
+--> Processing Dependency: /usr/bin/virsh for package: fence-agents-3.1.5-1.fc15.x86_64
+--> Processing Dependency: net-snmp-utils for package: fence-agents-3.1.5-1.fc15.x86_64
+--> Processing Dependency: sg3_utils for package: fence-agents-3.1.5-1.fc15.x86_64
+--> Processing Dependency: perl(Net::Telnet) for package: fence-agents-3.1.5-1.fc15.x86_64
+--> Processing Dependency: /usr/bin/ipmitool for package: fence-agents-3.1.5-1.fc15.x86_64
+--> Processing Dependency: perl-Net-Telnet for package: fence-agents-3.1.5-1.fc15.x86_64
+--> Processing Dependency: pexpect for package: fence-agents-3.1.5-1.fc15.x86_64
+--> Processing Dependency: pyOpenSSL for package: fence-agents-3.1.5-1.fc15.x86_64
+--> Processing Dependency: python-suds for package: fence-agents-3.1.5-1.fc15.x86_64
+---> Package modcluster.x86_64 0:0.18.7-1.fc15 will be installed
+--> Processing Dependency: oddjob for package: modcluster-0.18.7-1.fc15.x86_64
+---> Package openais.x86_64 0:1.1.4-2.fc15 will be installed
+---> Package openaislib.x86_64 0:1.1.4-2.fc15 will be installed
+---> Package ricci.x86_64 0:0.18.7-1.fc15 will be installed
+--> Processing Dependency: parted for package: ricci-0.18.7-1.fc15.x86_64
+--> Processing Dependency: nss-tools for package: ricci-0.18.7-1.fc15.x86_64
+--> Running transaction check
+---> Package ipmitool.x86_64 0:1.8.11-6.fc15 will be installed
+---> Package libvirt-client.x86_64 0:0.8.8-7.fc15 will be installed
+--> Processing Dependency: libnetcf.so.1(NETCF_1.3.0)(64bit) for package: libvirt-client-0.8.8-7.fc15.x86_64
+--> Processing Dependency: cyrus-sasl-md5 for package: libvirt-client-0.8.8-7.fc15.x86_64
+--> Processing Dependency: gettext for package: libvirt-client-0.8.8-7.fc15.x86_64
+--> Processing Dependency: nc for package: libvirt-client-0.8.8-7.fc15.x86_64
+--> Processing Dependency: libnuma.so.1(libnuma_1.1)(64bit) for package: libvirt-client-0.8.8-7.fc15.x86_64
+--> Processing Dependency: libnuma.so.1(libnuma_1.2)(64bit) for package: libvirt-client-0.8.8-7.fc15.x86_64
+--> Processing Dependency: libnetcf.so.1(NETCF_1.2.0)(64bit) for package: libvirt-client-0.8.8-7.fc15.x86_64
+--> Processing Dependency: gnutls-utils for package: libvirt-client-0.8.8-7.fc15.x86_64
+--> Processing Dependency: libnetcf.so.1(NETCF_1.0.0)(64bit) for package: libvirt-client-0.8.8-7.fc15.x86_64
+--> Processing Dependency: libxenstore.so.3.0()(64bit) for package: libvirt-client-0.8.8-7.fc15.x86_64
+--> Processing Dependency: libyajl.so.1()(64bit) for package: libvirt-client-0.8.8-7.fc15.x86_64
+--> Processing Dependency: libnl.so.1()(64bit) for package: libvirt-client-0.8.8-7.fc15.x86_64
+--> Processing Dependency: libnuma.so.1()(64bit) for package: libvirt-client-0.8.8-7.fc15.x86_64
+--> Processing Dependency: libaugeas.so.0()(64bit) for package: libvirt-client-0.8.8-7.fc15.x86_64
+--> Processing Dependency: libnetcf.so.1()(64bit) for package: libvirt-client-0.8.8-7.fc15.x86_64
+---> Package net-snmp-utils.x86_64 1:5.6.1-7.fc15 will be installed
+---> Package nss-tools.x86_64 0:3.12.10-6.fc15 will be installed
+---> Package oddjob.x86_64 0:0.31-2.fc15 will be installed
+---> Package parted.x86_64 0:2.3-10.fc15 will be installed
+---> Package perl-Net-Telnet.noarch 0:3.03-12.fc15 will be installed
+---> Package pexpect.noarch 0:2.3-6.fc15 will be installed
+---> Package pyOpenSSL.x86_64 0:0.10-3.fc15 will be installed
+---> Package python-suds.noarch 0:0.3.9-3.fc15 will be installed
+---> Package sg3_utils.x86_64 0:1.29-3.fc15 will be installed
+--> Processing Dependency: sg3_utils-libs = 1.29-3.fc15 for package: sg3_utils-1.29-3.fc15.x86_64
+--> Processing Dependency: libsgutils2.so.2()(64bit) for package: sg3_utils-1.29-3.fc15.x86_64
+--> Running transaction check
+---> Package augeas-libs.x86_64 0:0.9.0-1.fc15 will be installed
+---> Package cyrus-sasl-md5.x86_64 0:2.1.23-18.fc15 will be installed
+---> Package gettext.x86_64 0:0.18.1.1-7.fc15 will be installed
+--> Processing Dependency: libgomp.so.1(GOMP_1.0)(64bit) for package: gettext-0.18.1.1-7.fc15.x86_64
+--> Processing Dependency: libgettextlib-0.18.1.so()(64bit) for package: gettext-0.18.1.1-7.fc15.x86_64
+--> Processing Dependency: libgettextsrc-0.18.1.so()(64bit) for package: gettext-0.18.1.1-7.fc15.x86_64
+--> Processing Dependency: libgomp.so.1()(64bit) for package: gettext-0.18.1.1-7.fc15.x86_64
+---> Package gnutls-utils.x86_64 0:2.10.5-1.fc15 will be installed
+---> Package libnl.x86_64 0:1.1-14.fc15 will be installed
+---> Package nc.x86_64 0:1.100-3.fc15 will be installed
+--> Processing Dependency: libbsd.so.0(LIBBSD_0.0)(64bit) for package: nc-1.100-3.fc15.x86_64
+--> Processing Dependency: libbsd.so.0(LIBBSD_0.2)(64bit) for package: nc-1.100-3.fc15.x86_64
+--> Processing Dependency: libbsd.so.0()(64bit) for package: nc-1.100-3.fc15.x86_64
+---> Package netcf-libs.x86_64 0:0.1.9-1.fc15 will be installed
+---> Package numactl.x86_64 0:2.0.7-1.fc15 will be installed
+---> Package sg3_utils-libs.x86_64 0:1.29-3.fc15 will be installed
+---> Package xen-libs.x86_64 0:4.1.1-3.fc15 will be installed
+--> Processing Dependency: xen-licenses for package: xen-libs-4.1.1-3.fc15.x86_64
+---> Package yajl.x86_64 0:1.0.11-1.fc15 will be installed
+--> Running transaction check
+---> Package gettext-libs.x86_64 0:0.18.1.1-7.fc15 will be installed
+---> Package libbsd.x86_64 0:0.2.0-4.fc15 will be installed
+---> Package libgomp.x86_64 0:4.6.1-9.fc15 will be installed
+---> Package xen-licenses.x86_64 0:4.1.1-3.fc15 will be installed
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
-<!ENTITY % BOOK_ENTITIES SYSTEM "Clusters_from_Scratch.ent">
-%BOOK_ENTITIES;
-]>
-<chapter>
- <title>Conversion to Active/Active</title>
- <section>
- <title>Requirements</title>
- <para>
- The primary requirement for an Active/Active cluster is that the data required for your services is available, simultaneously, on both machines.
- Pacemaker makes no requirement on how this is achieved, you could use a SAN if you had one available, however since DRBD supports multiple Primaries, we can also use that.
- </para>
- <para>
- The only hitch is that we need to use a cluster-aware filesystem. The one we used earlier with DRBD, ext4, is not one of those.
- Both OCFS2 and GFS2 are supported, however here we will use GFS2 which comes with &DISTRO; &DISTRO_VERSION; .
- </para>
- <para>
- We'll also need to use CMAN for Cluster Membership and Quorum instead of our Corosync plugin.
- </para>
- </section>
-
- <section>
- <title>Adding CMAN Support</title>
- <para>
- <ulink url="http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html-single/Cluster_Suite_Overview/index.html#s2-clumembership-overview-CSO">CMAN v3</ulink> is a Corsync plugin that monitors the names and number of active cluster nodes in order to deliver membership and quorum information to clients (such as the Pacemaker daemons).
- </para>
- <para>
- In a traditional Corosync-Pacemaker cluster, a Pacemaker plugin is loaded to provide membership and quorum information.
- The motivation for wanting to use CMAN for this instead, is to ensure all elements of the cluster stack are making decisions based on the same membership and quorum data.
- <footnote>
- <para>
- A failure to do this can lead to what is called <literal>internal split-brain</literal> - a situation where different parts of the stack disagree about whether some nodes are alive or dead - which quickly leads to unnecssary down-time and/or data corruption.
- </para>
- </footnote>
- </para>
- <para>
- In the case of GFS2, the key pieces are the <filename>dlm_controld</filename> and <filename>gfs_controld</filename> helpers which act as the glue between the filesystem and the cluster software.
- Supporting CMAN enables us to use the versions already being shipped by most distributions (since CMAN has been around longer than Pacemaker and is part of the Red Hat cluster stack).
- </para>
- <warning>
- <para>
- Ensure Corosync and Pacemaker are stopped <emphasis>on all nodes</emphasis> before continuing
- </para>
- </warning>
- <warning>
- <para>
- Be sure to disable the Pacemaker plugin before continuing with this section.
- In most cases, this can be achieved by removing <filename>/etc/corosync/service.d/pcmk</filename> and stopping Corosync.
- Next we create a basic configuration file and place is in <filename>/etc/cluster/cluster.conf</filename>.
- The <constant>name</constant> used for each <constant>clusternode</constant> should correspond to that node's <command>uname -n</command>, just as Pacemaker expects.
- The <constant>nodeid</constant> can be any positive mumber but nust be unique.
- <example>
- <title>Basic cluster.conf for a two-node cluster</title>
- We configure the <filename>fence_pcmk</filename> agent (supplied with Pacemaker) to redirect any fencing requests from CMAN components (such as dlm_controld) to Pacemaker.
- Pacemaker's fencing subsystem lets other parts of the stack know that a node has been successfully fenced, thus avoiding the need for it to be fenced again when other subsystems notice the node is gone.
- <warning>
- <para>
- Configuring real fencing devices in CMAN will result in nodes being fenced multiple times as different parts of the stack notice the node is missing or failed.
- </para>
- </warning>
- </para>
- <para>
- The definition should be placed in the <constant>fencedevices</constant> section and contain:
- <programlisting>
- <![CDATA[
- <fencedevice name="pcmk" agent="fence_pcmk"/>
- ]]>
- </programlisting>
- Each <constant>clusternode</constant> must be configured to use this <quote>device</quote> by adding a <constant>fence method</constant> block that lists the node's <constant>name</constant> as the <constant>port</constant>.
- <programlisting>
- <![CDATA[
- <fence>
- <method name="pcmk-redirect">
- <device name="pcmk" port="node_name_here"/>
- </method>
- </fence>
- ]]>
- </programlisting>
- </para>
- <para>
- Putting everything together, we have:
- <example>
- <title>cluster.conf for a two-node cluster with fencing</title>
- <programlisting>
- <![CDATA[
-<?xml version="1.0"?>
-<cluster config_version="1" name="mycluster">
- <logging debug="off"/>
- <clusternodes>
- <clusternode name="pcmk-1" nodeid="1">
- <fence>
- <method name="pcmk-redirect">
- <device name="pcmk" port="pcmk-1"/>
- </method>
- </fence>
- </clusternode>
- <clusternode name="pcmk-2" nodeid="2">
- <fence>
- <method name="pcmk-redirect">
- <device name="pcmk" port="pcmk-2"/>
- </method>
- </fence>
- </clusternode>
- </clusternodes>
- <fencedevices>
- <fencedevice name="pcmk" agent="fence_pcmk"/>
- </fencedevices>
-</cluster>
- ]]>
- </programlisting>
- </example>
- </para>
- </section>
- <section>
- <title>Bringing the Cluster Online with CMAN</title>
- <para>
- The first thing to do is check that the configuration is valid
- You should now see both nodes online and services started.
- </para>
- </section>
- </section>
- <section id="gfs-create-filesystem">
- <title>Create a GFS2 Filesystem</title>
- <section>
- <title>Preparation</title>
- <para>
- Before we do anything to the existing partition, we need to make sure it is unmounted. We do this by tell the cluster to stop the WebFS resource. This will ensure that other resources (in our case, Apache) using WebFS are not only stopped, but stopped in the correct order.
-ClusterIP (ocf::heartbeat:IPaddr): Started pcmk-1
-</screen>
- <note>
- <para>
- Note that both Apache and WebFS have been stopped.
- </para>
- </note>
- </section>
-
- <section>
- <title>Create and Populate an GFS2 Partition</title>
- <para>
- Now that the cluster stack and integration pieces are running smoothly, we can create an GFS2 partition.
- </para>
- <warning>
- <para>
- This will erase all previous content stored on the DRBD device. Ensure you have a copy of any important data.
- </para>
- </warning>
- <para>
- We need to specify a number of additional parameters when creating a GFS2 partition.
- </para>
- <para>
- First we must use the -p option to specify that we want to use the the Kernel’s DLM. Next we use -j to indicate that it should reserve enough space for two journals (one per node accessing the filesystem).
- </para>
- <para>
- Lastly, we use -t to specify the lock table name. The format for this field is clustername:fsname. For the fsname, we just need to pick something unique and descriptive and since we haven’t specified a clustername yet, we will use the default (pcmk).
- </para>
- <para>
- To specify an alternate name for the cluster, locate the service section containing "name: pacemaker" in corosync.conf and insert the following line anywhere inside the block:
- </para>
- <para>
- clustername: myname
- </para>
- <para>
- Do this on each node in the cluster and be sure to restart them before continuing.
- Now that we’ve recreated the resource, we also need to recreate all the constraints that used it. This is because the shell will automatically remove any constraints that referenced WebFS.
-ClusterIP (ocf::heartbeat:IPaddr): Started pcmk-2
-<emphasis>WebFS (ocf::heartbeat:Filesystem): Started pcmk-1</emphasis>
-</screen>
- </section>
- <section>
- <title>Reconfigure Pacemaker for Active/Active</title>
- <para>
- Almost everything is in place.
- Recent versions of DRBD are capable of operating in Primary/Primary mode and the filesystem we’re using is cluster aware.
- All we need to do now is reconfigure the cluster to take advantage of this.
- </para>
- <para>
- This will involve a number of changes, so we’ll again use interactive mode.
- </para>
-
- <screen>
-[root@pcmk-1 ~]# <userinput>crm</userinput>
-[root@pcmk-1 ~]# <userinput>cib new active</userinput>
- </screen>
- <para>
- There’s no point making the services active on both locations if we can’t reach them, so lets first clone the IP address.
- Cloned IPaddr2 resources use an iptables rule to ensure that each request only processed by one of the two clone instances.
- The additional meta options tell the cluster how many instances of the clone we want (one "request bucket" for each node) and that if all other nodes fail, then the remaining node should hold all of them.
- Otherwise the requests would be simply discarded.
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
-<!ENTITY % BOOK_ENTITIES SYSTEM "Clusters_from_Scratch.ent">
-%BOOK_ENTITIES;
-]>
-<chapter>
- <title>Replicated Storage with DRBD</title>
- <para>
- Even if you’re serving up static websites, having to manually synchronize the contents of that website to all the machines in the cluster is not ideal.
- For dynamic websites, such as a wiki, its not even an option.
- Not everyone care afford network-attached storage but somehow the data needs to be kept in sync.
- Enter DRBD which can be thought of as network based RAID-1.
- See <ulink url="http://www.drbd.org/">http://www.drbd.org</ulink>/ for more details.
- </para>
- <para>
- </para>
- <section>
- <title>Install the DRBD Packages</title>
- <para>
- Since its inclusion in the upstream 2.6.33 kernel, everything needed to use DRBD ships with &DISTRO; &DISTRO_VERSION;.
- There is no series of commands for build a DRBD configuration, so simply copy the configuration below to /etc/drbd.conf
- </para>
- <para>
- Detailed information on the directives used in this configuration (and other alternatives) is available from <ulink url="http://www.drbd.org/users-guide/ch-configure.html">http://www.drbd.org/users-guide/ch-configure.html</ulink>
- </para>
- <warning>
- <para>
- Be sure to use the names and addresses of <emphasis>your</emphasis> nodes if they differ from the ones used in this guide.
- </para>
- </warning>
- <screen>
-global {
- usage-count yes;
-}
-common {
- protocol C;
-}
-resource wwwdata {
- meta-disk internal;
- device /dev/drbd1;
- syncer {
- verify-alg sha1;
- }
- net {
- allow-two-primaries;
- }
- <emphasis> on pcmk-1</emphasis> {
- disk /dev/mapper/<emphasis>VolGroup</emphasis>-drbd--demo;
- Include details on adding a second DRBD resource
- </para>
- </note>
- <para>
- Now that DRBD is functioning we can configure a Filesystem resource to use it.
- In addition to the filesystem’s definition, we also need to tell the cluster where it can be located (only on the DRBD Primary) and when it is allowed to start (after the Primary was promoted).
- </para>
- <para>
- Once again we’ll use the shell’s interactive mode
- Once we’ve done everything we needed to on pcmk-1 (in this case nothing, we just wanted to see the resources move), we can allow the node to be a full cluster member again.