diff --git a/website/source/assets/images/lb-homepage.png b/website/source/assets/images/lb-homepage.png new file mode 100644 index 000000000..567f2d8d4 Binary files /dev/null and b/website/source/assets/images/lb-homepage.png differ diff --git a/website/source/assets/images/lb-routing-table.png b/website/source/assets/images/lb-routing-table.png new file mode 100644 index 000000000..d37682b64 Binary files /dev/null and b/website/source/assets/images/lb-routing-table.png differ diff --git a/website/source/assets/images/routing-table.png b/website/source/assets/images/routing-table.png new file mode 100644 index 000000000..acc71946f Binary files /dev/null and b/website/source/assets/images/routing-table.png differ diff --git a/website/source/guides/load-balancing/fabio.html.md b/website/source/guides/load-balancing/fabio.html.md new file mode 100644 index 000000000..718caca70 --- /dev/null +++ b/website/source/guides/load-balancing/fabio.html.md @@ -0,0 +1,233 @@ +--- +layout: "guides" +page_title: "Load Balancing with Nomad" +sidebar_current: "guides-load-balancing" +description: |- + There are multiple approaches to load balancing within a Nomad cluster. + One approach involves using [fabio][fabio]. Fabio integrates natively + with Consul and provides rich features with an optional Web UI. +--- + +# Load Balancing with Fabio + +[Fabio][fabio] integrates natively with Consul and provides an optional Web UI +to visualize routing. + +The main use case for fabio is to distribute incoming HTTP(S) and TCP requests +from the internet to frontend services that can handle these requests. This +guide will show you one such example using [Apache][apache] web server. + +## Reference Material + +- [Fabio](https://github.com/fabiolb/fabio) on GitHub +- [Load Balancing Strategies for Consul](https://www.hashicorp.com/blog/load-balancing-strategies-for-consul) +- [Elastic Load Balancing][elb] + +## Estimated Time to Complete + +20 minutes + +## Challenge + +Think of a scenario where a Nomad operator needs to configure an environment to +make Apache web server highly available behind an endpoint and distribute +incoming traffic evenly. + +## Solution + +Deploy fabio as a +[system][system] +scheduler so that it can route incoming traffic evenly to the Apache web server +group regardless of which client nodes Apache is running on. Place all client nodes +behind an [AWS load balancer][elb] to +provide the end user with a single endpoint for access. + +## Prerequisites + +To perform the tasks described in this guide, you need to have a Nomad +environment with Consul installed. You can use this +[repo](https://github.com/hashicorp/nomad/tree/master/terraform#provision-a-nomad-cluster-in-the-cloud) +to easily provision a sandbox environment. This guide will assume a cluster with +one server node and three client nodes. + +-> **Please Note:** This guide is for demo purposes and is only using a single server +node. In a production cluster, 3 or 5 server nodes are recommended. + +## Steps + +### Step 1: Create a Job for Fabio + +Create a job for Fabio and name it `fabio.nomad` + +```hcl +job "fabio" { + datacenters = ["dc1"] + type = "system" + + group "fabio" { + task "fabio" { + driver = "docker" + config { + image = "fabiolb/fabio" + network_mode = "host" + } + + resources { + cpu = 200 + memory = 128 + network { + mbits = 20 + port "lb" { + static = 9999 + } + port "ui" { + static = 9998 + } + } + } + } + } +} +``` + +Setting `type` to [system][system] will ensure that fabio is run on all clients. +Please note that the `network_mode` option is set to `host` so that fabio can +communicate with Consul which is also running on the client nodes. + +### Step 2: Run the Fabio Job + +We can now register our fabio job: + +```shell +$ nomad job run fabio.nomad +==> Monitoring evaluation "fba4f04a" + Evaluation triggered by job "fabio" + Allocation "6e6367d4" created: node "f3739267", group "fabio" + Allocation "d17573b4" created: node "28d7f859", group "fabio" + Allocation "f3ad9b16" created: node "510898b6", group "fabio" + Evaluation status changed: "pending" -> "complete" +==> Evaluation "fba4f04a" finished with status "complete" +``` +At this point, you should be able to visit any one of your client nodes at port +`9998` and see the web interface for fabio. The routing table will be empty +since we have not yet deployed anything that fabio can route to. +Accordingly, if you visit any of the client nodes at port `9999` at this +point, you will get a `404` HTTP response. That will change soon. + +### Step 3: Create a Job for Apache Web Server + +Create a job for Apache and name it `webserver.nomad` + +```hcl +job "webserver" { + datacenters = ["dc1"] + type = "service" + + group "webserver" { + count = 3 + restart { + attempts = 2 + interval = "30m" + delay = "15s" + mode = "fail" + } + ephemeral_disk { + size = 300 + } + + task "apache" { + driver = "docker" + config { + image = "httpd:latest" + port_map { + http = 80 + } + } + + resources { + network { + mbits = 10 + port "http" {} + } + } + + service { + name = "apache-webserver" + tags = ["urlprefix-/"] + port = "http" + check { + name = "alive" + type = "http" + path = "/" + interval = "10s" + timeout = "2s" + } + } + } + } +} +``` + +Notice the tag in the service stanza begins with `urlprefix-`. This is how a +path is registered with fabio. In this case, we are registering the path '/' +with fabio (which will route us to the default page for Apache web server). + +### Step 4: Run the Job for Apache Web Server + +We can now register our job for Apache: + +```shell +$ nomad job run webserver.nomad +==> Monitoring evaluation "c7bcaf40" + Evaluation triggered by job "webserver" + Evaluation within deployment: "e3603b50" + Allocation "20951ad4" created: node "510898b6", group "webserver" + Allocation "43807686" created: node "28d7f859", group "webserver" + Allocation "7b60eb24" created: node "f3739267", group "webserver" + Evaluation status changed: "pending" -> "complete" +==> Evaluation "c7bcaf40" finished with status "complete" +``` +You have now deployed and registered your web servers with fabio! At this point, +you should be able to visit any of the Nomad clients at port `9999` and +see the default web page for Apache web server. If you visit fabio's web +interface by going to any of the client nodes at port `9998`, you will see that +the routing table has been populated as shown below (**Note:** your destination IP +addresses will be different). + +[![Routing Table][routing-table]][routing-table] + +Feel free to reduce the `count` in `webserver.nomad` for testing purposes. You +will see that you still get routed to the Apache home page by accessing +any client node on port `9999`. Accordingly, the routing table +in the web interface on port `9999` will reflect the changes. + +### Step 5: Place Nomad Client Nodes Behing AWS Load Balancer + +At this point, you are ready to place your Nomad client nodes behind an AWS load +balancer. Your Nomad client nodes may change over time, and it is important +to provide your end users with a single endpoint to access your services. This guide will use the [Classic Load Balancer][classic-lb]. + +The AWS [documentation][classic-lb-doc] provides instruction on how to create a +load balancer. The basic steps involve creating a load balancer, registering +instances behind the load balancer (in our case these will be the Nomad client +nodes), creating listeners, and configuring health checks. + +Once you are done +with this, you should be able to hit the DNS name of your load balancer at port +80 (or whichever port you configured in your listener) and see the home page of +Apache web server. If you configured your listener to also foward traffic to +the web interface at port `9998`, you should be able to access that as well. + +[![Home Page][lb-homepage]][lb-homepage] + +[![Routing Table][lb-routing-table]][lb-routing-table] + +[apache]: https://httpd.apache.org/ +[classic-lb]: https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/introduction.html +[classic-lb-doc]: https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-getting-started.html +[elb]: https://aws.amazon.com/elasticloadbalancing/ +[fabio]: https://fabiolb.net/ +[lb-homepage]: /assets/images/lb-homepage.png +[lb-routing-table]: /assets/images/lb-routing-table.png +[routing-table]: /assets/images/routing-table.png +[system]: /docs/runtime/schedulers.html#system diff --git a/website/source/guides/load-balancing/load-balancing.html.md b/website/source/guides/load-balancing/load-balancing.html.md new file mode 100644 index 000000000..9a34fe87b --- /dev/null +++ b/website/source/guides/load-balancing/load-balancing.html.md @@ -0,0 +1,20 @@ +--- +layout: "guides" +page_title: "Load Balancing" +sidebar_current: "guides-load-balancing" +description: |- + There are multiple approaches to load balancing within a Nomad cluster. This + discusses the most popular strategies. +--- + +# Load Balancing + +There are multiple approaches to set up load balancing across a Nomad cluster. +Most of these methods assume Consul is installed alongside Nomad (see [Load +Balancing Strategies for +Consul](https://www.hashicorp.com/blog/load-balancing-strategies-for-consul)). + +- [Fabio](/guides/load-balancing/fabio.html) + +Please refer to the specific documentation above or in the sidebar for more +detailed information about each strategy. diff --git a/website/source/layouts/guides.erb b/website/source/layouts/guides.erb index 3a9207a0e..0fce3df53 100644 --- a/website/source/layouts/guides.erb +++ b/website/source/layouts/guides.erb @@ -200,6 +200,15 @@ +