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.
Join the DZone community and get the full member experience.
Join For FreeBeethoven 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 finalnginx.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.
Conclusion
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.
Published at DZone with permission of Jeremy Unruh, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments