Skip to main content
RunBook Academy

LinuxLVI · Keepalived and VRRPKeepalived config

Keepalived configuration - the Linux VRRP implementation

Intermediate⏱ ~10 minkeepalived

What you'll learn

  • Configure keepalived for VRRP
  • Set priorities and preemption
  • Use notify scripts for failover actions
  • Test failover
  • Allocate a unique VRID per L2 segment and prevent VRRP split brain

Prerequisites

Verified against Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL 9.x · Rocky Linux 9.x · AlmaLinux 9.x · Linux kernel 6.1 LTS / 6.6 LTS · systemd 255+ · OpenSSH 8.7p1 (RHEL 9) / 9.6p1 (Ubuntu 24.04) · nftables 1.0.x · chrony 4.x · Pacemaker 2.1.x · Corosync 3.1.x · 2026-08-09

Not yet marked complete on this device.

Keepalived is the Linux implementation of VRRP. This lesson covers the configuration for production use.

Install

sudo apt install keepalived

Basic configuration

A VRRP group is always at least two files, one per peer. Write both. The only differences are priority and the unicast addresses.

# host1 (lb-01) - /etc/keepalived/keepalived.conf
vrrp_script check_service {
    script "/usr/bin/curl -sf http://localhost/health"
    interval 2
    weight -60
    fall 3
    rise 2
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 150
    advert_int 1
    unicast_src_ip 10.0.0.11
    unicast_peer {
        10.0.0.12
    }
    authentication {
        auth_type PASS
        auth_pass mysecret
    }
    virtual_ipaddress {
        10.0.0.100/24
    }
    track_script {
        check_service
    }
    notify_master "/usr/local/bin/keepalived-master.sh"
    notify_backup "/usr/local/bin/keepalived-backup.sh"
    notify_fault "/usr/local/bin/keepalived-fault.sh"
}
# host2 (lb-02) - /etc/keepalived/keepalived.conf
# Identical apart from priority and the unicast addresses.
vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    unicast_src_ip 10.0.0.12
    unicast_peer {
        10.0.0.11
    }
    ...
}

Both peers start as BACKUP. The election gives the VIP to the higher priority, so lb-01 becomes master within one advert_int. Declaring state MASTER buys nothing and costs a VIP move on every keepalived start, because a MASTER-declared instance claims the VIP immediately instead of listening for an existing master first.

Key parameters

  • state: the initial state only, not the running role. Set BACKUP on both peers and let priority decide. MASTER means “claim the VIP at startup without listening first”.
  • interface: the network interface for the VIP.
  • virtual_router_id: 1-255. Must match between peers in the same group, and must be unique among every VRRP group sharing an L2 segment. The VRID selects the virtual MAC 00:00:5e:00:01:<vrid>, so two unrelated groups both using 51 on one VLAN fight over the same MAC and both VIPs become intermittently unreachable. Record VRID allocations centrally, the same way you record VLAN IDs.
  • priority: 1-255. Higher wins. Default 100.
  • advert_int: how often the master advertises, in seconds. This is the setting that sets your failover time, and it is not the failover time itself. A backup declares the master down after the master-down interval — three missed advertisements plus a skew derived from priority — so advert_int 1 costs roughly 3.6 seconds of VIP outage, not the “sub-second” figure keepalived summaries like to quote. Sub-second failover needs a sub-second value (advert_int 0.5 gives about 1.8s), which buys speed at the price of flapping the VIP on transient packet loss. Whichever you pick, measure the real number across a controlled failover and record it as the component’s RTO.
  • virtual_ipaddress: the VIP(s) to manage.
  • track_script: a script whose exit status gates the instance. weight defaults to 0, and weight 0 does not mean “no adjustment” — it means the instance transitions to FAULT after fall consecutive failures and gives up the VIP outright. There is no -2 default. Set a non-zero weight (e.g. weight -60 above) when you want a priority adjustment instead, sized so master_priority + weight < backup_priority.

Authentication

VRRPv2 has no authentication by default (security flaw). Always use authentication:

authentication {
    auth_type PASS
    auth_pass <strong-password>
}

Or use VRRPv3 with IPsec.

Preemption

By default, when the original master returns, it takes back the VIP. That is a second, avoidable outage during a recovery. Disable it with nopreempt:

vrrp_instance VI_1 {
    state BACKUP      # required for nopreempt to do anything
    priority 150
    nopreempt
    ...
}

nopreempt is only honoured when the instance’s initial state is BACKUP. Declaring state MASTER and adding nopreempt is a silent no-op: keepalived ignores it and the instance preempts anyway.

Notify scripts

Run a script on state change:

#!/bin/bash
# /usr/local/bin/keepalived-master.sh
echo "Became MASTER at $(date)" >> /var/log/keepalived.log
# Update DNS, run health checks, etc.

The script runs in the background; keepalived does not wait for it.

Health checks

Use a script to monitor the service and trigger failover:

vrrp_script check_service {
    script "/usr/bin/curl -sf http://localhost/health"
    interval 2
    weight -60
    fall 3
    rise 2
}

If the script fails 3 times in a row (fall), the effective priority drops by 60: 150 becomes 90, the backup at 100 now has the higher effective priority, and it takes over. After 2 consecutive successes (rise) the penalty is removed.

Omit weight and you get the default of 0, which is a different mechanism entirely - FAULT state and an unconditional VIP release. Choose deliberately.

VRRP split brain

Keepalived has no fencing. It cannot verify that the other peer has stopped; it only infers state from advertisements. If those advertisements stop arriving while both hosts are alive, both declare themselves MASTER, both raise 10.0.0.100, and the LAN has a duplicate IP with flapping ARP.

Three ways advertisements go missing:

  • A host firewall that does not permit IP protocol 112. This is the common one, because the security baseline is applied after keepalived was proven working.
  • Switch multicast filtering or IGMP snooping dropping the 224.0.0.18 group.
  • A genuine network partition between the peers.

Detect it. Both peers logging a MASTER transition at once is the signature:

# Run on BOTH peers and compare timestamps
journalctl -u keepalived --since -1h | grep -i 'Entering MASTER'

# Duplicate address detection from a third host on the segment
arping -D -I eth0 -c 3 10.0.0.100

Prevent it two ways. First, permit protocol 112 between the peers before you enable the firewall:

# nftables
sudo nft add rule inet filter input ip protocol 112 ip saddr 10.0.0.0/24 accept

Second, stop depending on multicast at all. Unicast VRRP sends advertisements directly to the named peers, which works in cloud VPCs and multicast-hostile switching:

vrrp_instance VI_1 {
    unicast_src_ip 10.0.0.11
    unicast_peer {
        10.0.0.12
    }
}

Test failover

# Check current state
ip addr show eth0 | grep 10.0.0.100

# Stop the keepalived on the master
sudo systemctl stop keepalived

# Verify the backup took over
ssh backup "ip addr show eth0 | grep 10.0.0.100"

The VIP should now be on the backup.

Knowledge check

Knowledge check · 5 questions

  1. Q1. You want lb-01 to hold the VIP normally and to keep it after lb-02 has taken over during an incident. How should the two configs be written?

  2. Q2. VRRP without authentication is acceptable for production.

  3. Q3. Which of the following are valid keepalived features? Select all that apply.

  4. Q4. A vrrp_script is defined with no weight line. The health endpoint returns 500 for six seconds during a restart, then recovers. What happens to the VIP?

  5. Q5. After applying the nftables baseline, both lb-01 and lb-02 log "Entering MASTER STATE" within the same second and clients report intermittent resets. What is the most likely cause?

Passing score: 75%. Answers are checked in this browser.