Wenn man eine Lösung sucht, um einen Reverse Proxy oder Load Balancer aufzusetzen, ohne dafür aber eine sehr lange Konfigurationsdatei schreiben und warten zu müssen, dann ist die Kombination von Traefik mit Consul vielleicht die richtige Lösung.
Traefik implementiert einen Zugriff auf Consul, um von dort seine Konfigurationsdaten zu beziehen. Dies erlaubt einem sämtliche Konfigurationen im Key/Value-Store von Consul abzulegen und Traefik nimmt diese Änderungen wahr und lädt sich selbstständig neu.
logLevel = "INFO"
defaultEntryPoints = ["http", "https"]
[consul]
endpoint = "${consul_backend}"
watch = true
prefix = "${prefix}"
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[acme]
email = "it-is-me@example.com"
storage = "${prefix}/acme/account"
entryPoint = "https"
caServer = "https://acme-staging-v02.api.letsencrypt.org/directory"
[acme.httpChallenge]
entryPoint = "http"
[acme.dnsChallenge]
provider = "dnsimple"
delayBeforeCheck = 0
[[acme.domains]]
main = "*.example.com"
sans = ["example.com"]
In unserem Beispiel verwenden wir nun ein Docker whoami
Image, um die Skalierung und das Loadbalancing im Hintergrund zu veranschaulichen.
Außerden werden wir das ganze auch mittels Terraform ausrollen. Zu allererst definiert man die Variablen, um auf den Hosts dann die Docker Container zu starten. Die beiden Hosts wurden so provisioniert, dass der Docker-Port im lokalen Netz verfügbar ist.
variable "traefik_version" {
default = "v1.7.11"
}
variable "consul_version" {
default = "1.5"
}
variable "traefik_host" {
default = "10.0.0.10"
}
variable "backend_host" {
default = "10.10.0.20"
}
variable "prefix" {
default = "traefik"
}
variable "consul_backend" {
default = "10.10.0.20:8500"
}
variable "domain" {
default = "example.com"
}
Anschließend muss Consul ausgerollt werden:
provider "docker" {
host = "tcp://${var.backend_host}:2376/"
}
resource "docker_image" "consul" {
name = "consul:${var.consul_version}"
}
resource "docker_container" "consul" {
image = "${docker_image.consul.latest}"
name = "consul"
must_run = true
restart = "always"
ports {
internal = 8500
external = 8500
protocol = "tcp"
}
}
Auf diesem Host wird dann auch das whoami
Image laufen:
resource "docker_image" "whoami" {
name = "jwilder/whoami"
}
resource "docker_container" "whoami" {
image = "${docker_image.whoami.latest}"
name = "whoami"
must_run = true
restart = "always"
ports {
internal = 8000
external = 8000
protocol = "tcp"
}
}
Zum Schluss muss Traefik auf seinem eigenen Host definiert und ausgerollt werden:
provider "docker" {
host = "tcp://${var.traefik_host}:2376/"
}
data "template_file" "traefik_config" {
template = "${file("templates/traefik.tpl")}"
vars {
consul_backend = "${var.consul_backend}"
prefix = "${var.prefix}"
}
}
resource "docker_container" "traefik" {
depends_on = ["consul_keys.whoami"]
image = "${docker_image.traefik.latest}"
name = "traefik_proxy"
must_run = true
restart = "always"
ports {
internal = 80
external = 80
protocol = "tcp"
}
ports {
internal = 443
external = 443
protocol = "tcp"
}
upload {
content = "${join(",", data.template_file.traefik_config.*.rendered)}"
file = "/etc/traefik/traefik.toml"
}
volumes {
host_path = "/srv/traefik"
container_path = "/srv/"
read_only = false
}
}
Damit nun alle Services miteinander reden können, muss diese Information in Consul abgelegt werden. Auch hier wird Terraform dafür verwendet, diese Daten anzulegen und zu warten:
resource "consul_keys" "whoami" {
key {
path = "${var.prefix}/acme/account/"
value = ""
}
key {
path = "${var.prefix}/backends/whoami/servers/server1/url"
value = "http://${var.backend_host}:8000/"
}
key {
path = "${var.prefix}/backends/whoami/servers/server1/weight"
value = "10"
}
key {
path = "${var.prefix}/frontends/frontend1/backend"
value = "whoami"
}
key {
path = "${var.prefix}/frontends/frontend1/routes/whoami/rule"
value = "Host: whoami.${var.domain}"
}
}
Nach diesem Konfigurationschritt lädt Traefik seine Konfiguation neu. Ein Zugriff auf