I installed the software the exact same on both Dell servers. The two dell servers were then connected to the gigabit switch (192.168.1.x), which also connected the other nodes to the SAN. I would NOT recommend using a 100Mbps switch, as you’ll likely saturate the line. 1Gbps provided me with enough bandwidth. The two SAN servers were also connected with a crossover cable on a separate network (10.0.0.x). This allowed DRBD to have a dedicated 1Gbps line to replicate data between the two servers. The ‘nodes’ in the cluster mount the iSCSI drive over the local network.
Essentially, I followed all of the typical configuration steps for the above software. You’ll need a working installation of CentOS. Nothing too special, though. I prefer to keep my servers slim and install only the minimum, leaving off the graphical interface. The only exception to this is the cluster nodes, because OCFS requires the GUI in order to set-up and maintain the cluster configuration.
global {
usage-count yes;
}
common {
syncer { rate 100M; }
}
resource drbd0 {
protocol C;
handlers {
pri-on-incon-degr “echo o > /proc/sysrq-trigger ; halt -f”;
pri-lost-after-sb “echo o > /proc/sysrq-trigger ; halt -f”;
local-io-error “echo o > /proc/sysrq-trigger ; halt -f”;
outdate-peer “/usr/lib64/heartbeat/drbd-peer-outdater”;
}
startup {
wfc-timeout 600;
degr-wfc-timeout 120; # 2 minutes.
}
disk {
on-io-error detach;
fencing resource-only;
}
net {
cram-hmac-alg “sha1″;
shared-secret “ImNotPostingThatOnTheInternet”;
after-sb-0pri disconnect;
after-sb-1pri disconnect;
after-sb-2pri disconnect;
rr-conflict disconnect;
}
on san1.xxxxxx.com {
device /dev/drbd0;
disk /dev/sdb1;
address 10.0.0.1:7788;
flexible-meta-disk internal;
}
on san2.xxxxxx.com {
device /dev/drbd0;
disk /dev/sdb1;
address 10.0.0.2:7788;
flexible-meta-disk internal;
}
}
While the full configuration of DRBD is outside the scope of this post (and LinBit has a great
User Guide), there are a few things to point out. First off, I have DRBD communicating on its own private network, on port 7788. Also, note that /dev/sb1 is where my 1TB RAID array is located (as far as CentOS is concerned). This is my shared storage.
So, at this point we have DRBD working. Next, let’s get Heartbeat up and running to manage the drive and failover. Again, full configuration of Heartbeat is outside the scope of this posting, but again, g
reat information is available on their web site.
For this set-up, my heartbeat config (cib.xml) looks like this (I apologize in advance for the wrapping):
<cib admin_epoch=”0″ have_quorum=”true” num_peers=”1″ cib_feature_revision=”1.3″ generated=”true” epoch=”242″ ignore_dtd=”false” nu
m_updates=”13″ cib-last-written=”Sat Feb 23 13:51:32 2008″ ccm_transition=”1″ dc_uuid=”0a38edda-e639-4f27-87c2-142ef3ff1fa9″>
<configuration>
<crm_config>
<cluster_property_set id=”default”>
<attributes>
<nvpair id=”symmetric-cluster” name=”symmetric-cluster” value=”true”/>
<nvpair id=”no-quorum-policy” name=”no-quorum-policy” value=”stop”/>
<nvpair id=”stonith-enabled” name=”stonith-enabled” value=”false”/>
<nvpair id=”short-resource-names” name=”short-resource-names” value=”true”/>
<nvpair id=”is-managed-default” name=”is-managed-default” value=”true”/>
<nvpair id=”transition-idle-timeout” name=”transition-idle-timeout” value=”60000″/>
<nvpair id=”default-resource-stickiness” name=”default-resource-stickiness” value=”INFINITY”/>
<nvpair id=”stop-orphan-resources” name=”stop-orphan-resources” value=”false”/>
<nvpair id=”stop-orphan-actions” name=”stop-orphan-actions” value=”false”/>
<nvpair id=”remove-after-stop” name=”remove-after-stop” value=”false”/>
</attributes>
</cluster_property_set>
<cluster_property_set id=”cib-bootstrap-options”>
<attributes>
<nvpair id=”cib-bootstrap-options-dc-version” name=”dc-version” value=”2.1.3-node: 552305612591183b1628baa5bc6e903e0f1e26
a3″/>
</attributes>
</cluster_property_set>
</crm_config>
<nodes>
<node id=”c343bdeb-26d4-405b-b852-04ed6a2a27c4″ uname=”san1.xxxxxx.com” type=”normal”/>
<node id=”0a38edda-e639-4f27-87c2-142ef3ff1fa9″ uname=”san2.xxxxxx.com” type=”normal”/>
</nodes>
<resources>
<group id=”san_group”>
<primitive class=”heartbeat” id=”drbd” provider=”heartbeat” type=”drbddisk”>
<operations>
<op id=”drbd_monitor” interval=”120s” name=”monitor” timeout=”60s”/>
</operations>
<instance_attributes id=”drbd_attributes”>
<attributes>
<nvpair id=”drbd_resource_name” name=”1″ value=”drbd0″/>
</attributes>
</instance_attributes>
</primitive>
<primitive id=”ip_resource_1″ class=”ocf” type=”IPaddr” provider=”heartbeat”>
<instance_attributes id=”ip_attributes”>
<attributes>
<nvpair id=”ipaddr_ip” name=”ip” value=”192.168.1.200″/>
</attributes>
</instance_attributes>
</primitive>
<primitive id=”ietdid” class=”lsb” type=”iscsi-target”/>
</group>
</resources>
<constraints>
<rsc_location id=”run_ip_resource_1″ rsc=”ip_resource_1″>
<rule id=”pref_run_ip_resource_1″ score=”100″>
<expression attribute=”#uname” operation=”eq” value=”san1″ id=”san1″/>
</rule>
</rsc_location>
<rsc_order id=”order1″ from=”drbd” action=”start” type=”before” to=”ip_resource_1″/>
<rsc_order id=”order2″ from=”ip_resource_1″ action=”start” type=”before” to=”ietdid”/>
</constraints>
</configuration>
<status>
<node_state id=”0a38edda-e639-4f27-87c2-142ef3ff1fa9″ uname=”san2.xxxxx.com” crmd=”online” crm-debug-origin=”do_update_r
esource” shutdown=”0″ in_ccm=”true” ha=”active” join=”member” expected=”member”>
<lrm id=”0a38edda-e639-4f27-87c2-142ef3ff1fa9″>
<lrm_resources>
<lrm_resource id=”drbd” type=”drbddisk” class=”heartbeat” provider=”heartbeat”>
<lrm_rsc_op id=”drbd_monitor_0″ operation=”monitor” crm-debug-origin=”do_update_resource” transition_key=”3:0:379e97e4-
cfbd-47c4-8da9-2fa60ac47451″ transition_magic=”0:7;3:0:379e97e4-cfbd-47c4-8da9-2fa60ac47451″ call_id=”2″ crm_feature_set=”2.0″ rc_co
de=”7″ op_status=”0″ interval=”0″ op_digest=”ea09f933342d2b2407fb06548c8249df”/>
<lrm_rsc_op id=”drbd_start_0″ operation=”start” crm-debug-origin=”do_update_resource” transition_key=”7:0:379e97e4-cfbd
-47c4-8da9-2fa60ac47451″ transition_magic=”4:1;7:0:379e97e4-cfbd-47c4-8da9-2fa60ac47451″ call_id=”5″ crm_feature_set=”2.0″ rc_code=”
1″ op_status=”4″ interval=”0″ op_digest=”ea09f933342d2b2407fb06548c8249df”/>
<lrm_rsc_op id=”drbd_stop_0″ operation=”stop” crm-debug-origin=”do_update_resource” transition_key=”1:1:379e97e4-cfbd-4
7c4-8da9-2fa60ac47451″ transition_magic=”0:0;1:1:379e97e4-cfbd-47c4-8da9-2fa60ac47451″ call_id=”6″ crm_feature_set=”2.0″ rc_code=”0″
op_status=”0″ interval=”0″ op_digest=”ea09f933342d2b2407fb06548c8249df”/>
</lrm_resource>
<lrm_resource id=”ip_resource_1″ type=”IPaddr” class=”ocf” provider=”heartbeat”>
<lrm_rsc_op id=”ip_resource_1_monitor_0″ operation=”monitor” crm-debug-origin=”do_update_resource” transition_key=”4:0:
379e97e4-cfbd-47c4-8da9-2fa60ac47451″ transition_magic=”0:7;4:0:379e97e4-cfbd-47c4-8da9-2fa60ac47451″ call_id=”3″ crm_feature_set=”2
.0″ rc_code=”7″ op_status=”0″ interval=”0″ op_digest=”fbfabc6bc90887bc11bf8ed485ec821d”/>
</lrm_resource>
<lrm_resource id=”ietdid” type=”iscsi-target” class=”lsb”>
<lrm_rsc_op id=”ietdid_monitor_0″ operation=”monitor” crm-debug-origin=”do_update_resource” transition_key=”5:0:379e97e
4-cfbd-47c4-8da9-2fa60ac47451″ transition_magic=”0:7;5:0:379e97e4-cfbd-47c4-8da9-2fa60ac47451″ call_id=”4″ crm_feature_set=”2.0″ rc_
code=”7″ op_status=”0″ interval=”0″ op_digest=”f2317cad3d54cec5d7d7aa7d0bf35cf8″/>
</lrm_resource>
</lrm_resources>
</lrm>
<transient_attributes id=”0a38edda-e639-4f27-87c2-142ef3ff1fa9″>
<instance_attributes id=”status-0a38edda-e639-4f27-87c2-142ef3ff1fa9″>
<attributes>
<nvpair id=”status-0a38edda-e639-4f27-87c2-142ef3ff1fa9-probe_complete” name=”probe_complete” value=”true”/>
<nvpair id=”status-0a38edda-e639-4f27-87c2-142ef3ff1fa9-fail-count-drbd” name=”fail-count-drbd” value=”1″/>
</attributes>
</instance_attributes>
</transient_attributes>
</node_state>
</status>
</cib>
The only real things to point out here are that I have a ‘drbddisk’ defined and I’ve told heartbeat to manage it, as well as that I have defined a virtual IP address - 192.168.1.200. This IP will ‘float’ between the two servers, depending on which server is active. THIS IS THE IP THAT ISCSI WILL RUN ON!!! That’s critical. That allows me to configure the nodes to look for iSCSI drives on that IP and still have the cluster failover properly. That means, if the primary server fails, the secondary server should come up and essentially tell DRBD ‘you are now primary, take over’. The other piece to heartbeat is the ha.cf, which is pretty straightforward:
keepalive 3
deadtime 15
warntime 9
initdead 30
auto_failback off
node san1.xxxxxx.com san2.xxxxxx.com
udpport 694
baud 19200
serial /dev/ttyS0
crm yes
bcast eth0
use_logd yes
ping 192.168.1.1
respawn hacluster /usr/lib64/heartbeat/dopd
apiauth dopd gid=haclient uid=hacluster
Basically, this file defines the cluster members and how the cluster will communicate. In my case, I’m communicating over a serial port AND over ethernet. This is critical - you need more than one communication path. If you only communicate over ethernet and your network has a small hiccup, both nodes will think the other went away and will BOTH try to be primary, which can be a very bad thing.
OK, so here we are, we have DRBD set up to mirror the data between the two servers and heartbeat set up to manage the failover. Almost there. Now, we need a way to export the device. For this, I’m using iSCSI.
I choose to use IETD -
iSCSI Enterprise Target. Installation was really quite simple. I downloaded the file, untarred it, and just followed the instructions in the README - basically, just make && make install. Configuration is pretty straight-forward, too. There is a default config file that pretty much has everything you need, just a few things to update, such as your target name. Honestly, the file is commented so good that I’m not going to post it. All I had to do was specify the Target name, the authentication username/password (which is so basic that it hardly provides an protection) and the location of the drive to export.
This is the one thing that threw me off for a bit - you MUST EXPORT THE DRBD DRIVE. If you export your physical drive, the data will not be mirrored. So, in my case, this looked like:
Lun 0 Path=/dev/drbd0,Type=fileio
Now, I’ve got everything I need set up on the SAN servers. Remember, I have 2 servers for the failover, so all of this must be done on both servers. Time for the nodes…
Each node will need OCFS2 and OCFS2 Tools installed. Again, this is beyond the scope of this document. However, Oracle provides RPMS for RHEL, which will install just fine on CentOS. Again, for the initial setup, you need the GUI (X-Windows, Gnome, KDE, etc). The GUI generates a config file for OCFS2. Just follow the instructions provided by Oracle for this step. It’s really pretty simple. You’re basically just naming the nodes and assigning them to a cluster.
The only trick with the nodes is to discover the iSCSI drive and add it to /etc/fstab so that it finds it on boot. You’ll need iscsi-initiator-utils for RHEL5 or CentOS 5. Basically, once you have that installed, you’ll just need to:
iscsiadm -m discovery -t sendtargets -p
You can then login to the device you find with:
iscsiadm -m node -T iqn.2001-04.il.org.tournament:diskserv.disk1 -p :3260,1 -l
To have the discovery happen automatically, you’ll need to create a file in /etc/iscsi/ called ‘initiatorname.iscsi’. You can read more
at this site.
After you can see the drive, make sure you format it with OCFS. Again, this is very simple through the GUI that Oracle provides.
At this point, we’re ready to edit the /etc/fstab file. I added:
/dev/sdb /data ocfs2 _netdev 0 0
The _netdev command tells the OS that this drive is mounted over the network, so we need to wait for the network to be available before attempting to mount this drive. By this point, OCFS will have started up, so it will be ready to handle the drive. You can see that I’m mounting mine to a /data directory.
Next? Test it out!! Make sure that OCFS is set to start on boot on all of the nodes, which it should be.