This episode teaches professional management of keepalived.conf: versioning with Git, automated deployment with Ansible and templates, validating changes before applying them, rollback strategies, and drift detection between nodes so configurations don't diverge.

The bigger the infrastructure, the more impossible it becomes to manage configuration with vim on every node. Episode 11 brings you professional practices: Keepalived configuration managed like code — versioned in Git, rendered from templates, validated before deploy, and deployed automatically and idempotently.
The big theme of this episode is drift control: making sure all nodes in one virtual router always talk with the same configuration. Two nodes with different configurations are a time bomb waiting for an incident. By the end of this episode, you'll have a configuration pipeline you can be held accountable for.
Store all Keepalived configuration in a single repository. A simple suggested structure:
keepalived-config/
├── inventory/hosts.yml
├── roles/keepalived/
│ ├── tasks/main.yml
│ ├── templates/keepalived.conf.j2
│ └── vars/main.yml
└── README.mdWith this structure, a single repository holds templates, per-environment variables, and change notes. No more configurations lost because they only live in someone's head.
Follow good versioning habits:
git init
git add .
git commit -m "feat: tambah instance VI_GW untuk VLAN backend"
git tag config-1.2.3The git commit -m "feat: ..." command records changes meaningfully. git tag marks a configuration version proven to work, making rollback to that version easy.
A Jinja template lets one config file be rendered for many nodes and environments. An example keepalived.conf.j2:
global_defs {
router_id {{ router_id }}
}
vrrp_instance VI_1 {
state {{ vrrp_state }}
interface {{ vrrp_interface }}
virtual_router_id {{ virtual_router_id }}
priority {{ vrrp_priority }}
virtual_ipaddress {
{{ virtual_ip }}/{{ virtual_prefix }} dev {{ vrrp_interface }}
}
}Variables like vrrp_state, vrrp_priority, and virtual_ip come from per-node host_vars. MASTER and BACKUP nodes can be rendered from the same template, only differing in variables.
An Ansible playbook for safely deploying configuration:
- name: Deploy konfigurasi keepalived
hosts: keepalived_nodes
tasks:
- name: Render template konfigurasi
ansible.builtin.template:
src: keepalived.conf.j2
dest: /etc/keepalived/keepalived.conf
owner: root
group: root
mode: "0600"
notify: validate dan reload
handlers:
- name: validate dan reload
ansible.builtin.command: keepalived -t -f /etc/keepalived/keepalived.conf
register: syntax_check
failed_when: syntax_check.rc != 0
- name: reload keepalived
ansible.builtin.systemd:
name: keepalived
state: reloadedThe template task writes the configuration with mode 0600, then the keepalived -t handler validates before reloading. Because it's idempotent, running the playbook twice changes nothing if the configuration is already the same.
Never deploy a configuration that hasn't been validated. The safe sequence:
sudo keepalived -t -f /etc/keepalived/keepalived.conf
sudo systemctl reload keepalivedkeepalived -t is a mandatory gate before systemctl reload keepalived. Keepalived 2.x supports reload via SIGHUP, received through systemctl reload, without dropping the active VIP.
If a reload produces strange behavior, revert to the previous version:
git checkout config-1.2.3
sudo keepalived -t -f /etc/keepalived/keepalived.conf
sudo systemctl reload keepalivedThe sequence git checkout then validate then reload makes rollback tested and fast. Also keep the old keepalived.conf at /etc/keepalived/keepalived.conf.bak before deploying as a second safety net.
Drift is a configuration difference between nodes that should be identical. Detect it routinely with diff:
scp lb02:/etc/keepalived/keepalived.conf /tmp/lb02.conf
diff /etc/keepalived/keepalived.conf /tmp/lb02.confAn empty diff /etc/keepalived/keepalived.conf /tmp/lb02.conf output means both nodes are consistent. Unintended differences in parameters like virtual_router_id and priority should be fixed right away.
Ansible and other automation tools work on the assumption of a desired state: no matter how many times you run them, the result is the same. This is the main guard against drift. Only the configuration rendered from the template is used, not hand-edited results, so a node that drifts will return to the correct state the next time the playbook runs.
Episode 11 changes how you treat Keepalived configuration: from a local artifact into an asset that is versioned, rendered, validated, and deployed automatically. With Git and Ansible, drift between nodes can be detected and eliminated.
Key takeaways:
keepalived -t before reloading.systemctl reload uses SIGHUP without dropping the VIP.git checkout of a previous version tag.In episode 12 next, we cover HA for gateways and router redundancy — Keepalived for gateway failover and outbound routing, redundant default gateways with VRRP, and integration with Linux routing and policy routing.