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 front-end services that can handle these requests. This guide will show you one such example using Apache web server.
»Reference Material
»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 job type 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 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 Terraform environment to provision a sandbox environment. This tutorial will assume a cluster with one server node and three client nodes.
Note: This tutorial is for demo purposes and only assumes a single server node. Please consult the reference architecture for production configuration.
»Steps
»Step 1: Create a Job for Fabio
Create a job for Fabio and name it fabio.nomad
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 ensures that Fabio is run on all clients. Note that
the network_mode
option is set to host
so that Fabio can communicate with
Consul on the client nodes.
»Step 2: Run the Fabio Job
We can now register our Fabio job:
$ 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. This is because there are no routes built yet and is
expected.
»Step 3: Create a Job for Apache Web Server
Create a job for Apache and name it webserver.nomad
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-
. Fabio looks for
services with that special tag and builds routes for them. In this case, we are
registering the path '/' with Fabio. This 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:
$ 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).
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 Behind 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.
The AWS documentation 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
forward traffic to the web interface at port 9998
, you should be able to
access that as well.