How To Configure High-Availability Cluster on CentOS 7 / RHEL 7

High-Availability cluster aka Failover-cluster (active-passive cluster) is one of the most widely used cluster types in the production environment. This type of cluster provides you the continued availability of services even one of the cluster nodes fails. If the server running application has failed for some reason (hardware failure), cluster software (pacemaker) will restart the application on another node.

High-Availability is mainly used for databases, custom application, and also for file sharing. Fail-over is not just starting an application. It has some series of operations associated with it like, mounting filesystems, configuring networks and starting dependent applications.

Environment

CentOS 7 / RHEL 7 supports Fail-over cluster using the pacemaker. Here, we will be looking at configuring the Apache (web) server as a highly available application.

As I said, fail-over is a series of operations, so we would need to configure filesystem and networks as a resource. For a filesystem, we would be using a shared storage from iSCSI storage.

Configure High-Availability Cluster on CentOS 7 – Infrastructure
Host Name IP Address OS Purpose
node1.itzgeek.local 192.168.1.11 CentOS 7 Cluster Node 1
node2.itzgeek.local 192.168.1.12 Cluster Node 1
server.itzgeek.local 192.168.1.20 iSCSI Shared Storage
192.168.1.100 Virtual Cluster IP (Apache)

All are running on VMware Workstation.

Shared Storage

Shared storage is one of the important resources in the high-availability cluster as it holds the data of a running application. All the nodes in a cluster will have access to shared storage for recent data. SAN storage is the most widely used shared storage in the production environment. For this demo, we will configure a cluster with iSCSI storage for a demonstration purpose.

Install Packages

iSCSI Server

[root@server ~]# yum install targetcli -y

Cluster Nodes

It’s the time to configure cluster nodes to make use of iSCSI storage, perform below steps on all of your cluster nodes.

# yum install iscsi-initiator-utils -y

Setup Disk

Here, we will create 10GB of LVM disk on the iSCSI server to use as shared storage for our cluster nodes. Let’s list the available disks attached to the target server using the command.

[root@server ~]# fdisk -l | grep -i sd

Output:

Disk /dev/sda: 107.4 GB, 107374182400 bytes, 209715200 sectors
/dev/sda1 * 2048 1026047 512000 83 Linux
/dev/sda2 1026048 209715199 104344576 8e Linux LVM
Disk /dev/sdb: 10.7 GB, 10737418240 bytes, 20971520 sectors

From the above output, you can see that my system has 10GB of hard disk (/dev/sdb). Create an LVM with /dev/sdb (replace /dev/sdb with your disk name)

[root@server ~]# pvcreate /dev/sdb

[root@server ~]# vgcreate vg_iscsi /dev/sdb

[root@server ~]# lvcreate -l 100%FREE -n lv_iscsi vg_iscsi

Create Shared Storage

Get the nodes initiator’s details.

cat /etc/iscsi/initiatorname.iscsi

Node 1:

InitiatorName=iqn.1994-05.com.redhat:b11df35b6f75

Node 2:

InitiatorName=iqn.1994-05.com.redhat:119eaf9252a

Enter below command to get an iSCSI CLI for an interactive prompt.

[root@server ~]# targetcli

Output:

targetcli shell version 2.1.fb46
Copyright 2011-2013 by Datera, Inc and others.
For help on commands, type 'help'.

