Configure network load balancing with keepalived and VRRP for high availability failover

Intermediate 25 min Apr 03, 2026 18 views
Ubuntu 24.04 Ubuntu 22.04 Debian 12 AlmaLinux 9 Rocky Linux 9 Fedora 41

Set up keepalived with VRRP to create highly available network services with automatic failover. Configure virtual IP addresses that move between servers when one fails, ensuring zero-downtime load balancing.

Prerequisites

  • Two or more Linux servers with network connectivity
  • Root or sudo access on all nodes
  • Basic understanding of IP networking
  • Network interface names (ens3, eth0, etc.)

What this solves

Keepalived uses VRRP (Virtual Router Redundancy Protocol) to create high-availability network services by sharing virtual IP addresses between multiple servers. When the primary server fails, the backup automatically takes over the virtual IP, ensuring continuous service availability without manual intervention. This tutorial sets up two-node keepalived clusters with health checks and automatic failover for production load balancing.

Step-by-step installation

Update system packages

Start by updating your package manager to ensure you get the latest versions of keepalived and dependencies.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Install keepalived

Install keepalived package which includes VRRP support and health checking capabilities.

sudo apt install -y keepalived ipvsadm
sudo dnf install -y keepalived ipvsadm

Enable IP forwarding

Enable IP forwarding in the kernel to allow the system to route traffic between interfaces and handle virtual IP addresses.

echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
echo 'net.ipv4.ip_nonlocal_bind = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Configure primary server keepalived

Create the keepalived configuration for the primary server. This server will have higher priority and own the virtual IP by default.

global_defs {
    router_id LB_PRIMARY
    enable_script_security
    script_user root
}

vrrp_script chk_nginx {
    script "/bin/curl -f http://localhost:80 || exit 1"
    interval 2
    weight -2
    fall 3
    rise 2
}

vrrp_instance VI_1 {
    state MASTER
    interface ens3
    virtual_router_id 51
    priority 110
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass changeme123
    }
    virtual_ipaddress {
        203.0.113.10/24
    }
    track_script {
        chk_nginx
    }
    notify_master "/etc/keepalived/master.sh"
    notify_backup "/etc/keepalived/backup.sh"
    notify_fault "/etc/keepalived/fault.sh"
}

Configure backup server keepalived

Create the keepalived configuration for the backup server with lower priority. Replace the interface name and adjust IP addresses for your network.

global_defs {
    router_id LB_BACKUP
    enable_script_security
    script_user root
}

vrrp_script chk_nginx {
    script "/bin/curl -f http://localhost:80 || exit 1"
    interval 2
    weight -2
    fall 3
    rise 2
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens3
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass changeme123
    }
    virtual_ipaddress {
        203.0.113.10/24
    }
    track_script {
        chk_nginx
    }
    notify_master "/etc/keepalived/master.sh"
    notify_backup "/etc/keepalived/backup.sh"
    notify_fault "/etc/keepalived/fault.sh"
}

Create notification scripts

Create scripts that run when VRRP state changes occur. These scripts can update DNS, send alerts, or perform custom actions during failover.

#!/bin/bash
echo "$(date): Becoming MASTER" >> /var/log/keepalived-state.log

Add custom actions when becoming master

Example: systemctl start nginx

Example: curl -X POST https://monitoring.example.com/webhook

sudo chmod 755 /etc/keepalived/master.sh

Create backup and fault scripts

Create additional notification scripts for backup and fault states to provide complete state tracking.

#!/bin/bash
echo "$(date): Becoming BACKUP" >> /var/log/keepalived-state.log

Add custom actions when becoming backup

Example: systemctl stop nginx

#!/bin/bash
echo "$(date): Entering FAULT state" >> /var/log/keepalived-state.log

Add custom actions when entering fault state

Example: send alert email

sudo chmod 755 /etc/keepalived/backup.sh
sudo chmod 755 /etc/keepalived/fault.sh

Configure firewall rules

Open the necessary firewall ports for VRRP communication. VRRP uses IP protocol 112 for heartbeat messages between nodes.

sudo ufw allow in on ens3 to 224.0.0.18
sudo ufw allow in on ens3 proto vrrp
sudo ufw reload
sudo firewall-cmd --permanent --add-protocol=vrrp
sudo firewall-cmd --permanent --add-rich-rule="rule family='ipv4' destination address='224.0.0.18' accept"
sudo firewall-cmd --reload

Install and configure NGINX for testing

Install a web server on both nodes to test the health checks and load balancing functionality.

sudo apt install -y nginx
echo "

$(hostname) - Primary Server

