load_balancer_setup
Runs ansible/load_balancer_setup.yml to configure a RHEL-family host as an haproxy + keepalived load balancer, as part of the Linux SOE. Use when asked to set up, check, or fix a load balancer host, h
SKILL.md.claude/skills/load_balancer_setup/SKILL.md
GitHubload_balancer_setup
Runs ansible/load_balancer_setup.yml, a purpose-built playbook that
configures haproxy + keepalived on a host, by reusing four generic,
list-driven domain roles with load-balancer-specific variables set directly
in the playbook (not those roles' own defaults/main.yml). See
docs/ARCHITECTURE.md for the six-playbook layout this fits into, and each
role's own SKILL.md (packages_install, files_copy, sebooleans,
service_state) for what it does in the general case.
Policy & workload awareness
This playbook doesn't own an ansible/roles/<name>/ directory of its
own — it reuses packages_install, files_copy, sebooleans, service_state, each of which already carries its own
policy/workload staleness check in its own SKILL.md (see
docs/ARCHITECTURE.md's "Policy & workload awareness"). What's specific to
this playbook is the load_balancer_setup.yml-specific variables set directly
there rather than in any role's own defaults/main.yml — check whether
those need updating too:
git log -1 --format='%cI %h %s' -- docs/VERTICAL_POLICY.md docs/HORIZONTAL_POLICY.md docs/WORKLOAD.md
git log -1 --format='%cI %h %s' -- ansible/load_balancer_setup.yml
If the docs are newer than the playbook file, re-read both docs with this specific workload in mind (not just the general-baseline case each underlying role's own check considers) before assuming nothing needs to change.
What the playbook actually does
Encoded directly in ansible/load_balancer_setup.yml's vars: block:
packages_install: [haproxy, keepalived]— installs both packages via thepackages_installrole, overriding that role's own default baseline utility package list entirely (this playbook'svars:replace the role'sdefaults/main.ymlvalue, they don't add to it).files_copydeployskeepalived-notify-haproxyto/usr/local/sbin/keepalived-notify-haproxy(mode0755).files_copy_templatesrenders three Jinja templates:haproxy-global.cfg.j2→/etc/haproxy/haproxy.cfg,haproxy-app.cfg.j2→/etc/haproxy/conf.d/app.cfg, andkeepalived.conf.j2→/etc/keepalived/keepalived.conf.service_state_enable: [keepalived]— onlykeepalivedis enabled directly; the comment in the playbook notes keepalived manages haproxy itself (via the notify script above), so haproxy isn't separately enabled here.- A second
service_staterole invocation conditionally reloads haproxy and restarts keepalived, but onlywhen: copy_templates is changed and start_services is not changed— i.e. only if the templates actually changed on this run and the initial enable didn't already restart something, avoiding a redundant double-restart. sebooleansis in theroles:list but itsvars:(sebooleans_enable: [haproxy_connect_any]) is commented out by default — see "Notes" below.
Known gap, verified against this checkout: the four assets this playbook references —
keepalived-notify-haproxy,haproxy-global.cfg.j2,haproxy-app.cfg.j2,keepalived.conf.j2— do not exist anywhere in this repository (noansible/files/, noansible/templates/, nothing underroles/files_copy/).files_copy'sansible.builtin.copy/templatetasks resolvesrc:by searching the playbook directory'sfiles//templates/subdirectories (and the current role's, when one applies) — none of those exist here. Running this playbook today fails with "could not find src" on both thefiles_copyandfiles_copy_templatestasks, both under--checkand for real. Don't tell a user this playbook works end-to-end without flagging this; the package install,sebooleans, andservice_statesteps are unaffected and will still run.
What to do
Audit (read-only, safe to run any time):
ansible-playbook ansible/load_balancer_setup.yml --check --diff
Summarize the diff output and any failed tasks in plain language. To audit
just one piece (e.g. only the package install), add --tags packages_install
etc.
Remediate (modifies the system — only after the user explicitly asks):
first summarize what will change from the --check --diff output, then run
the same command without --check:
ansible-playbook ansible/load_balancer_setup.yml
Propose a change to this playbook or its templates: never edit and
commit directly. On a branch named soe/load_balancer_setup/<short-desc>,
edit ansible/load_balancer_setup.yml and/or the referenced templates,
validate locally (--syntax-check, --check --diff against a real/test
host if available), then push and open a PR titled
[load_balancer_setup] <what changed> with the --check --diff output in
the body. Then stop — a human reviews and merges; see
docs/ARCHITECTURE.md's "Contribution workflow". If the change is really
to one of the underlying roles' general behavior (not this playbook's
specific use of it), scope the branch/PR to that role instead, per its own
SKILL.md.
Notes
- Before anything else: this playbook can't currently deploy the
haproxy/keepalived config (see the gap noted above) — create
ansible/files/keepalived-notify-haproxyandansible/templates/{haproxy-global.cfg,haproxy-app.cfg,keepalived.conf}.j2(or whereverfiles_copy's search path actually needs them for this playbook) before relying on it for a real load balancer build-out, and propose that addition via the branch + PR workflow below like any other change. sebooleans_enable: [haproxy_connect_any]is present in the playbook but commented out — SELinux may block haproxy from connecting out to backend servers on a non-standard port until this is enabled. If haproxy fails to reach its backends and SELinux is enforcing, checkausearch/sealertforhaproxy_connect_anydenials and uncomment this before assuming the haproxy config itself is wrong.- This playbook doesn't open any firewalld ports/services for haproxy —
unlike
nfs_server_setup.yml, it has nofirewallrole invocation at all. If the load balancer needs firewalld rules, that's a change to propose to this playbook (or handle viaconfigure_rhel.yml'sfirewallrole for that host/group), not something this playbook does today.