/> cd /backstores/block
/backstores/block> create iscsi_shared_storage /dev/vg_iscsi/lv_iscsi
Created block storage object iscsi_shared_storage using /dev/vg_iscsi/lv_iscsi.
/backstores/block> cd /iscsi
/iscsi> create
Created target iqn.2003-01.org.linux-iscsi.server.x8664:sn.518a1f561ad5.
Created TPG 1.
Global pref auto_add_default_portal=true
Created default portal listening on all IPs (0.0.0.0), port 3260.
/iscsi> cd iqn.2003-01.org.linux-iscsi.server.x8664:sn.518a1f561ad5/tpg1/acls
/iscsi/iqn.20...ad5/tpg1/acls> create iqn.1994-05.com.redhat:b11df35b6f75   << Initiator of Node 1
Created Node ACL for iqn.1994-05.com.redhat:b11df35b6f75
/iscsi/iqn.20...ad5/tpg1/acls> create iqn.1994-05.com.redhat:119eaf9252a    << Initiator of Node 1
Created Node ACL for iqn.1994-05.com.redhat:119eaf9252a
/iscsi/iqn.20...ad5/tpg1/acls> cd /iscsi/iqn.2003-01.org.linux-iscsi.server.x8664:sn.518a1f561ad5/tpg1/luns
/iscsi/iqn.20...ad5/tpg1/luns> create /backstores/block/iscsi_shared_storage
Created LUN 0.
Created LUN 0->0 mapping in node ACL iqn.1994-05.com.redhat:119eaf9252a
Created LUN 0->0 mapping in node ACL iqn.1994-05.com.redhat:b11df35b6f75
/iscsi/iqn.20...ad5/tpg1/luns> cd /
/> ls
o- / ...................................................................................................... [...]
  o- backstores ........................................................................................... [...]
  | o- block ............................................................................... [Storage Objects: 1]
  | | o- iscsi_shared_storage ........................... [/dev/vg_iscsi/lv_iscsi (10.0GiB) write-thru activated]
  | |   o- alua ................................................................................ [ALUA Groups: 1]
  | |     o- default_tg_pt_gp .................................................... [ALUA state: Active/optimized]
  | o- fileio .............................................................................. [Storage Objects: 0]
  | o- pscsi ............................................................................... [Storage Objects: 0]
  | o- ramdisk ............................................................................. [Storage Objects: 0]
  o- iscsi ......................................................................................... [Targets: 1]
  | o- iqn.2003-01.org.linux-iscsi.server.x8664:sn.518a1f561ad5 ....................................... [TPGs: 1]
  |   o- tpg1 ............................................................................ [no-gen-acls, no-auth]
  |     o- acls ....................................................................................... [ACLs: 2]
  |     | o- iqn.1994-05.com.redhat:119eaf9252a ................................................ [Mapped LUNs: 1]
  |     | | o- mapped_lun0 ............................................... [lun0 block/iscsi_shared_storage (rw)]
  |     | o- iqn.1994-05.com.redhat:b11df35b6f75 ............................................... [Mapped LUNs: 1]
  |     |   o- mapped_lun0 ............................................... [lun0 block/iscsi_shared_storage (rw)]
  |     o- luns ....................................................................................... [LUNs: 1]
  |     | o- lun0 ...................... [block/iscsi_shared_storage (/dev/vg_iscsi/lv_iscsi) (default_tg_pt_gp)]
  |     o- portals ................................................................................. [Portals: 1]
  |       o- 0.0.0.0:3260 .................................................................................. [OK]
  o- loopback ...................................................................................... [Targets: 0]
/> saveconfig
Configuration saved to /etc/target/saveconfig.json
/> exit
Global pref auto_save_on_exit=true
Last 10 configs saved in /etc/target/backup/.
Configuration saved to /etc/target/saveconfig.json
[root@server ~]#

Enable and restart the target service.

[root@server ~]# systemctl enable target

[root@server ~]# systemctl restart target

Configure the firewall to allow iSCSI traffic.

[root@server ~]# firewall-cmd --permanent --add-port=3260/tcp

[root@server ~]# firewall-cmd --reload

Discover Shared Storage

On both cluster nodes, discover the target using below command.

# iscsiadm -m discovery -t st -p 192.168.1.20

Output:

192.168.1.20:3260,1 iqn.2003-01.org.linux-iscsi.server.x8664:sn.518a1f561ad5

Now, login to the target with the below command.

# iscsiadm -m node -T iqn.2003-01.org.linux-iscsi.server.x8664:sn.518a1f561ad5 -p 192.168.1.20 -l

Output:

Logging in to [iface: default, target: iqn.2003-01.org.linux-iscsi.server.x8664:sn.518a1f561ad5, portal: 192.168.1.20,3260] (multiple)
Login to [iface: default, target: iqn.2003-01.org.linux-iscsi.server.x8664:sn.518a1f561ad5, portal: 192.168.1.20,3260] successful.

Restart and enable the initiator service.

# systemctl restart iscsid

