Traefik and HashiCorp Consul with terraform


Bicycle

Traefik and Hashicorp Consul with Terraform

Are you looking for a solution to configure a reverse proxy or load balancer without the need to step into a big long configuration file? Maybe Traefik in combination with Consul is the right solution for you.

Traefik has implemented a backend to Consul. This allows you to configure the reverse proxy configuration of frontend and backend in the key value store and Traefik will automatically reload itself according to this configuration changes.

 1logLevel = "INFO"
 2defaultEntryPoints = ["http", "https"]
 3
 4[consul]
 5  endpoint = "${consul_backend}"
 6  watch = true
 7  prefix = "${prefix}"
 8
 9[entryPoints]
10  [entryPoints.http]
11    address = ":80"
12  [entryPoints.https]
13    address = ":443"
14    [entryPoints.https.tls]
15
16[acme]
17  email = "it-is-me@example.com"
18  storage = "${prefix}/acme/account"
19  entryPoint = "https"
20  caServer = "https://acme-staging-v02.api.letsencrypt.org/directory"
21  [acme.httpChallenge]
22    entryPoint = "http"
23  [acme.dnsChallenge]
24    provider = "dnsimple"
25    delayBeforeCheck = 0
26[[acme.domains]]
27    main = "*.example.com"
28    sans = ["example.com"]

In our example we gonna use a docker whoami with scaling to reflect running a load balanced service in the background.

Also we gonna use terraform to rollout this configuration ;-) So first we define all our variables of docker container versions and hosts for docker. Those 2 hosts are already prepared to share the docker port in our local network.

 1variable "traefik_version" {
 2  default = "v1.7.11"
 3}
 4variable "consul_version" {
 5  default = "1.5"
 6}
 7
 8variable "traefik_host" {
 9  default = "10.0.0.10"
10}
11variable "backend_host" {
12  default = "10.10.0.20"
13}
14
15variable "prefix" {
16  default = "traefik"
17}
18
19variable "consul_backend" {
20  default = "10.10.0.20:8500"
21}
22
23variable "domain" {
24  default = "example.com"
25}

Next we deploy consul on the background host:

 1
 2provider "docker" {
 3  host = "tcp://${var.backend_host}:2376/"
 4}
 5
 6resource "docker_image" "consul" {
 7  name = "consul:${var.consul_version}"
 8}
 9resource "docker_container" "consul" {
10
11  image    = "${docker_image.consul.latest}"
12  name     = "consul"
13  must_run = true
14  restart  = "always"
15
16  ports {
17    internal = 8500
18    external = 8500
19    protocol = "tcp"
20  }
21}

And also deploy our whoami image on this host:

 1resource "docker_image" "whoami" {
 2  name = "jwilder/whoami"
 3}
 4resource "docker_container" "whoami" {
 5
 6  image    = "${docker_image.whoami.latest}"
 7  name     = "whoami"
 8  must_run = true
 9  restart  = "always"
10
11  ports {
12    internal = 8000
13    external = 8000
14    protocol = "tcp"
15  }
16}

Then we deploy our traefik proxy

 1provider "docker" {
 2  host = "tcp://${var.traefik_host}:2376/"
 3}
 4
 5data "template_file" "traefik_config" {
 6  template = "${file("templates/traefik.tpl")}"
 7
 8  vars {
 9    consul_backend = "${var.consul_backend}"
10    prefix         = "${var.prefix}"
11  }
12}
13
14resource "docker_container" "traefik" {
15  depends_on = ["consul_keys.whoami"]
16
17  image    = "${docker_image.traefik.latest}"
18  name     = "traefik_proxy"
19  must_run = true
20  restart  = "always"
21
22  ports {
23    internal = 80
24    external = 80
25    protocol = "tcp"
26  }
27
28  ports {
29    internal = 443
30    external = 443
31    protocol = "tcp"
32  }
33
34  upload {
35    content = "${join(",", data.template_file.traefik_config.*.rendered)}"
36    file    = "/etc/traefik/traefik.toml"
37  }
38
39  volumes {
40    host_path      = "/srv/traefik"
41    container_path = "/srv/"
42    read_only      = false
43  }
44}

Now all services are up and running but Traefik does not know where the backend is running. So we have to put this information into Consul:

 1resource "consul_keys" "whoami" {
 2  key {
 3    path  = "${var.prefix}/acme/account/"
 4    value = ""
 5  }
 6
 7  key {
 8    path  = "${var.prefix}/backends/whoami/servers/server1/url"
 9    value = "http://${var.backend_host}:8000/"
10  }
11
12  key {
13    path  = "${var.prefix}/backends/whoami/servers/server1/weight"
14    value = "10"
15  }
16
17  key {
18    path  = "${var.prefix}/frontends/frontend1/backend"
19    value = "whoami"
20  }
21
22  key {
23    path  = "${var.prefix}/frontends/frontend1/routes/whoami/rule"
24    value = "Host: whoami.${var.domain}"
25  }
26}

After this configuration step Traefik will reload its configuration and when pointing whoami.example.com to the IP of traefik whoami should respond with its id.

Go Back explore our courses

We are here for you

You are interested in our courses or you simply have a question that needs answering? You can contact us at anytime! We will do our best to answer all your questions.

Contact us