Health-check scripts driven by the Patroni API

Keepalived is steered by short shell scripts that query the local Patroni REST API on http://127.0.0.1:8008 and exit non-zero when the node does not hold the expected role. The leader check reads .role from the /patroni endpoint and exits 0 only when it equals leader:

PATRONI_API_URL="http://127.0.0.1:8008"
role=$(curl -s $PATRONI_API_URL/patroni | jq -r .role)
if [ "$role" == "leader" ]; then exit 0; else exit 1; fi

A second script applies the same pattern for the replica role, exiting 0 on replica and 1 otherwise. Both are placed under /etc/keepalived/scripts/ (check_leader.sh, check_replica.sh).

Registering the checks with keepalived

Each script is wrapped in a vrrp_script block in /etc/keepalived/keepalived.conf, with identical timing: a 5-second interval, a 3-second timeout, and 2 failures or successes required to move the state:

  • check_leader — points at /etc/keepalived/scripts/check_leader.sh
  • check_replica — points at /etc/keepalived/scripts/check_replica.sh

Two VRRP instances, two virtual addresses

The configuration defines separate instances for the leader and replica roles, both starting in state BACKUP on eth0 with priority 100 and a 1-second advertisement interval, and both using PASS authentication.

  • VI_1 carries the leader VIP 192.168.1.10 (virtual_router_id 51) and tracks check_leader; its notify hooks are notify_master.sh, notify_backup.sh and notify_fault.sh.
  • VI_2 carries the replica VIP 192.168.1.20 (virtual_router_id 52) and tracks check_replica; its hooks are notify_replica_master.sh, notify_replica_backup.sh and notify_replica_fault.sh.

Notify hooks

The notify scripts bound to each instance can be as small as a logging call, or extended to send a message elsewhere — for example a curl to a Slack channel:

#!/bin/bash
echo "VIP switched to leader" | logger