Advanced HTTP/S Routing with Traefik on HashiCorp stack
By: Habibie Faried
Tags: DevOps, Consul, Traefik, Hashicorp, Infrastructure

Hey Guys~~

This time, I would like to introduce traefik integration with Consul Catalog to provide load balancing http/s, as well as automated https using Let’s Encrypt.

Let’s Go.

Run traefik as nomad job

job "traefik" {

region = "global"

datacenters = ["dc1"]

type = "system" group "traefik" {

task "traefik" {

driver = "docker" config {

image = "traefik:v2.2"

network_mode = "host" volumes = [

"local/traefik.toml:/etc/traefik/traefik.toml",

]

} template {

data = <<EOF

[entryPoints]

[entryPoints.http]

address = ":80"

[entryPoints.traefik]

address = ":8081"

[entryPoints.websecure]

address = ":443" [certificatesResolvers.myresolver.acme]

email = "uptoyou@gmail.com"

storage = "acme.json"

[certificatesResolvers.myresolver.acme.httpChallenge]

# used during the challenge

entryPoint = "http" [api]

dashboard = true

insecure = true # Enable Consul Catalog configuration backend.

[providers.consulCatalog]

prefix = "traefik"

exposedByDefault = false [providers.consulCatalog.endpoint]

address = "127.0.0.1:8500"

scheme = "http"

EOF destination = "local/traefik.toml"

} resources {

cpu = 100

memory = 128 network {

port "http" {

static = 80

} port "https" {

static = 443

} port "api" {

static = 8081

}

}

} service {

name = "traefik" check {

name = "alive"

type = "tcp"

port = "http"

interval = "10s"

timeout = "2s"

}

}

}

}

}

This job definition will require port 80, 443, 8081 (for traefik UI). It’s up to you on how you want to run it. In this definition, it will run as a service. Which means, it will be run on all nomad workers. If you don’t want to do this or having some particular different design, then adjust that accordingly.

If it run successfully, then you can access the traefik UI on port 8081, on one of nomad worker machine

If you take a look again on the job, you will see that `providers.consulCatalog.endpoint` is pointed to local consul agent (127.0.0.1:8500). Yes, consul agent must be installed on all nomad servers and workers. And I think that is the best practice that Hashicorp defined, am I right?

If you are confused to do so, then maybe this article https://habibiefaried.medium.com/setup-ha-nomad-consul-using-aws-auto-scaling-group-spot-fleet-8dcf71af6727 can help you.

Run web container

Let’s run one of the web container. Pay attention to the tag on job definition below.

job "demo-webapp2" {

datacenters = ["dc1"]

group "demo" {

count = 3

network {

port "demowebapp2" { to = 80 }

}

task "server" {

driver = "docker"

config {

image = "mendhak/http-https-echo"

ports = ["demowebapp2"]

}

}

service {

name = "demo-webapp2"

port = "demowebapp2"

tags = [

"traefik.enable=true",

"traefik.http.routers.demowebapp2-https.tls=true",

"traefik.http.routers.demowebapp2-https.rule=Host(`demo-webapp2.nomad.habibiefaried.com`)",

"traefik.http.routers.demowebapp2-https.tls.certresolver=myresolver",

"traefik.http.routers.demowebapp2-https.tls.domains[0].main=demo-webapp2.nomad.habibiefaried.com",

"traefik.http.routers.demowebapp2-http.rule=Host(`demo-webapp2.nomad.habibiefaried.com`)",

]

check {

port = "demowebapp2"

type = "http"

path = "/"

interval = "2s"

timeout = "2s"

}

}

}

}

Let me explain one by one of its tag

traefik.enable=true. Indicates traefik to look this job definition’s tag. This must be written.

2. traefik.http.routers.demowebapp2-https.tls=true. Add routers namely demowebapp2-https, indicates traefik to provide TLS service to this specific router.

3. traefik.http.routers.demowebapp2-https.tls.domains[0].main=demo-webapp2.nomad.habibiefaried.com. Add the domain demo-webapp2.nomad.habibiefaried.com, this domain will be registered by traefik to ACME Let’s Encrypt.

4. traefik.http.routers.<router name>.rule=Host(`demo-webapp2.nomad.habibiefaried.com`). This <router name> will accept the domain as its virtual host domain. So, this container will be accessible from this domain.

Let’s see the result

On nomad

All instances are registed with consul, alongside with its tag info

2 routers, one with TLS, another one without it

The endpoint

So, the conclusion is…

Traefik is more like nginx but with advanced features, for example, able to route the traffic based on the tags that defined in Consul.

Another features

There are another features that you might be interested. Take a look at the tags given to you for each feature.

Route with prefix

"traefik.enable=true",

"traefik.http.routers.demoprefix-http.rule=Host(`demo-prefix.nomad.habibiefaried.com`) && PathPrefix(`/test`)",

"traefik.http.middlewares.demoprefix-http.stripprefix.prefixes=/test",

"traefik.http.routers.demoprefix-http.middlewares=demoprefix-http@consulcatalog",

Basic Authentication

"traefik.enable=true",

"traefik.http.routers.demoauth-http.rule=Host(`demo-auth.nomad.habibiefaried.com`)",

"traefik.http.middlewares.demoauth-http.basicauth.users=admin:$apr1$ilatsgyn$bkm6zIYXeRnizLOBJ44R31",

"traefik.http.routers.demoauth-http.middlewares=demoauth-http@consulcatalog",

Take a note that, http.basicauth.users must be apache compliant hash. It can be generated using htpasswd command

Put those tags on your container, and see. Hit me on email or telegram if there’s something wrong going on. I will be more than happy to help my fellow hashicorp users here :D

Thanks!