Discoverable HTTP Load Balancing in Mesos and Marathon Using Beethoven and Nginx

DZone 's Guide to

Discoverable HTTP Load Balancing in Mesos and Marathon Using Beethoven and Nginx

Beethoven is an application written in Go that automatically configures Nginx for applications deployed on Marathon/Mesos.

· Integration Zone ·
Free Resource

Beethoven is an application written in Go that automatically configures Nginx for applications deployed on Marathon and Mesos. Beethoven runs in Docker and can be managed by Marathon to provide HTTP load balancing.

Feature Highlights

Beethoven uses NGINX for HTTP-based load balancing and has handlebars for powerful template parsing. There's zero downtime load balancing when changes occur. It allows stream filtering so that NGINX re-configuration is only triggered by RegEx patterns and listens to the real-time SSE from Marathon to quickly change upstreams based on application and tasks state changes. There are also RESTful endpoints for current status and flexible configuration options (local config, spring-cloud configuration remote configuration fetching, and ENV variables).

It's easy to get started and use Beethoven; simply add a FROM containx/beethoven to your Dockerfile add your template, config options, and deploy.

A Look at the Beethoven Container


Beethoven takes a user-defined Nginx conf template and listens to events from Marathon. When an application or task state changes, Beethoven parses the template and writes it to a temp location. Beethoven then asks Nginx to validate the newly generated configuration file. On success, Beethoven will copy the temp configuration onto the one serving traffic followed by an Nginx reload. Beethoven exposes a RESTful interface. This allows you to find out information such as last updates, last error, and any failed configuration templates.

Getting Started

Below, I will cover the bare bones setup to get you up and running.

Create a Template

Create a file called nginx.template. Refer to the nginx.template found in the examples/ directory in this repo. Modify the example to suit your own needs.

Notes About the Example Template

  • The {{#if}} blocks are optional. I prefer these so that if an application is removed altogether in the cluster, then the final nginx.conf is valid.
  • The /_health endpoint at the bottom is optional. It allows Marathon health checks to use that to determine Nginx is running.
  • The /_bt endpoint at the bottom is optional. If you would like to find information such as updated times and any failures from Beethoven, then this mapping allows you to expose these internal endpoints via Nginx. Alternatively, you can expose Beethoven via its configured port.

Create the Beethoven Configuration File

Create a file that ends in .json. In this example, we’ll call it btconf.json. Refer to the btconf.json found in the examples/ directory in this repo.

Add or modify any options to suit your needs. For a description and all possible configuration options, refer to the docs found within the config.go file.

Create a Dockerfile

Next, we will create the Dockerfile to package up the nginx.template and btconf.json files. If you used the filenames in this guide, then simply copy the code below into your Dockerfile.

FROM containx/beethoven

ADD nginx.template /etc/nginx/nginx.template
ADD btconf.json /etc/btconf.json

Build and Testing Your Container

Build and run your container.

docker build -t myloadbalancer .
docker run -p 80:80 -d myloadbalancer -c /etc/btconf.json

Now open your browser and test paths you created at http://localhost.


As you can see, Beethoven allows for easy HTTP load balancing to dynamically discovered microservices and applications within your cluster. In the example we provided, we used a local/static configuration file. To leverage a dynamic remote configuration file served by spring-cloud config, read the full README at this link.

beethoven, containers, http, integration, load balancing, nginx

Published at DZone with permission of Jeremy Unruh , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}