Keepalived provides two critical functions — Virtual Router Redundancy Protocol (VRRP) for IP failover and Linux Virtual Server (LVS) for load balancing — and it runs silently in the background. When the MASTER node loses its virtual IP without promoting a BACKUP, or when an LVS real server is removed from rotation without anyone noticing, the failure is often discovered by end users, not by operations.
This tutorial shows you how to build complete observability for Keepalived using Vigilmon: monitoring VRRP state transitions, virtual IP reachability, LVS real server health, and the Keepalived daemon itself.
Why Keepalived needs external monitoring
Keepalived is designed to be self-healing, which means failures can hide for a long time:
- VRRP split-brain — both nodes may believe they are MASTER if the VRRP multicast group becomes unavailable. Both nodes hold the virtual IP, causing ARP conflicts and packet loss.
- Silent BACKUP promotion failure — if the MASTER fails but the BACKUP doesn't promote (firewall blocking VRRP multicast, misconfigured priority), the virtual IP disappears entirely.
- LVS real server removal — Keepalived's health checks quietly remove real servers from the LVS pool when they fail. If all real servers fail, Keepalived may still be "healthy" while all traffic is dropped.
- Daemon crash on reload —
keepalived --reloadcan crash on config syntax errors, silently dropping VRRP instances. - Virtual IP not responding — the virtual IP can be held by the MASTER node but the service listening on it can be down.
Monitoring Keepalived means watching the virtual IP, the VRRP state, the LVS pool, and the daemon — not just whether the process is running.
What you'll need
- A Keepalived setup with at least one VRRP instance (MASTER + BACKUP nodes)
- Root or sudo access to run
keepalived_dbus,ipvsadm, orip addr - A free Vigilmon account
Step 1: Monitor the virtual IP from the outside
The most important thing to monitor is the virtual IP itself. Add an HTTP or TCP monitor in Vigilmon targeting the VIP directly:
For an HTTP service behind the VIP:
- Monitors → New Monitor → HTTP
- URL:
http://YOUR_VIRTUAL_IP/health(or the service's health endpoint) - Expected status:
200 - Check interval:
1 minute - Name:
Keepalived VIP — HTTP
For a TCP service (database, SMTP, etc.):
- Monitors → New Monitor → TCP Port
- Hostname:
YOUR_VIRTUAL_IP - Port:
5432(or your service port) - Name:
Keepalived VIP — TCP
This is your first line of defense. If the VIP stops responding, Vigilmon alerts regardless of what Keepalived thinks its state is.
Step 2: Monitor VRRP state on each node
On each Keepalived node, run a probe that checks the local VRRP state and pings a per-node heartbeat. This lets you detect state transitions (MASTER → BACKUP, or unexpected BACKUP → FAULT):
#!/bin/bash
# keepalived-vrrp-probe.sh
# Run on each node separately with separate heartbeat URLs
# Set this per-node:
# NODE_ROLE="master" on your expected MASTER
# NODE_ROLE="backup" on your expected BACKUP
NODE_ROLE="${KEEPALIVED_EXPECTED_ROLE:-master}"
MASTER_HEARTBEAT="https://vigilmon.online/api/heartbeat/YOUR_MASTER_HEARTBEAT"
BACKUP_HEARTBEAT="https://vigilmon.online/api/heartbeat/YOUR_BACKUP_HEARTBEAT"
LOG="/var/log/keepalived-probe.log"
# Check Keepalived is running
if ! systemctl is-active --quiet keepalived; then
echo "$(date): FAIL — keepalived not running" >> "$LOG"
exit 1
fi
# Detect current VRRP state by checking if the VIP is held locally
VIP="192.168.1.100" # replace with your virtual IP
if ip addr show | grep -q "$VIP"; then
current_state="MASTER"
else
current_state="BACKUP"
fi
echo "$(date): Node is $current_state (expected: $NODE_ROLE)" >> "$LOG"
# Ping the appropriate heartbeat based on current state
if [ "$current_state" = "MASTER" ]; then
curl -s "$MASTER_HEARTBEAT" --max-time 10 --retry 2
else
curl -s "$BACKUP_HEARTBEAT" --max-time 10 --retry 2
fi
Set up two heartbeats in Vigilmon:
Keepalived MASTER Node— interval 2 minutes, expects a ping from whichever node holds the VIPKeepalived BACKUP Node— interval 2 minutes, expects a ping from the non-VIP node
If both heartbeats stop (split-brain scenario where both nodes are confused), both alerts fire simultaneously.
Step 3: Monitor LVS real server pool health
If you use Keepalived for LVS load balancing, monitor the real server pool:
#!/bin/bash
# keepalived-lvs-probe.sh
HEARTBEAT_URL="https://vigilmon.online/api/heartbeat/YOUR_LVS_HEARTBEAT"
LOG="/var/log/keepalived-lvs-probe.log"
MIN_REAL_SERVERS=1 # alert if fewer than this many real servers are active
# Get active real server count from ipvsadm
active_count=$(ipvsadm -L -n 2>/dev/null | grep -c "->")
if [ "$active_count" -lt "$MIN_REAL_SERVERS" ]; then
echo "$(date): FAIL — only $active_count real servers active (min: $MIN_REAL_SERVERS)" >> "$LOG"
ipvsadm -L -n >> "$LOG"
exit 1
fi
echo "$(date): LVS pool healthy — $active_count real servers active" >> "$LOG"
curl -s "$HEARTBEAT_URL" --max-time 10 --retry 2
Add to crontab on the MASTER node:
*/2 * * * * /opt/scripts/keepalived-lvs-probe.sh
In Vigilmon:
- Monitors → New Monitor → Heartbeat
- Name:
Keepalived LVS Pool - Interval:
5 minutes
Step 4: Use Keepalived's notify scripts to push state changes
Keepalived supports notify scripts that run on VRRP state transitions. Use these to immediately notify Vigilmon when a failover occurs:
#!/bin/bash
# /etc/keepalived/notify.sh
# Called by Keepalived on state change: $1=GROUP|INSTANCE $2=name $3=MASTER|BACKUP|FAULT
INSTANCE="$2"
STATE="$3"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
# Log the transition
echo "$TIMESTAMP: $INSTANCE transitioned to $STATE" >> /var/log/keepalived-transitions.log
# Ping a state-specific heartbeat
case "$STATE" in
MASTER)
curl -s "https://vigilmon.online/api/heartbeat/YOUR_FAILOVER_HEARTBEAT" --max-time 10
;;
FAULT)
# Don't ping — Vigilmon will alert on missed heartbeat
# Optionally call an external webhook here
;;
BACKUP)
curl -s "https://vigilmon.online/api/heartbeat/YOUR_BACKUP_PROMOTION_HEARTBEAT" --max-time 10
;;
esac
Add to your Keepalived VRRP instance config (/etc/keepalived/keepalived.conf):
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
notify /etc/keepalived/notify.sh
virtual_ipaddress {
192.168.1.100
}
}
The notify script fires immediately on state change — you'll know about a failover within seconds.
Step 5: Monitor the Keepalived daemon and config reload
#!/bin/bash
# keepalived-daemon-check.sh
HEARTBEAT_URL="https://vigilmon.online/api/heartbeat/YOUR_DAEMON_HEARTBEAT"
if systemctl is-active --quiet keepalived; then
curl -s "$HEARTBEAT_URL" --max-time 10
fi
* * * * * /opt/scripts/keepalived-daemon-check.sh
In Vigilmon:
- Monitors → New Monitor → Heartbeat
- Name:
Keepalived Daemon - Interval:
2 minutes— daemon crashes should alert fast
Step 6: Configure alerting
Route Keepalived alerts appropriately by severity:
- Alert Channels → Add Channel → PagerDuty — for VIP down and FAULT state (production-impacting)
- Add Channel → Slack —
#infra-alertsfor all transitions including MASTER→BACKUP - Add Channel → Email — on-call engineer for daemon health
Set 0-minute escalation on the VIP HTTP/TCP monitor — if the VIP is unreachable, every second counts.
Step 7: Build a high-availability status page
- Status Pages → New Status Page
- Name:
HA Infrastructure - Add monitors: VIP HTTP, MASTER Node, BACKUP Node, LVS Pool, Daemon
- Set visibility to internal team
- Post the URL in
#infra
This gives on-call engineers an instant answer to "is it the VIP, the MASTER, or the pool?"
Complete monitoring reference
| Monitor | Type | What it catches | |---------|------|-----------------| | Keepalived VIP — HTTP | HTTP | VIP unreachable, service down | | Keepalived VIP — TCP | TCP | VIP unreachable at transport layer | | MASTER Node state | Heartbeat | VIP holder down, no-MASTER state | | BACKUP Node state | Heartbeat | BACKUP not promoting, split-brain | | LVS Pool | Heartbeat | All real servers removed from pool | | Keepalived Daemon | Heartbeat | Daemon crash, failed reload | | VRRP notify script | Heartbeat | Failover event detection |
Troubleshooting common failures
- VIP not responding but
ip addrshows it on MASTER — the service on the VIP is down. Checksystemctl status <service>andss -tlnp | grep <port>. - No node holds the VIP — check VRRP multicast is not blocked:
tcpdump -i eth0 vrrpshould show VRRP advertisements every second. If silent, check firewall rules for protocol 112. - Both nodes show VIP (split-brain) — check network connectivity between nodes on the VRRP interface. Both nodes lost contact and each promoted itself to MASTER. Restore connectivity; the lower-priority node will relinquish the VIP.
- LVS probe shows 0 active real servers — run
ipvsadm -L -nto see the pool state, then check the individual real server health check scripts in Keepalived config. keepalived --reloadsilently fails — test config withkeepalived --config-test -f /etc/keepalived/keepalived.confbefore reloading.
Next steps
- SSL monitoring — if the VIP serves HTTPS, add an SSL certificate expiry monitor in Vigilmon to catch cert issues before they become outages
- ARP monitoring — on critical failovers, verify gratuitous ARP propagation by checking MAC address tables on your switch; stale ARP caches can cause post-failover packet loss
Start monitoring your Keepalived HA infrastructure today at vigilmon.online — free, no credit card.