HAProxy with Consul

HAProxy with Consul

Aug 11 2014 Armon Dadgar

Consul provides both a DNS and HTTP interface for doing service discovery. This works for broad set of uses, but latency sensitive or high-throughput applications can benefit from reducing the overhead of service discovery by using a client-side load balancer such as HAProxy.

Using consul-haproxy makes it incredibly simple to provide a configuration template for HAProxy and have it dynamically populated based on service information from Consul. This allows HAProxy to be updated seamlessly with zero downtime. While this approach requires a prior configuration, it also reduces the per-request overhead of service discovery.

Why use a load balancer?

As mentioned, Consul provides both DNS and HTTP interfaces for service discovery. The DNS interface makes it simple for applications to make use of Consul's discovery features without having to make code changes. Conversely, the HTTP API can be used to get rich information about services and enables clients to do intelligent routing and load balancing. However, this requires that clients be Consul-aware which isn't always possible.

Deploying an intermediate load balancer is a middle ground approach. Using consul-haproxy information from Consul is used to dynamically configure a local HAProxy instance. This allows applications to route to a local HAProxy instance which can perform the rich routing and load balancing without the end application being Consul-aware.

Using the DNS interface also imposes a small latency cost per-request. This is generally not an issue, but for high-throughput or latency sensitive applications it is preferable to avoid that cost. Using consul-haproxy allows an application to talk directly to the load balancer without making any additional requests. The load balancer is reconfigured anytime the underlying service changes ensuring an up-to-date configuration.


consul-haproxy provides the glue required to read service information from Consul and dynamically configure an HAProxy instance. It works by specifying any number of "backends" which are services filtered by name, tag or datacenter. These backends are interpolated into a template configuration file which HAProxy consumes. Lastly, consul-haproxy monitors the backends for changes and regenerates the configuration and reloads HAProxy to ensure new nodes are added and old nodes removed.

The first step with consul-haproxy

defaults mode tcp timeout connect 5000ms timeout client 60000ms timeout server 60000ms

listen http-in bind *:80{{range .app}} {{.}} maxconn 32{{end}}

This template makes use of the Golang templating language. Using the templating language is quite simple. Because we defined the app backend, that variable is available for us to iterate over. Now that we've specified our backends and template, we can use consul-haproxy to perform a dry-run to get an example output:

consul-haproxy -in in.conf -backend "app=webapp@dc1" -backend "app=webapp@dc2" -backend "app=webapp@dc3" -dry

Using the -dry flag, consul-haproxy

defaults mode tcp timeout connect 5000ms timeout client 60000ms timeout server 60000ms

listen http-in bind *:80 server 0_nyc1-worker-1_webapp maxconn 32 server 0_nyc1-worker-2_webapp maxconn 32 server 0_nyc1-worker-3_webapp maxconn 32 server 1_sfo1-worker-1_webapp maxconn 32 server 1_sfo1-worker-2_webapp maxconn 32

The list of servers in the http-in block has been dynamically populated using the service catalog from Consul.

Automatic Reload

When actually running consul-haproxy we must provide an output path and a reload command. This allows the configuration to be written out and HAProxy to be reloaded with the latest configuration.

By adding the -reload flag, consul-haproxy will invoke the given command any time the configuration changes, allowing HAProxy to be reloaded:

$ consul-haproxy ... -reload "sudo reload haproxy"

The Consul HTTP API supports long polling for changes in the service catalog, which enables consul-haproxy to efficiently detect changes and update the configuration for HAProxy in real-time.

Improved Process

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now