How to Setup Highly Available NGINX with KeepAlived on CentOS 8

Nginx is a free, open-source and one of the most popular webserver around the world. It can also be used as a reverse proxy, load balancer and HTTP cache. The high availability allows an application to reroute work to another system in the event of failure. There are different technologies available to set up a highly available system.

Keepalived is a system daemon that monitors services or systems continusly and achieve high availability in the event of failure. If one node is down then the second node served the resources.

In this tutorial, I will show you how to set up a highly available Nginx web server with KeepAlived on CentOS 8.

Prerequisites

  • Two servers running CentOS 8 one for the master node and one for the backup node.
  • A root password is configured on your server.

Install Nginx on Both Nodes

First, you will need to install the Nginx package in both nodes. You can install it using the following command:

dnf install nginx -y

Once the Nginx has been installed on both nodes, start the Nginx service and enable it to start at system reboot:

systemctl start nginx
systemctl enable nginx

Once you are finished, you can proceed to the next step.

Create Index.html File on Both Nodes

Next, you will need to create a custom index.html file on both nodes to identify each node.

On the first node, create an index.html file with the following command:

echo "<h1>This is My First NGINX Web Server Node</h1>" | tee /usr/share/nginx/html/index.html

On the second node, create an index.html file with the following command:

echo "<h1>This is My Second NGINX Web Server Node</h1>" | tee /usr/share/nginx/html/index.html

Save and close the file when you are finished.

Install and Configure Keepalived

Next, you will need to install Keepalived on both nodes. By default, the Keepalived package is available in the CentOS 8 default repository. You can install it by running the following command:

dnf install keepalived -y

Once the keepalived package is installed on both nodes, you will need to edit the keepalived default configuration file on both nodes.

On the first node, edit the keepalived.conf file:

nano /etc/keepalived/keepalived.conf

Remove the default contents and add the following contents:

global_defs {
  # Keepalived process identifier
  router_id nginx
}

# Script to check whether Nginx is running or not
vrrp_script check_nginx {
  script "/bin/check_nginx.sh"
  interval 2
  weight 50
}

# Virtual interface - The priority specifies the order in which the assigned interface to take over in a failover
vrrp_instance VI_01 {
  state MASTER
  interface eth0
  virtual_router_id 151
  priority 110

  # The virtual ip address shared between the two NGINX Web Server which will float
  virtual_ipaddress {
    192.168.1.10/24
  }
  track_script {
    check_nginx
  }
  authentication {
    auth_type AH
    auth_pass secret
  }
}

Save and close the file when you are finished.

On the second node, edit the keepalived.conf file:

nano /etc/keepalived/keepalived.conf

Remove the default contents and add the following contents:

global_defs {
  # Keepalived process identifier
  router_id nginx
}

# Script to check whether Nginx is running or not
vrrp_script check_nginx {
  script "/bin/check_nginx.sh"
  interval 2
  weight 50
}

# Virtual interface - The priority specifies the order in which the assigned interface to take over in a failover
vrrp_instance VI_01 {
  state BACKUP
  interface eth0
  virtual_router_id 151
  priority 100

  # The virtual ip address shared between the two NGINX Web Server which will float
  virtual_ipaddress {
    192.168.1.10/24
  }
  track_script {
    check_nginx
  }
  authentication {
    auth_type AH
    auth_pass secret
  }
}

Save and close the file then you will need to create a script to check whether the Nginx service is running or not. You can create it using the following command:

Note: Just replaced MASTER with BACKUP and 110 with 100 in the above configuration file.

nano /bin/check_nginx.sh

Add the following lines:

#!/bin/sh
if [ -z "`pidof nginx`" ]; then
  exit 1
fi

Save and close the file then set proper permission with the following command:

chmod 755 /bin/check_nginx.sh

Finally, start keepalived service and enable it to start at system reboot using the following command:

systemctl start keepalived
systemctl enable keepalived

You can also check the status of keepalived service using the following command:

systemctl status keepalived

You should get the following output:

? keepalived.service - LVS and VRRP High Availability Monitor
   Loaded: loaded (/usr/lib/systemd/system/keepalived.service; disabled; vendor preset: disabled)
   Active: active (running) since Thu 2021-04-08 04:24:22 EDT; 5s ago
  Process: 3141 ExecStart=/usr/sbin/keepalived $KEEPALIVED_OPTIONS (code=exited, status=0/SUCCESS)
 Main PID: 3142 (keepalived)
    Tasks: 2 (limit: 12524)
   Memory: 2.1M
   CGroup: /system.slice/keepalived.service
           ??3142 /usr/sbin/keepalived -D
           ??3143 /usr/sbin/keepalived -D

Apr 08 04:24:22 node1 Keepalived_vrrp[3143]: (VI_01) Changing effective priority from 110 to 160
Apr 08 04:24:25 node1 Keepalived_vrrp[3143]: (VI_01) Receive advertisement timeout
Apr 08 04:24:25 node1 Keepalived_vrrp[3143]: (VI_01) Entering MASTER STATE
Apr 08 04:24:25 node1 Keepalived_vrrp[3143]: (VI_01) setting VIPs.
Apr 08 04:24:25 node1 Keepalived_vrrp[3143]: Sending gratuitous ARP on eth0 for 192.168.1.10
Apr 08 04:24:25 node1 Keepalived_vrrp[3143]: (VI_01) Sending/queueing gratuitous ARPs on eth0 for 192.168.1.10
Apr 08 04:24:25 node1 Keepalived_vrrp[3143]: Sending gratuitous ARP on eth0 for 192.168.1.10
Apr 08 04:24:25 node1 Keepalived_vrrp[3143]: Sending gratuitous ARP on eth0 for 192.168.1.10
Apr 08 04:24:25 node1 Keepalived_vrrp[3143]: Sending gratuitous ARP on eth0 for 192.168.1.10
Apr 08 04:24:25 node1 Keepalived_vrrp[3143]: Sending gratuitous ARP on eth0 for 192.168.1.10

You can also verify the virtual ip address status on the Master node using the following command:

ip add show

You should see the virtual IP address 192.168.1.10 in the following output:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:00:2d:3a:20:9b brd ff:ff:ff:ff:ff:ff
    inet 45.58.32.155/24 brd 45.58.32.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet 192.168.1.10/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::200:2dff:fe3a:209b/64 scope link 
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:00:0a:3a:20:9b brd ff:ff:ff:ff:ff:ff
    inet6 fe80::200:aff:fe3a:209b/64 scope link 
       valid_lft forever preferred_lft forever

Once you are finished, you can proceed to the next step.

Configure Firewall on Both Nodes

Next, you will need to allow port 80 and allow VRRP on both nodes. You can do it using the following command:

firewall-cmd --permanent --add-service=http
firewall-cmd --add-rich-rule='rule protocol value="vrrp" accept' --permanent

Next, reload the firewalld to apply the changes:

firewall-cmd –reload

Verify Keepalived

At this point, Nginx and Keepalived are installed and configured. It's time to test whether the Nginx high availability works or not.

Open your web browser and access the URL http://your-virtual-ip. You should see the following page:

Nginx page on node 1

Now, stop the Nginx service on the Master node and test whether the virtual IP is switched from Node 1 to Node 2.

On the Master node, stop the Nginx service using the following command:

systemctl stop nginx

Next, login to Node2 and verify the virtual IP using the following command:

ip add show

You should see your Virtual IP in the following output:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:00:2d:3a:26:37 brd ff:ff:ff:ff:ff:ff
    inet 45.58.38.55/24 brd 45.58.38.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet 192.168.1.10/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::200:2dff:fe3a:2637/64 scope link 
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:00:0a:3a:26:37 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::200:aff:fe3a:2637/64 scope link 
       valid_lft forever preferred_lft forever

Now, access your Nginx web server using the URL http://your-virtual-ip. You should see the Node2 page:

Nginx on node 2

Conclusion

Congratulations! you have successfully set up a highly available Nginx server with Keepalived. I hope you have now enough knowledge to set up highly a available Nginx server in a production environment.

Share this page:

2 Comment(s)