# systemctl enable iscsid

Setup Cluster Nodes

Host Entry

Make a host entry on each node for all nodes. The cluster will be using the hostname to communicate with each other.

# vi /etc/hosts

Host entries will be something like below.

192.168.1.11 node1.itzgeek.local  node1
192.168.1.12 node2.itzgeek.local  node2

Shared Storage

Go to all of your nodes and check whether the new disk is visible or not. In my nodes, /dev/sdb is the disk coming from our iSCSI storage.

# fdisk -l | grep -i sd

Output:

Disk /dev/sda: 107.4 GB, 107374182400 bytes, 209715200 sectors 
/dev/sda1 * 2048 1026047 512000 83 Linux 
/dev/sda2 1026048 209715199 104344576 8e Linux LVM
Disk /dev/sdb: 10.7 GB, 10733223936 bytes, 20963328 sectors

On any one of your node (Ex, node1), create a filesystem for the Apache web server to hold the website files. We will create a filesystem with LVM.

[root@node1 ~]# pvcreate /dev/sdb

[root@node1 ~]# vgcreate vg_apache /dev/sdb

[root@node1 ~]# lvcreate -n lv_apache -l 100%FREE vg_apache

[root@node1 ~]# mkfs.ext4 /dev/vg_apache/lv_apache

Now, go to another node and run below commands to detect the new filesystem.

[root@node2 ~]# pvscan

[root@node2 ~]# vgscan

[root@node2 ~]# lvscan

Finally, verify the LVM we created on node1 is available to you on another node (Ex. node2) using below command.

[root@node2 ~]# lvdisplay /dev/vg_apache/lv_apache

Output: You should see /dev/vg_apache/lv_apache on node2.itzgeek.local

 --- Logical volume ---
  LV Path                /dev/vg_apache/lv_apache
  LV Name                lv_apache
  VG Name                vg_apache
  LV UUID                mFUyuk-xTtK-r7PV-PLPq-yoVC-Ktto-TcaYpS
  LV Write Access        read/write
  LV Creation host, time node1.itzgeek.local, 2019-07-05 08:57:33 +0530
  LV Status              available
  # open                 0
  LV Size                9.96 GiB
  Current LE             2551
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     8192
  Block device           253:3
If the system doesn’t display the logical volume, consider rebooting the second node.

Install Packages

Install cluster packages (pacemaker) on all nodes using below command.

# yum install pcs fence-agents-all -y

Allow all high availability application on the firewall to have proper communication between nodes. You can skip this step if the system doesn’t have firewalld installed.

# firewall-cmd --permanent --add-service=high-availability

# firewall-cmd --add-service=high-availability

Use below command to list down the allowed applications in the firewall.

# firewall-cmd --list-service

Output:

ssh dhcpv6-client high-availability

Set password for the hacluster user. This user account is a cluster administration account. We suggest you set the same password for all nodes.

# passwd hacluster

Start the cluster service. Also, enable it to start automatically on system startup.

# systemctl start pcsd

# systemctl enable pcsd

Remember to run the above commands on all of your cluster nodes.

Create a High Availability Cluster

Authorize the nodes using below command. Run the below command in any one of the nodes to authorize the nodes.

[root@node1 ~]# pcs cluster auth node1.itzgeek.local node2.itzgeek.local

Output:

Username: hacluster
Password:      << Enter Password
node1.itzgeek.local: Authorized
node2.itzgeek.local: Authorized

Create a cluster.

[root@node1 ~]# pcs cluster setup --start --name itzgeek_cluster node1.itzgeek.local node2.itzgeek.local

Output:

Destroying cluster on nodes: node1.itzgeek.local, node2.itzgeek.local...
node1.itzgeek.local: Stopping Cluster (pacemaker)...
node2.itzgeek.local: Stopping Cluster (pacemaker)...
node2.itzgeek.local: Successfully destroyed cluster
node1.itzgeek.local: Successfully destroyed cluster

Sending 'pacemaker_remote authkey' to 'node1.itzgeek.local', 'node2.itzgeek.local'
node1.itzgeek.local: successful distribution of the file 'pacemaker_remote authkey'
node2.itzgeek.local: successful distribution of the file 'pacemaker_remote authkey'
Sending cluster config files to the nodes...
node1.itzgeek.local: Succeeded
node2.itzgeek.local: Succeeded

