Containerized High Availability: Deploying Keepalived with Docker for Virtual IP Failover

Retrieve the official Keepalived container image from Docker Hub:

docker pull osixia/keepalived:latest

Deploy the primary (Master) instance using host networking mode to allow VRRP advertisement packets to traverse network boundaries:

docker run -d \
  --name keepalived-primary \
  --net=host \
  --privileged \
  --restart unless-stopped \
  -v /etc/localtime:/etc/localtime:ro \
  -e HA_ROLE="MASTER" \
  -e VRRP_PRIORITY="200" \
  -e BIND_INTERFACE="eth0" \
  -e PEER_NODES="#PYTHON2BASH:['10.0.0.2', '10.0.0.3']" \
  -e VIRTUAL_IPS="10.0.0.100" \
  osixia/keepalived \
  --loglevel debug

Deploy secondary (Backup) instances on additional nodes. Ensure the priority value remains lower than the primary to enable automatic failover:

docker run -d \
  --name keepalived-secondary \
  --net=host \
  --privileged \
  --restart unless-stopped \
  -v /etc/localtime:/etc/localtime:ro \
  -e HA_ROLE="BACKUP" \
  -e VRRP_PRIORITY="100" \
  -e BIND_INTERFACE="eth0" \
  -e PEER_NODES="#PYTHON2BASH:['10.0.0.1', '10.0.0.3']" \
  -e VIRTUAL_IPS="10.0.0.100" \
  osixia/keepalived \
  --loglevel debug

Critical requirement: Assign unique priority values to each node. Identical priorities prevent automatic state transitions and cause connection drops during failover events in containerized environments.

Verify the host network interface matches the BIND_INTERFACE parameter before deployment:

ip link show
# or
ip addr show eth0

Confirm the Virtual IP (VIP) is not currently assigned to any interface in the subnet to avoid address conflicts. If reassigning the VIP, remove and recreate the container rather than attempting hot-swaps.

Validate the container is operational:

docker ps --filter "name=keepalived" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

Inspect network interfaces to verify the VIP attachment on the active Master node:

ip addr show eth0 | grep "10.0.0.100"

Review runtime logs for state transitions or error conditions:

docker logs -f keepalived-primary

Troubleshooting IPVS Protocol Errors

If logs display IPVS: Can't initialize ipvs: Protocol not available, the kernel lacks required load balancer modules.

Check currently loaded modules:

lsmod | grep -E "ip_vs|nf_conntrack"

Manually load the necessary kernel modules:

modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh

Enable persistence across reboots:

echo "ip_vs" >> /etc/modules-load.d/keepalived.conf
echo "ip_vs_rr" >> /etc/modules-load.d/keepalived.conf
systemctl restart systemd-modules-load

Verify successful module loading:

lsmod | grep ip_vs

Custom Configuration Management

The container stores default configurations at /container/service/keepalived/assets/. For production environments, mount a custom configuration file from the host:

docker run -d \
  --name keepalived-custom \
  --net=host \
  --privileged \
  -v /opt/keepalived/keepalived.conf:/container/service/keepalived/assets/keepalived.conf:ro \
  -v /opt/keepalived/check_scripts:/usr/local/bin:ro \
  osixia/keepalived \
  --copy-service \
  --loglevel debug

Important: Set configuration file permissions to 644 (rw-r--r--) before mounting. Incorrect permissions prevent the Keepalived process from reading the configuration inside the container.

Example configuration with health checks:

global_defs {
    router_id LVS_HA_1
    default_interface eth0
    script_user root
    enable_script_security
}

vrrp_script backend_health {
    script "/usr/local/bin/health_check.sh"
    interval 3
    weight -30
    fall 2
    rise 1
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 60
    priority 150
    advert_int 1
    nopreempt
    
    unicast_peer {
        10.0.0.2
        10.0.0.3
    }
    
    virtual_ipaddress {
        10.0.0.100/24 dev eth0 label eth0:vip
    }
    
    authentication {
        auth_type PASS
        auth_pass SecurePass123
    }
    
    track_script {
        backend_health
    }
    
    notify_master "/container/service/keepalived/assets/notify.sh"
    notify_backup "/container/service/keepalived/assets/notify.sh"
    notify_fault "/container/service/keepalived/assets/notify.sh"
}

When using custom scripts for service health monitoring, ensure the scripts exit with code 0 for healthy states and non-zero for failures. The weight parameter adjusts priority dynamically based on script results, triggering failover when thresholds are exceeded.

Tags: docker Keepalived High Availability VRRP Virtual IP

Posted on Tue, 27 Oct 2026 16:05:59 +0000 by DyslexicDog