HAProxy-SRV is a templating solution that can flexibly reconfigure HAProxy based on the regular polling of the service data from DNS (e.g. SkyDNS or Mesos-DNS) using SRV records.
HAProxy-SRV also works with Round-Robin DNS A records, like Docker Swarm Mode.
It has a very simple logic - HA Proxy is configured based on the Handlebars template that is re-evaluated every time changes in DNS are detecting. Script is polling DNS and trigger a HA Proxy configuration refresh after changes.
Made by elastic.io in Germany.
Simplest way to start it with Docker:
docker run -d -p 8080:8080 -p 80:80 -v $PWD/haproxy.cfg.template:/src/haproxy.cfg.template elasticio/haproxy-srv:latest
if you want to see more DEBUG output then just add -e "DEBUG=*"
Script works very simple - after docker container started script parse and validates template, create a HAProxy configuration file in /src/haproxy.cfg
and start HAProxy as a daemon. Every second (by default, can be configured via REFRESH_TIMEOUT
env variable, default 1000) scirpt will execute a DNS lookup and re-evaluate the template, if result of evaluation is different from original configuration, original config will be overwritten and HAProxy reload will be triggered. HAProxy reload will not affect existing connections.
Recommended way to deploy is is to use a Docker image. You would need to place your configuration file template, the simples way to do it is to build an image based on haproxy-srv
image.
Create a new Dockerfile
content like this:
FROM elasticio/haproxy-srv:latest
COPY haproxy.cfg.template /src/
EXPOSE 80 8880
Note the EXPOSE
part here, don't forget to specify exposed ports if your HAProxy configuration listens on any port different from 80
.
As a next step create a template file, it should be placed under /src/haproxy.cfg.template
in resulting Docker container and should have a Handlebars syntax with one little extension (see below). Here is the sample:
It could be any valid HAProxy configuration with one mandatory addition:
stats socket /tmp/haproxy.sock level admin
to trigger HAProxy restart the script inside the file will communicate with HAProxy daemon via socket /tmp/haproxy.sock
.
Configuration template is a normal Handlebars so that you could use any of the feature of this template language. There is however one additional helper dns-srv
implemented. This helper takes one string parameter and will execute a DNS SRV lookup to fetch an SRV record(s). After SRV Record lookup, for each SRV record a DNS resolution to find the IP will be made.
This template will give you an idea how to use it:
Typical use-case for Msos-DNS you can see above.
First, create a network, and web service:
$ docker network create -d overlay --subnet 10.1.1.0/24 my_net
$ docker service create --replicas 2 --name my_web --network my_net nginx
By default, services are created as --endpoint-mode vip
. If you use VIP mode,
then the Round-Robin DNS name is tasks.my_web
. If you use --endpoint-mode dnsrr
then the my_web
DNS name will work in the HAProxy dns-a
template.
Follow the How to use it section above on creating a new proxy image using
a custom haproxy.cfg.template. For the dns-a
section use:
{{#dns-a "tasks.my_web"}}
# other configs
backend my_web
{{#each this}}
server {{name}} {{ip}}:80 check
{{/each}}
{{/dns-a}}
$ mkdir my_proxy ; cd my_proxy
# (make a new Dockerfile)
$ docker build -t my_proxy_image .
Fire up a new proxy, publishing port 80 to something unique on each docker host node
$ docker service create --name my_proxy --network my_net -p 8081:80 my_proxy_image
Optionally, use some other method for sharing & binding the haproxy.cfg.template file
into the elasticio/haproxy-srv
image.
Just set the DEBUG
environment variable into *
to see detailed logging.
PRs are welcome for
- Bug fixes
- Unit tests
- Gulp or Grunt-based builds
- CircleCI config for continous integration