Starting cluster on nodes: node1.itzgeek.local, node2.itzgeek.local...
node1.itzgeek.local: Starting Cluster (corosync)...
node2.itzgeek.local: Starting Cluster (corosync)...
node1.itzgeek.local: Starting Cluster (pacemaker)...
node2.itzgeek.local: Starting Cluster (pacemaker)...

Synchronizing pcsd certificates on nodes node1.itzgeek.local, node2.itzgeek.local...
node1.itzgeek.local: Success
node2.itzgeek.local: Success
Restarting pcsd on the nodes in order to reload the certificates...
node1.itzgeek.local: Success
node2.itzgeek.local: Success

Enable the cluster to start at the system startup.

[root@node1 ~]# pcs cluster enable --all

Output:

node1.itzgeek.local: Cluster Enabled
node2.itzgeek.local: Cluster Enabled

Use below command to get the status of the cluster.

[root@node1 ~]# pcs cluster status

Output:

Cluster Status:
 Stack: corosync
 Current DC: node2.itzgeek.local (version 1.1.19-8.el7_6.4-c3c624ea3d) - partition with quorum
 Last updated: Fri Jul  5 09:14:57 2019
 Last change: Fri Jul  5 09:13:12 2019 by hacluster via crmd on node2.itzgeek.local
 2 nodes configured
 0 resources configured

PCSD Status:
  node1.itzgeek.local: Online
  node2.itzgeek.local: Online

Run the below command to get detailed information about the cluster, including its resources, pacemaker status, and nodes details.

[root@node1 ~]# pcs status

Output:

Cluster name: itzgeek_cluster

WARNINGS:
No stonith devices and stonith-enabled is not false

Stack: corosync
Current DC: node2.itzgeek.local (version 1.1.19-8.el7_6.4-c3c624ea3d) - partition with quorum
Last updated: Fri Jul  5 09:15:37 2019
Last change: Fri Jul  5 09:13:12 2019 by hacluster via crmd on node2.itzgeek.local

2 nodes configured
0 resources configured

Online: [ node1.itzgeek.local node2.itzgeek.local ]

No resources


Daemon Status:
  corosync: active/enabled
  pacemaker: active/enabled
  pcsd: active/enabled

Fencing Devices

The fencing device is a hardware/software device which helps to disconnect the problem node by resetting node / disconnecting shared storage from accessing it. My demo cluster is running on top of VMware Virtual machine, so I am not showing you a fencing device setup, but you can follow this guide to set up a fencing device.

Cluster Resources

Prepare resources

Apache Web Server

Install Apache web server on both nodes.

# yum install -y httpd wget

Edit the configuration file.

# vi /etc/httpd/conf/httpd.conf

Add below content at the end of file on both cluster nodes.

<Location /server-status>
  SetHandler server-status
  Order deny,allow
  Deny from all
  Allow from 127.0.0.1
</Location>

Now we need to use shared storage for storing the web content (HTML) file. Perform below operation in any one of the nodes.

[root@node2 ~]# mount /dev/vg_apache/lv_apache /var/www/

[root@node2 ~]# mkdir /var/www/html

[root@node2 ~]# mkdir /var/www/cgi-bin

[root@node2 ~]# mkdir /var/www/error

[root@node2 ~]# restorecon -R /var/www

[root@node2 ~]# cat <<-END >/var/www/html/index.html
<html>
<body>Hello, Welcome!. This Page Is Served By Red Hat Hight Availability Cluster</body>
</html>
END

[root@node2 ~]# umount /var/www

Allow Apache service in the firewall on both nodes.

# firewall-cmd --permanent --add-service=http

# firewall-cmd --reload

Create Resources

Create a filesystem resource for Apache server. Use the storage coming from the iSCSI server.

# pcs resource create httpd_fs Filesystem device="/dev/mapper/vg_apache-lv_apache" directory="/var/www" fstype="ext4" --group apache

Output:

Assumed agent name 'ocf:heartbeat:Filesystem' (deduced from 'Filesystem')