" | sudo tee /var/www/html/index.html sudo systemctl enable --now nginx
sudo dnf install -y nginx
echo "

$(hostname) - Primary Server

" | sudo tee /usr/share/nginx/html/index.html sudo systemctl enable --now nginx

Start keepalived services

Enable and start keepalived on both servers. The primary server should claim the virtual IP address within a few seconds.

sudo systemctl enable --now keepalived
sudo systemctl status keepalived

Configure advanced health checks

Create a more comprehensive health check script that monitors multiple services and system resources.

#!/bin/bash

Check HTTP response

if ! curl -f -s http://localhost:80 > /dev/null; then echo "HTTP check failed" exit 1 fi

Check system load

load=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | tr -d ',') if (( $(echo "$load > 10.0" | bc -l) )); then echo "System load too high: $load" exit 1 fi

Check memory usage

mem_usage=$(free | grep Mem | awk '{printf("%.1f", $3/$2 * 100.0)}') if (( $(echo "$mem_usage > 90.0" | bc -l) )); then echo "Memory usage too high: $mem_usage%" exit 1 fi echo "All health checks passed" exit 0
sudo chmod 755 /etc/keepalived/check_services.sh

Update configuration with advanced checks

Modify the keepalived configuration to use the comprehensive health check script instead of the simple curl command.

vrrp_script chk_services {
    script "/etc/keepalived/check_services.sh"
    interval 5
    weight -10
    fall 2
    rise 2
    timeout 3
}
sudo systemctl restart keepalived

Configure multiple virtual IPs

Add secondary VRRP instance

Configure a second VRRP instance with different virtual IP and router ID for additional services or load distribution.

vrrp_instance VI_2 {
    state MASTER
    interface ens3
    virtual_router_id 52
    priority 110
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass changeme456
    }
    virtual_ipaddress {
        203.0.113.11/24
    }
    track_script {
        chk_services
    }
}

Configure VRRP with load balancer backend

Add virtual server configuration

Configure keepalived to act as a load balancer with real servers for distributing traffic beyond simple IP failover.

virtual_server 203.0.113.10 80 {
    delay_loop 6
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP

    real_server 192.168.1.10 80 {
        weight 1
        HTTP_GET {
            url {
                path /health
                status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }

    real_server 192.168.1.11 80 {
        weight 1
        HTTP_GET {
            url {
                path /health
                status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }
}

Verify your setup

# Check keepalived status
sudo systemctl status keepalived

View virtual IP assignments

ip addr show

Check VRRP state

sudo journalctl -u keepalived -f

Test virtual IP connectivity

ping -c 3 203.0.113.10 curl http://203.0.113.10

View keepalived statistics

sudo ipvsadm -ln

Check notification script logs

sudo tail -f /var/log/keepalived-state.log
Note: The virtual IP should only appear on the master node. Use ip addr show on both servers to verify which node currently owns the VIP.

Test automatic failover

Simulate primary server failure

Test the failover mechanism by stopping services or disconnecting the primary server to verify automatic VIP migration.

# Stop keepalived on primary to trigger failover
sudo systemctl stop keepalived

Or stop the monitored service

sudo systemctl stop nginx

Watch failover in logs on backup server

sudo journalctl -u keepalived -f

Monitor failover timing

Use these commands to monitor how quickly failover occurs and verify the backup server assumes the virtual IP.

# Monitor VIP changes
watch -n 1 'ip addr show | grep 203.0.113.10'

Test connectivity during failover

while true; do curl -m 2 http://203.0.113.10 && sleep 1; done

Check VRRP advertisements

sudo tcpdump -i ens3 vrrp

Common issues

SymptomCauseFix
Both nodes claim masterVRRP traffic blocked by firewallOpen protocol 112 and multicast 224.0.0.18
Virtual IP not respondingNetwork interface mismatchVerify interface name matches in config
Constant failover flappingHealth check too aggressiveIncrease interval and fall/rise thresholds
Authentication errors in logsPassword mismatch between nodesEnsure auth_pass identical on both servers
Permission denied on scriptsNotification scripts not executablesudo chmod 755 /etc/keepalived/*.sh
VRRP process exitsInvalid router_id conflictUse unique virtual_router_id for each VRRP instance
Warning: Never use the same virtual_router_id on different VRRP instances in the same broadcast domain. This causes conflicts and unpredictable behavior.

Next steps

Automated install script

Run this to automate the entire setup

#keepalived #vrrp #high-availability #virtual-ip #failover

Need help?

Don't want to manage this yourself?

We handle infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.

Talk to an engineer