A manager for VirtualIPs in multinetwork environments.
virtualip-manager renders a keepalived configuration from a
declarative VirtualIP spec and runs keepalived to advertise those VIPs over VRRP. It is
distributed as a container image that bundles the generate-config binary together with a
purpose-built keepalived (compiled with JSON status support).
The container entrypoint runs two steps:
generate-config -input <spec.yaml> -output /etc/keepalived/keepalived.conf— reads and validates the VirtualIP spec, resolves each address to a host network interface, and renders the keepalived config.exec keepalived …— starts keepalived against the generated config.
For each address, the node whose NODE_NAME matches the address's node becomes the VRRP
MASTER (priority 130); every other node is a BACKUP (priority 80).
The input is a VirtualIPConfiguration document (apiVersion loadbalancer.scality.com/v1alpha1):
---
apiVersion: loadbalancer.scality.com/v1alpha1
kind: VirtualIPConfiguration
addresses:
- ip: 172.18.0.10 # virtual IP to advertise
node: bootstrap # node that should own this VIP (becomes MASTER)
vrId: 51 # VRRP virtual_router_id (must be unique per VIP on the segment)
- ip: 172.18.0.11
node: node1
vrId: 52
healthcheck: https://__NODE_IP__:443/healthz # optional; __NODE_IP__ is substituted at runtime
healthcheckNodePort: http://localhost:31846 # optional; probes a local NodePortaddressesis required and must be non-empty. Each entry needsip,node, andvrId.healthcheckis optional. When set, avrrp_script check_getis added that probes the URL every 5s via/etc/keepalived/check-get.sh(shipped fromscripts/check-get.sh); the__NODE_IP__token is replaced with theNODE_IPenv var.healthcheckNodePortis optional and follows the same rules, emitting avrrp_script check_get_nodeport. It is meant to probe a service exposed locally on a NodePort.- Each
vrrp_instancegets atrack_scriptblock listing the scripts that are enabled; when neither healthcheck is set, novrrp_scriptand notrack_scriptblock is generated. - Both healthcheck fields are validated at startup: the value must be an
httporhttpsURL with a host, and must not contain characters that would break the generated keepalived config (quotes, whitespace, and shell metacharacters). A key present but left empty counts as absent.
The check script is used by keepalived to check that the local node, where the keepalived process is running, is ready to get some load.
generate-config is configured by environment variables (validated at startup):
| Variable | Required | Default | Purpose |
|---|---|---|---|
NODE_IP |
yes | — | This node's IP; substituted into the healthcheck. |
NODE_NAME |
yes | — | This node's name; decides MASTER vs BACKUP. |
LOGGER_LOG_LEVEL |
no | info |
Log level for the structured (slog) logger. |
NODE_IP must parse as an IP address; it is interpolated into the generated keepalived config, so
anything else is rejected at startup.
Flags: -input <path> (required) and -output <path> (defaults to stdout).
Run locally against a spec file:
cat >spec.yaml <<EOF
---
apiVersion: loadbalancer.scality.com/v1alpha1
kind: VirtualIPConfiguration
addresses:
- ip: 172.17.0.15
node: bootstrap
vrId: 51
- ip: 172.17.0.16
node: node1
vrId: 52
- ip: 172.17.0.17
node: node2
vrId: 53
healthcheck: https://__NODE_IP__:443/healthz
healthcheckNodePort: http://localhost:31846
EOF
NODE_NAME=bootstrap NODE_IP=1.1.1.1 \
go run ./cmd -input ./spec.yamlBuild and run the container:
make docker-build # builds virtualip-manager:latest
docker run --rm --privileged --network host \
-e NODE_NAME=bootstrap -e NODE_IP=172.18.0.1 \
-v "$PWD/spec.yaml:/etc/keepalived/keepalived-input.yaml" \
virtualip-manager:latest- DESIGN.md — architecture and internals.
- CONTRIBUTING.md — development workflow and conventions.