Create an IP address resource. This IP address will act a virtual IP address for the Apache and clients will use this ip address for accessing the web content instead of individual node’s ip.

# pcs resource create httpd_vip IPaddr2 ip=192.168.1.100 cidr_netmask=24 --group apache

Output:

Assumed agent name 'ocf:heartbeat:IPaddr2' (deduced from 'IPaddr2')

Create an Apache resource which will monitor the status of the Apache server and move the resource to another node in case of any failure.

# pcs resource create httpd_ser apache configfile="/etc/httpd/conf/httpd.conf" statusurl="http://127.0.0.1/server-status" --group apache

Output:

Assumed agent name 'ocf:heartbeat:apache' (deduced from 'apache')

Since we are not using fencing, disable it (STONITH). You must disable to start the cluster resources, but disabling STONITH in the production environment is not recommended.

# pcs property set stonith-enabled=false

Check the status of the cluster.

[root@node1 ~]# pcs status

Output:

Cluster name: itzgeek_cluster
Stack: corosync
Current DC: node2.itzgeek.local (version 1.1.19-8.el7_6.4-c3c624ea3d) - partition with quorum
Last updated: Fri Jul  5 09:26:04 2019
Last change: Fri Jul  5 09:25:58 2019 by root via cibadmin on node1.itzgeek.local

2 nodes configured
3 resources configured

Online: [ node1.itzgeek.local node2.itzgeek.local ]

Full list of resources:

 Resource Group: apache
     httpd_fs   (ocf::heartbeat:Filesystem):    Started node1.itzgeek.local
     httpd_vip  (ocf::heartbeat:IPaddr2):       Started node1.itzgeek.local
     httpd_ser  (ocf::heartbeat:apache):        Started node1.itzgeek.local

Daemon Status:
  corosync: active/enabled
  pacemaker: active/enabled
  pcsd: active/enabled

Verify High Availability Cluster

Once the cluster is up and running, point a web browser to the Apache virtual IP address. You should get a web page like below.

Configure High-Availability Cluster on CentOS 7 – Apache Web Server

Test High Availability Cluster

Let’s check the failover of resource of the node by stopping the cluster on the active node.

[root@node1 ~]# pcs cluster stop node1.itzgeek.local

Conclusion

That’s All. In this post, you have learned how to setup a High-Availability cluster on CentOS 7. Please let us know your thoughts in the comment section.

