Large websites serve innumerable requests and must be able to concurrently respond to client requests and return the correct messages, images, video, application data e.t.c in time.
Load balancing can be defined as the distribution of traffic across a group of backend servers referred to as a server pool or server farm. A load balancer sits in between the application server and the client, to be able to route all the requests as well as fulfill the requests accordingly.
There are different load balancing algorithms, each providing a unique benefit. The choice of the algorithm depended on your needs:
- Round Robin – the requests are distributed across the server pool
- Least Connections – requests are sent to the server with the fewest current connections to clients
- Least Time – requests are directed to a server with the fastest response and least active connections
- Hash – requests are distributed based on the provided key such as IP address or URL
- IP Hash – the client’s IP address determines the server to receive the requests
- Random with Two Choices – two servers are selected randomly and requests sare ent to one ot them using the Least Connections algorithm
HAProxy an acronym for High Availability Proxy, is a free and open-source load balancer. It is able to balance incoming traffic from TCP and HTTP-based applications by distributing it across a server farm. This tool written in C language holds a reputation for high performance and efficiency.
There are several other features tied to HAProxy. These include:
- Simplified circuit breaking
- SSL/TLS termination.
- Layer 4 TCP and layer 7 HTTP load balancing.
- Proxy protocol support
- Scriptable multi-layer health checking
- Supports Lua and SPOE
- Supports gRPC
- Multithreading
- Multi-factor stickiness
- Supports API
With the above features, HAProxy finds use in several areas where high availability is required. There are a number of high-profile websites that use HAProxy, they include Reddit, GoDaddy, GitHub, Tumblr, Twitter, Tuenti, Bitbucket, OpsWorks(AWS), Speedtest.net e.t.c
Today, we will learn how to install and configure HAProxy on Rocky Linux 9.
Setup Requirements
For this guide to be a success, you need to meet the below requirements:
- At least 3 servers(one running HAProxy and two with the application)
- Memory -2GB and above
- Storage -20 GB and above
In my environment, the 3 servers have been configured as shown:
TASK | HOSTNAME | IP ADDRESS |
HAProxy | master.geeksforgeeks.org | 192.168.205.12 |
Backend01 | node1.geeksforgeeks.org | 192.168.205.2 |
Backend02 | node2.geeksforgeeks.org | 192.168.205.13 |
Set the hostnames as shown:
##HAProxy
sudo hostnamectl set-hostname master.geeksforgeeks.org
##Backend Node 01
sudo hostnamectl set-hostname node1.geeksforgeeks.org
##Backend Node 02
sudo hostnamectl set-hostname node2.geeksforgeeks.org
Add the hostnames to the /etc/hosts file on each server
$ sudo vim /etc/hosts
192.168.205.12 master.geeksforgeeks.org master
192.168.205.2 node1.geeksforgeeks.org node1
192.168.205.13 node2.geeksforgeeks.org node2
Step 1 – Install HAProxy on Rocky Linux 9
Once the environment has been set up, install HAProxy on the master node. Since HAProxy is provided in the default Rocky Linux 9 repositories, you can install it by executing the command:
sudo dnf install haproxy
Dependency Tree:
Dependencies resolved.
================================================================================
Package Architecture Version Repository Size
================================================================================
Installing:
haproxy x86_64 2.4.7-2.el9_0 appstream 2.1 M
Transaction Summary
================================================================================
Install 1 Package
Total download size: 2.1 M
Installed size: 6.5 M
Is this ok [y/N]: y
Step 2 – Configure HAProxy on Rocky Linux 9
Once the installation is complete, there are a few configurations you need to make to the /etc/haproxy/haproxy.cfg file. These configurations are:
- Global section– holds parameters to all servers running.
- default settings – has details that apply to all proxy subsections
- Frontend settings – defines the listening sockets from the client connection
- Backend settings – defines the server IP address and the load balancer algorithm
Take a backup of the config file:
sudo cp /etc/haproxy/haproxy.cfg{,.old}
Open the configuration file for editing:
sudo vim /etc/haproxy/haproxy.cfg
In the file, leave the global and default settings as they are and proceed to edit:
Frontend Settings:
This defines how the HAProxy server access the backend servers. Add the below lines to the section:
frontend main
bind *:80
default_backend rockylinux9_apps
option forwardfor
option http-server-close
As seen, we have defined the HAProxy server IP and port, as well as the backend servers providing the traffic
Backend Settings
Now in our backend settings, we need to define the backend servers and the load balancing algorithm to be applied.
backend rockylinux9_apps
balance roundrobin
server node1 node1.geeksforgeeks.org:80 check
server node2 node2.geeksforgeeks.org:80 check
We will implement the round-robin algorithm on the two nodes and also enable health checks.
Statistics settings(Optional)
This enables HAPRoxy to provide statistics on the usage. This includes the health, request rates and response times e.t.c
listen stats
bind 192.168.205.12:8088 # Bind stats to port 8088
log global # Enable Logging
stats enable # enable statistics reports
stats hide-version # Hide the version of HAProxy
stats refresh 30s # HAProxy refresh time
stats show-node # Shows the hostname of the node
stats auth admin:Passw0rd # Authentication for Stats page
stats uri /stats # Statistics URL
Save the configuration file and allows the ports through the firewall:
sudo firewall-cmd --add-port=8088/tcp --permanent
sudo firewall-cmd --add-port=80/tcp --permanent
sudo firewall-cmd --reload
Set SELinux in permissive mode:
sudo setenforce 0
sudo sed -i 's/SELINUX=enforcing/SELINUX=permissive/g' /etc/selinux/config
Verify if the configuration is okay:
$ haproxy -c -f /etc/haproxy/haproxy.cfg
Configuration file is valid
My configuration looks as shown without comments:
$ grep -v "^ *#" /etc/haproxy/haproxy.cfg | grep -v "^$"
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
stats socket /var/lib/haproxy/stats
ssl-default-bind-ciphers PROFILE=SYSTEM
ssl-default-server-ciphers PROFILE=SYSTEM
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
frontend main
bind *:80
acl url_static path_beg -i /static /images /javascript /stylesheets
acl url_static path_end -i .jpg .gif .png .css .js
default_backend rockylinux9_apps
option forwardfor
option http-server-close
backend rockylinux9_apps
balance roundrobin
server node1 node1.geeksforgeeks.org:80 check
server node2 node2.geeksforgeeks.org:80 check
listen stats
bind 192.168.205.12:8088 # Bind stats to port 8088
log global # Enable Logging
stats enable # enable statistics reports
stats hide-version # Hide the version of HAProxy
stats refresh 30s # HAProxy refresh time
stats show-node # Shows the hostname of the node
stats auth admin:Passw0rd! # Authentication for Stats page
stats uri /stats # Statistics URL
Configure HAProxy logging on Rocky Linux 9
To configure HAProxy logging, you need to edit the file below:
sudo vim /etc/rsyslog.conf
In the file, uncomment the lines:
# Provides UDP syslog reception
# for parameters see http://www.rsyslog.com/doc/imudp.html
module(load="imudp") # needs to be done just once
input(type="imudp" port="514")
Also, disable private authentication messages by adding the line:
# Don't log private authentication messages!
*.info;mail.none;authpriv.none;cron.none;local2.none /var/log/messages
local2.* /var/log/haproxy.log
Verify if the config file is okay:
$ rsyslogd -N1
rsyslogd: version 8.2102.0-101.el9_0.1, config validation run (level 1), master config /etc/rsyslog.conf
rsyslogd: End of config validation run. Bye.
Restart Rsyslog;
sudo systemctl restart rsyslog
Obtain logs at /var/log/haproxy.log;
sudo tail -f /var/log/haproxy.log
Now restart and enable the HAProxy service;
sudo systemctl restart haproxy
sudo systemctl enable haproxy
Verify if the service is running:
$ systemctl status haproxy
● haproxy.service - HAProxy Load Balancer
Loaded: loaded (/usr/lib/systemd/system/haproxy.service; enabled; vendor preset: disabled)
Active: active (running) since Fri 2022-07-29 10:56:44 CEST; 26s ago
Main PID: 31342 (haproxy)
Tasks: 2 (limit: 23441)
Memory: 4.1M
CPU: 22ms
CGroup: /system.slice/haproxy.service
├─31342 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
└─31345 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
Jul 29 10:56:43 master.geeksforgeeks.org systemd[1]: Starting HAProxy Load Balancer...
Jul 29 10:56:44 master.geeksforgeeks.org haproxy[31342]: [NOTICE] (31342) : New worker #1 (31345) forked
....
Step 3 – Configure HAProxy Backend Servers
The backend servers will be configured to run the application. We need to install the Apache web server on the backend servers.
sudo dnf install httpd -y
Once installed, start and enable the service:
sudo systemctl start httpd
sudo systemctl enable httpd
Enable port 80 through the firewall:
sudo firewall-cmd --add-port=80/tcp --permanent
sudo firewall-cmd --reload
Now create a sample HTML file on each of the servers;
Node1:
$ sudo vim /var/www/html/index.html
<h1>Voila! Welcome to Web Server 1</h1>
Restart the service;
sudo systemctl restart httpd
Node2:
$ sudo vim /var/www/html/index.html
<h1>Voila! Welcome to Web Server 2</h1>
Restart the service:
sudo systemctl restart httpd
Step 4 – Test HAProxy Load Balancer on Rocky Linux 9
Now we will test if the setup is working as desired with the round-robin algorithm. We should receive connections from both backend servers.
First access the page using the URL http://HAProxy-IP_Address or http://HAProxy-domain-name
Refresh the page and see if you will be able to receive the connection from the second server.
Check Statistics in HAProxy
Statistics can be viewed using the URL http://HAProxy-domain-name:8088/stats
Login using the set credentials and you will be authenticated to the dashboard below.
Here, you can see all the HAProxy statistics. When one node is down, all the traffic will be sent to the available node.
When all nodes are available, HAProxy automatically resumes traffic distribution using the set algorithm.
Step 5 – Secure HAProxy with TLS/SSL
HAProxy can be configured to use SSL/TLS to protect traffic from traveling across the unprotected wire(HTTP).
Generate the SSL/TL as preferred. Either using:
Let’s Encrypt
Install the required tools:
sudo dnf install epel-release
sudo dnf install certbot
Generate the certificates for the domain name:
sudo certbot certonly --standalone --preferred-challenges http -d example.com
Once generated, combine the certificate and private keys into a single file:
cd /etc/letsencrypt/live/example.com/
cat fullchain.pem privkey.pem | sudo tee haproxy.pem
Self-Signed Certificates
Alternatively, generate Self-signed certificates
sudo yum install openssl
Create a configuration file:
vim haproxy_ssl.conf
Add the lines below replacing them appropriately
[req]
default_bits = 2048
default_keyfile = haproxy_ssl.key
distinguished_name = req_distinguished_name
req_extensions = req_ext
x509_extensions = v3_ca
[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = KE
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Nairobi
localityName = Locality Name (eg, city)
localityName_default = Nairobi
organizationName = Organization Name (eg, company)
organizationName_default = Computingforgeeks
organizationalUnitName = organizationalunit
organizationalUnitName_default = Development
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = Your_IP-Address
commonName_max = 64
[req_ext]
subjectAltName = @alt_names
[v3_ca]
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
DNS.2 = Your_IP-Address
Generate self-signed certificates:
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout haproxy_ssl.key -out haproxy_ssl.crt -config haproxy_ssl.conf
Once generated, combine the certificates into one file and copy the certificates to the directory below:
sudo cat haproxy_ssl.crt haproxy_ssl.key > haproxy.pem
sudo cp haproxy.pem /etc/ssl/certs/haproxy.pem
Now add the certificates to your HAProxy config file:
sudo vim /etc/haproxy/haproxy.cfg
Add the HTTPS port and certificates file:
frontend main
bind *:80
bind *:443 ssl crt /etc/letsencrypt/live/example.com/haproxy.pem
For self-signed certificates, replace the path with /etc/ssl/certs/haproxy.pem. Save the file and restart HAProxy:
sudo systemctl restart haproxy
Allow the port through the firewall:
sudo firewall-cmd --add-port=443/tcp --permanent
sudo firewall-cmd --reload
Now access the HAPRoxy service using the URL https://HAProxy-domain-name
Closing Thoughts
At this point, am convinced that you can install and configure HAProxy on Rocky Linux 9. You should also be able to configure High availability Proxy for your application using the example captured in the guide. I hope this was significant.
See more: