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:
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:
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.