aapachecentos 7clusterrhel 7
Comments (30)
Add Comment
  • TECHNO SEO

    when i run the format command on node1 its showing /dev/sdb: Read-only file system while setting up superblock

    • Raj

      There seems an issue with created target, just follow the tutorial steps properly

        • Prabodh

          instead of “set attribute generate_node_acls=1” use “set attribute generate_node_acls=0”.

          I faced same problem but resolved after some r&d.

          Try and let me know if it works for you.

          • Bruce Malaudzi

            Dear Author and readers
            I would like to kindly assist. Readers are facing error messages when executing # mkfs.ext4 /dev/sdb. This is caused by one critical step, that was no mentioned in this tutorial.

            Under the section “Configuring iSCSI shared storage”
            You cannot create a file system, directly from a block device
            For example, /dev/sdb is a block device. You need to partition the block device prior to create a file system. Once a partition is created, you have something like /dev/sdb1 or /dev/sdb2 and so on. From there, you can create a file system.
            # mkfs.ext4 /dev/sdb [will give your errors]
            # mkfs.ext4 /dev/sdb1 [will work only after you partition the disk]

            How do I partition a disk?
            The fdisk utility can be used.
            # fdisk /dev/sdb
            Here are some useful options within the fdisk utility:
            Press m for menu
            Press p to print current partition table
            Press n to create new partition
            Press d to delete a partition
            Press w to write changes.
            Press q to quit the utility and redirected back to the normal terminal shell.

            Use +size in G or M to allocate size. For example, +10G will allocate a 10gb disk size when creating a partition.

            Whats next after creating a partition?
            Before creating filesystem to the /dev/sdb1 partition, inform the kernel of new changes to the partition table.
            # partprobe /dev/sdb
            The above command will force the kernel to re-read the partition table on block device /dev/sdb

            Now you can create your filesystem
            # mkfs.ext4 /dev/sdb1
            Thats all !!!
            You can also use the cfdisk utility instead of fdisk. The cfdisk utility is more user friendly.
            # cfdisk /dev/sdb

            This video can be useful too: https://youtu.be/bDnIfX7zVY0
            It demonstrates installing and configuring iSCSI in CentOS/RHEL-7, from scratch

            I love the whole tutorial presented here and really appreciate for sharing. I’m looking forward to be included in future tutorials, I’m interested in Red Hat/ CentOS 7. I love sharing ideas and knowledge.

          • William Fahham

            Hi!!

            I had a problem with creation the partition, I´m use cfdisk and show to me:

            Opened disk read-only – you have no permission to write.

          • Bruce Malaudzi

            You must switch to root user

          • William Fahham

            I´m with root, only worked when one node is shutdown.

          • Jobin Joseph

            You can create filesystem on a block device. No issues with it.

          • Bruce Malaudzi

            Yes you are right. I have just tested it and its working.

  • Box Office Buz

    Would it be possible to put a WHM / Cpanel on the iSCSI Storage ?

  • ITzGeek Web

    Try to have latest package installed on your server, or update your system with latest packages.

  • Raj Mohd

    I have created the MQ cluster in VM, but i need to place the scripts where if one node go down the other will take the Q manger. but i am unable to do because i am not getting the correct path to place the scripts. Please help on this

  • ritu rajawat

    how to download pcs and other packages. if not available on system

    • ITzGeek Web

      Which one you are using

      Rhel or centos

      • ritu rajawat

        Rhel 7

        • ITzGeek Web

          Make sure you have subscribed to below channels.

          rhel-ha-for-rhel-7-server-rpms

          And

          rhel-rs-for-rhel-7-server-rpms

          • ritu rajawat

            can you please elaborate it, i can’t get it properly and i didn’t found the above two channels so please provide me the link

          • ITzGeek Web

            If you don’t have subscriptions, configure CentOS 7 Repository so that you can get this packages from CentOS repo instead of rhel 7. Red hat support team will not support your server if you use CentOS packages in rhel machines

  • William Fahham

    I Had this error :

    Resource Group: apache
    httpd_fs (ocf::heartbeat:Filesystem): Stopped
    httpd_vip (ocf::heartbeat:IPaddr2): Stopped
    httpd_ser (ocf::heartbeat:apache): Stopped

    Failed Actions:
    * httpd_fs_start_0 on node1.fahham.corp ‘not installed’ (5): call=14, status=complete, exitreason=’Couldn’t find device [/dev/mapper/vg_apache-lv_apache]. Expected /dev/??? to exist’,
    last-rc-change=’Mon Aug 21 13:39:26 2017′, queued=0ms, exec=80ms
    * httpd_fs_start_0 on node2.fahham.corp ‘not installed’ (5): call=14, status=complete, exitreason=’Couldn’t find device [/dev/mapper/vg_apache-lv_apache]. Expected /dev/??? to exist’,
    last-rc-change=’Mon Aug 21 13:27:26 2017′, queued=0ms, exec=34ms

    Help Me!

    • ITzGeek Web

      Hi,

      LVM missing that’s the reason you got error.

      Article has been updated with LVM creation on node 1, then after on all your remaining; you just have to scan it

  • William Fahham

    Really the device [/dev/mapper/vg_apache-lv_apache]not exist,
    I need crete this at the node1 and node2 or at the server scsi ?

    • ITzGeek Web

      Hi,

      Article has been updated with LVM creation on node 1, then after on all your remaining; you just have to scan it

  • Utterkar Chinnajee Rao

    Hi GM All

      • Linux_byhrt

        Hi ITzGeek can you make same tutorial for HA on RHEL for Postgresql. How to configure postgresssql service for HA on RHEL7/Centos 7

  • Yan Aung Myo

    Hi, I was able to set up the apache HA successfully but found out the error that after I restart all three nodes all together and iscsi LVM for cluster nodes are missing and unable to remount back at all although iscsi disks are still showing (no error) at Storage Node.