Seite wählen

NETWAYS Blog

Ein Ausblick – Traefik Provider OpenStack

Bei unseren Online-Trainings von NETWAYS, werden jedem einzelnen Teilnehmer eine oder mehrere explizite VMs zur Verfügung gestellt, welche in der OpenStack-Umgebung von NWS gehostet werden. Hierbei benötigen die VMs jeweils öffentliche IPs, welche leider nicht unendlich zu Verfügung stehen. Aus dieser Prämisse heraus entstand die Idee, einen sog. reverse Proxy zu benutzen, welcher Anfragen von Clients an Webserver weiterleitet – in diesem Fall an die entsprechende VM.

Das Problem an dieser Stelle ist, dass es für Traefik noch keinen Provider für OpenStack gibt. Daher wurde ein experimenteller openstack-provider entwickelt, welchen ich hier kurz vorstelle.

 

Funktionsweise des openstack-providers

Der openstack-traefik-provider benutzt den http-provider von Traefik um die VMs/Instanzen innerhalb eines OpenStack-Projektes zu suchen/finden. Damit Traefik die Informationen über die Instanzen erhält, wird ein OpenStack-Go-Client innerhalb eines Docker-Containers gestartet, welcher anschließend über die URL http://openstack:8080/traefik (diese URL kann im Code selbst angepasst werden), alle Informationen des Projektes über ein HTTP-Response zur Verfügung stellt. Traefik selbst pollt alle 10 sek. von dieser Adresse, um die Routen, Middlewares, etc. zu aktualisieren.

 

Beispielhafte Konfiguration

Jeglicher HTTPS-Traffic soll am Proxy terminiert werden, sodass innerhalb des internen Netzwerks HTTP benutzt wird:

main.go
[...]
settings := discovery.DefaultSettings
	settings.DefaultRule = "Host(`{{ .Name }}.trainig.netways.de`)"
	settings.DefaultEnable = true
	settings.AddressType = "floating"
	settings.DefaultLabels = map[string]string{
		// HTTP
		"traefik.http.routers.{{ .Name }}-http.service":                   "{{ .Name }}-http",
		"traefik.http.routers.{{ .Name }}-http.rule":                      "Host(`{{ .Name }}.trainig.netways.de`)",
		"traefik.http.routers.{{ .Name }}-http.entrypoints":               "http",
		"traefik.http.services.{{ .Name }}-http.loadBalancer.server.port": "80",
		"traefik.http.routers.{{ .Name }}-http.middlewares":               "http-to-https",

		// HTTPS
		"traefik.http.routers.{{ .Name }}-https.service":                   "{{ .Name }}-https",
		"traefik.http.routers.{{ .Name }}-https.rule":                      "Host(`{{ .Name }}.trainig.netways.de`)",
		"traefik.http.routers.{{ .Name }}-https.entrypoints":               "https",
		"traefik.http.services.{{ .Name }}-https.loadBalancer.server.port": "80",
		"traefik.http.routers.{{ .Name }}-https.tls":                       "true",

		// Redirect HTTP to HTTPS
		"traefik.http.middlewares.http-to-https.redirectscheme.scheme":    "https",
		"traefik.http.middlewares.http-to-https.redirectscheme.permanent": "true",
	}
[...]

 

Anschließend muss über den Befehl docker-compose up der Docker-Container mit der neuen Konfiguration gestartet werden und die Routen + Middleware sollten im Frontend zu sehen sein:

 

Da das Projekt sich derzeit noch in Entwicklung befindet, würde ich mich über Vorschläge, PullRequests oder Kritik von der Open Source Community sehr freuen!

Sobald das Projekt abgeschlossen ist, werde ich auch davon berichten!

 

Let's Encrypt HTTP Proxy: Another approach

Yes, we all know that providing microservices with Docker is a very wicked thing. Easy to use and of course there is a Docker image available for almost every application you need. The next step to master is how we can expose this service to the public. It seems that this is where most people struggle. Browsing the web (generally GitHub) for HTTP proxies you’ll find an incredible number of images, people build to fit into their environments. Especially when it comes to implement a Let’s Encrypt / SNI encryption service. Because it raises the same questions every time: Is this really the definitely right way to do this? Wrap custom API’s around conventional products like web servers and proxies, inject megabytes of JSON (or YAML or TOML) through environment variables and build scrips to convert this into the product specific configuration language? Always my bad conscience tapped on the door while I did every time.
Some weeks ago, I stumble upon Træfik which is obviously not a new Tool album but a HTTP proxy server which has everything a highly dynamic Docker platform needs to expose its services and includes Let’s Encrypt silently – Such a thing doesn’t exist you say?
A brief summary:

Træfik is a single binary daemon, written in Go, lightweight and can be used in virtually any modern environment. Configuration is done by choosing a backend you have. This could be an orchestrator like Swarm or Kubernetes but you can also use a more “open” approach, like etcd, REST API’s or file backend (backends can be mixed of course). For example, if you are using plain Docker, or Docker Compose, Træfik uses Docker object labels to configures services. A simple configuration looks like this:

[docker]
endpoint = "unix:///var/run/docker.sock"
# endpoint = "tcp://127.0.0.1:2375"
domain = "docker.localhost"
watch = true

Træfik constantly watch for changes in your running Docker container and automatically adds backends to its configuration. Docker container itself only needs labels like this (configured as Docker Compose in this example):

whoami:
image: emilevauge/whoami # A container that exposes an API to show its IP address
labels:
- "traefik.frontend.rule=Host:whoami.docker.localhost"

The clue is, that you can configure everything you’ll need that is often pretty complex in conventional products. This is for Example multiple domains, headers for API’s, redirects, permissions, container which exposes multiple ports and interfaces and so on.
How you succeed with the configuration can be validated in a frontend which is included in Træfik.

However, the best thing everybody was waiting is the seamless Let’s Encrypt integration which can be achieved with this snippet:

[acme]
email = "test@traefik.io"
storage = "acme.json"
entryPoint = "https"
[acme.httpChallenge]
entryPoint = "http"
# [[acme.domains]]
# main = "local1.com"
# sans = ["test1.local1.com", "test2.local1.com"]
# [[acme.domains]]
# main = "local2.com"
# [[acme.domains]]
# main = "*.local3.com"
# sans = ["local3.com", "test1.test1.local3.com"]

Træfik will create the certificates automatically. Of course, you have a lot of conveniences here too, like wildcard certificates with DNS verification though different DNS API providers and stuff like that.
To conclude that above statements, it exists a thing which can meet the demands for a simple, apified reverse proxy we need in a dockerized world. Just give it a try and see how easy microservices – especially TLS-encrypted – can be.

Marius Hein
Marius Hein
Head of IT Service Management

Marius Hein ist schon seit 2003 bei NETWAYS. Er hat hier seine Ausbildung zum Fachinformatiker absolviert und viele Jahre in der Softwareentwicklung gearbeitet. Mittlerweile ist er Herr über die interne IT und als Leiter von ITSM zuständig für die technische Schnittmenge der Abteilungen der NETWAYS Gruppe. Wenn er nicht gerade IPv6 IPSec Tunnel bohrt, sitzt er daheim am Schlagzeug und treibt seine Nachbarn in den Wahnsinn.