-
Notifications
You must be signed in to change notification settings - Fork 2
dataplaneapi
Load-balancing and fault-tolerance in services can be very complex, but fortunately there are projects that make this task a little more pleasant. In this article, we will show you how to use the HAProxy (or technically Data Plane API) integration with Overlord.
dataplaneapi-metadata.yml:
kind: metadata
datacenters:
main:
entrypoint: !ENV '${ENTRYPOINT}'
access_token: !ENV '${TOKEN}'
deployIn:
labels:
- desktop
- centralita
metadata:
haproxy.makejail: |
OPTION start
OPTION overwrite=force
OPTION volume=dataplaneapi-data mountpoint:/usr/local/etc/haproxy owner:0 group:0
INCLUDE gh+DtxdF/efficient-makejail
CMD mkdir -p /usr/local/etc/pkg/repos
COPY ${OVERLORD_METADATA}/dataplaneapi.pkg.conf /usr/local/etc/pkg/repos/Latest.conf
PKG haproxy dataplaneapi
CMD mkdir -p /usr/local/etc/haproxy
RAW if appjail cmd jexec "${APPJAIL_JAILNAME}" [ ! -f /usr/local/etc/haproxy/haproxy.cfg ]; then
COPY ${OVERLORD_METADATA}/haproxy.conf /usr/local/etc/haproxy/haproxy.cfg
RAW fi
SYSRC haproxy_enable=YES
SYSRC haproxy_config=/usr/local/etc/haproxy/haproxy.cfg
SYSRC dataplaneapi_enable=YES
SERVICE haproxy start
SERVICE dataplaneapi start
haproxy.conf: !ENV |
global
daemon
stats socket /var/run/haproxy.sock mode 666 level admin
stats timeout 2m
log 127.0.0.1:514 local0
log-tag HAProxy
defaults
mode http
log global
option httplog
timeout http-request 10s
timeout connect 10s
timeout client 30s
timeout server 50s
userlist controller
user admin insecure-password ${DATAPLANEAPI_PASSWORD}
frontend stats
mode http
bind :8404
stats uri /
stats enable
stats refresh 10s
stats show-modules
stats auth admin:${DATAPLANEAPI_STATS_PASSWORD}
frontend web
bind :4080
default_backend web
backend web
balance roundrobin
option httpchk HEAD /
dataplaneapi.pkg.conf: |
FreeBSD: {
url: "pkg+https://pkg.FreeBSD.org/${ABI}/latest",
mirror_type: "srv",
signature_type: "fingerprints",
fingerprints: "/usr/share/keys/pkg",
enabled: yes
}
FreeBSD-kmods: {
enabled: no
}Now we need to define the deployment file to deploy HAProxy with Data Plane API. Remember that now this service will act as a reverse proxy to the service we want to deploy, so for the client's point of view, instead of using the IP address of the server where the service is deployed, we will use the IP address of the server where HAProxy is deployed. The port is entirely up to you, but in the above case the frontend is configured to use port 4080. The backend is important for Overlord as it is the part that touches to add, update or remove your service from the HAProxy configuration file.
Note that we also copy the HAProxy configuration file only once. First, because we are using a volume to persist the data generated by Data Plane API, and second, because we should not overwrite the HAProxy configuration file since Data Plane API has probably already touched it.
dataplaneapi.yml:
kind: directorProject
datacenters:
main:
entrypoint: !ENV '${ENTRYPOINT}'
access_token: !ENV '${TOKEN}'
deployIn:
labels:
- desktop
- centralita
projectName: load-balancer
projectFile: |
options:
- alias:
- ip4_inherit:
services:
haproxy:
makejail: !ENV '${OVERLORD_METADATA}/haproxy.makejail'
options:
- label: 'overlord.skydns:1'
- label: 'overlord.skydns.group:haproxy'
- label: 'overlord.skydns.interface:tailscale0'
volumes:
- data: dataplaneapi-data
default_volume_type: '<volumefs>'
volumes:
data:
device: /var/appjail-volumes/dataplaneapi/dataThe next step is to configure each API server. In the deployment file above, we will deploy HAProxy and Data Plane API in two chains. The idea is that each instance is located in different places in the country (as in my case). The other thing worth mentioning is SkyDNS, as it is used in the deployment above, so it also balances the load of each HAProxy instance from the client side.
/usr/local/etc/overlord.yml:
dataplaneapi:
auth:
username: 'admin'
password: '<password>'
entrypoint: 'http://<IP address or Host Name>:5555'After all this, we can finally define the deployment file for our service. As in other integrations, Overlord intercepts the labels and performs some tasks. In this case the relevant labels are overlord.load-balancer:1 to use Data Plane API, overlord.load-balancer.backend:web indicating the backend, overlord.load-balancer.interface:tailcale0 the interface to get the IP address, overlord.load-balancer.port the external port of the service that should be accessible from HAProxy, and overlord.load-balancer.set.check:"enabled" an optional parameter to enable HAProxy's healthcheckers.
hello-http-metadata.yml:
kind: metadata
datacenters:
main:
entrypoint: !ENV '${ENTRYPOINT}'
access_token: !ENV '${TOKEN}'
deployIn:
labels:
- dc-earth
- dc-air
exclude:
- provider
metadata:
hello-http.makejail: |
ARG hello_http_port=80
OPTION start
OPTION overwrite=force
INCLUDE gh+DtxdF/efficient-makejail
CMD mkdir -p /usr/local/etc/pkg/repos
COPY ${OVERLORD_METADATA}/hello-http.pkg.conf /usr/local/etc/pkg/repos/Latest.conf
PKG darkhttpd
CMD echo "Hello from `uuidgen -r`" > /usr/local/www/darkhttpd/index.html
SYSRC "darkhttpd_flags=--uid darkhttpd --gid darkhttpd --port ${hello_http_port}"
SYSRC darkhttpd_enable=YES
SERVICE darkhttpd start
hello-http.pkg.conf: |
FreeBSD: {
url: "pkg+https://pkg.FreeBSD.org/${ABI}/latest",
mirror_type: "srv",
signature_type: "fingerprints",
fingerprints: "/usr/share/keys/pkg",
enabled: yes
}
FreeBSD-kmods: {
enabled: no
}hello-http.yml:
kind: directorProject
datacenters:
main:
entrypoint: !ENV '${ENTRYPOINT}'
access_token: !ENV '${TOKEN}'
deployIn:
labels:
- dc-earth
- dc-air
exclude:
- provider
projectName: hello-http
projectFile: |
options:
- alias:
- ip4_inherit:
services:
darkhttpd:
makejail: !ENV '${OVERLORD_METADATA}/hello-http.makejail'
options:
- label: 'appjail.dns.alt-name:hello-http'
- label: 'overlord.load-balancer:1'
- label: 'overlord.load-balancer.backend:web'
- label: 'overlord.load-balancer.interface:tailscale0'
- label: !ENV 'overlord.load-balancer.interface.port:${OVERLORD_FREEPORT_TAILSCALE0}'
- label: 'overlord.load-balancer.set.check:"enabled"'
arguments:
- hello_http_port: !ENV '${OVERLORD_FREEPORT_TAILSCALE0}'
reserve_port:
tailscale0:The last step is to deploy the previous deployment files.
# overlord apply -f dataplaneapi-metadata.yml
# overlord apply -f dataplaneapi.yml
# overlord get-info -f dataplaneapi.yml -t projects --filter-per-project
datacenter: http://controller.namespace.lan:8888
entrypoint: main
chain: None
labels:
- all
- desktop
- services
- vm-only
- dc-air
projects:
load-balancer:
state: DONE
last_log: 2025-08-15_15h58m28s
locked: False
services:
- {'name': 'haproxy', 'status': 0, 'jail': 'b60ffd4e76'}
up:
operation: COMPLETED
output:
rc: 0
stdout: {'errlevel': 0, 'message': None, 'failed': []}
last_update: 3 hours, 11 minutes and 2.83 seconds
job_id: 31
restarted: False
labels:
error: False
message: None
load-balancer:
services:
haproxy:
error: False
message: None
skydns:
services:
haproxy:
error: False
message: (project:load-balancer, service:haproxy, records:[address:True,ptr:None,srv:None] records has been updated.
datacenter: http://controller.namespace.lan:8888
entrypoint: main
chain: centralita
labels:
- all
- centralita
- services
- dc-earth
projects:
load-balancer:
state: DONE
last_log: 2025-08-15_15h58m29s
locked: False
services:
- {'name': 'haproxy', 'status': 0, 'jail': 'c05455807f'}
up:
operation: COMPLETED
output:
rc: 0
stdout: {'errlevel': 0, 'message': None, 'failed': []}
last_update: 3 hours, 10 minutes and 24.54 seconds
job_id: 5
restarted: False
labels:
error: False
message: None
load-balancer:
services:
haproxy:
error: False
message: None
skydns:
services:
haproxy:
error: False
message: (project:load-balancer, service:haproxy, records:[address:True,ptr:None,srv:None] records has been updated.
# overlord apply -f hello-http-metadata.yml
# overlord apply -f hello-http.yml
# overlord get-info -f hello-http.yml -t projects --filter-per-project
datacenter: http://controller.namespace.lan:8888
entrypoint: main
chain: None
labels:
- all
- desktop
- services
- vm-only
- dc-air
projects:
hello-http:
state: DONE
last_log: 2025-08-15_18h59m07s
locked: False
services:
- {'name': 'darkhttpd', 'status': 0, 'jail': '8f8f7c848e'}
up:
operation: COMPLETED
output:
rc: 0
stdout: {'errlevel': 0, 'message': None, 'failed': []}
last_update: 9 minutes and 24.42 seconds
job_id: 33
restarted: False
labels:
error: False
message: None
load-balancer:
services:
darkhttpd:
error: False
message: (project:hello-http, service:darkhttpd, backend:web, serverid:0d67d160-61af-4810-b277-5fb9e20da8eb, code:202, transaction_id:b6b2cd6e-2d0f-4b54-9f30-1e4dfb149637, commit:1) server has been successfully added.
skydns:
services:
darkhttpd:
error: False
message: None
datacenter: http://controller.namespace.lan:8888
entrypoint: main
chain: provider.carl
labels:
- all
- carl
- services
- dc-earth
projects:
hello-http:
state: DONE
last_log: 2025-08-15_18h59m36s
locked: False
services:
- {'name': 'darkhttpd', 'status': 0, 'jail': '130edf0c32'}
up:
operation: COMPLETED
output:
rc: 0
stdout: {'errlevel': 0, 'message': None, 'failed': []}
last_update: 8 minutes and 48.42 seconds
job_id: 3
restarted: False
labels:
error: False
message: None
load-balancer:
services:
darkhttpd:
error: False
message: (project:hello-http, service:darkhttpd, backend:web, serverid:02c29ac1-eadc-4a16-835d-6377f4a01aea, code:202, transaction_id:f670f33d-2018-4d4d-8ec0-bb7308ced563, commit:1) server has been successfully added.
skydns:
services:
darkhttpd:
error: False
message: None
datacenter: http://controller.namespace.lan:8888
entrypoint: main
chain: centralita
labels:
- all
- centralita
- services
- dc-earth
projects:
hello-http:
state: DONE
last_log: 2025-08-15_18h59m08s
locked: False
services:
- {'name': 'darkhttpd', 'status': 0, 'jail': '0ab7ba1640'}
up:
operation: COMPLETED
output:
rc: 0
stdout: {'errlevel': 0, 'message': None, 'failed': []}
last_update: 8 minutes and 41.32 seconds
job_id: 7
restarted: False
labels:
error: False
message: None
load-balancer:
services:
darkhttpd:
error: False
message: (project:hello-http, service:darkhttpd, backend:web, serverid:f4b9e170-67bb-403e-88da-112c55b45fce, code:202, transaction_id:cf16b162-5584-41e7-9b94-af25b81bb615, commit:1) server has been successfully added.
skydns:
services:
darkhttpd:
error: False
message: None
datacenter: http://controller.namespace.lan:8888
entrypoint: main
chain: r2
labels:
- all
- r2
- services
- dc-air
projects:
hello-http:
state: DONE
last_log: 2025-08-15_18h59m14s
locked: False
services:
- {'name': 'darkhttpd', 'status': 0, 'jail': 'b4bd3f771b'}
up:
operation: COMPLETED
output:
rc: 0
stdout: {'errlevel': 0, 'message': None, 'failed': []}
last_update: 3 minutes and 42.37 seconds
job_id: 31
restarted: False
labels:
error: False
message: None
load-balancer:
services:
darkhttpd:
error: False
message: (project:hello-http, service:darkhttpd, backend:web, serverid:73ddf13e-cd81-420d-9c67-835f4cdafd69, code:202, transaction_id:e97527fd-4cc3-44ed-bd9c-ad454faf4293, commit:1) server has been successfully added.
skydns:
services:
darkhttpd:
error: False
message: NoneTesting:
$ curl http://haproxy.overlord.lan:4080
Hello from 18a7ff90-4773-4970-95ad-9ad2e0012a71
$ curl http://haproxy.overlord.lan:4080
Hello from bd36b060-d80e-401f-b3dd-972e1d4a4435
$ curl http://haproxy.overlord.lan:4080
Hello from 64b3cffb-bf8f-48dd-83d8-fb61cd46f2b9
$ curl http://haproxy.overlord.lan:4080
Hello from 3f5c2c3c-b3f0-4d2d-9c3d-2e40c654d827