Hello everyone, this article I mentioned a little bit about Traefik – an opensource software that I have introduced on Viblo. At that time, the latest version of Traefik was version v1.7
. After a long time of development, in October 2019, Traefik was released v2 version with a lot of changes and improvements. Let us also explore whether Traefik v2 is better than this article!
Traefik v1.7 – Score through
A bit back and forth! Traefik is a reverse-proxy, friendly to the micro services architecture – making it easier to deploy system services. Used in combination with Docker, K8s … Traefik configuration to publish a web service with Docker through docker label so deployment is quite simple:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <span class="token key atrule">version</span> <span class="token punctuation">:</span> <span class="token string">'3.7'</span> <span class="token key atrule">services</span> <span class="token punctuation">:</span> <span class="token key atrule">traefik</span> <span class="token punctuation">:</span> <span class="token key atrule">image</span> <span class="token punctuation">:</span> traefik <span class="token punctuation">:</span> v1.7 <span class="token key atrule">command</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> <span class="token punctuation">-</span> <span class="token punctuation">-</span> logLevel=INFO <span class="token punctuation">-</span> <span class="token punctuation">-</span> <span class="token punctuation">-</span> api <span class="token punctuation">-</span> <span class="token punctuation">-</span> <span class="token punctuation">-</span> docker <span class="token key atrule">volumes</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> /var/run/docker.sock <span class="token punctuation">:</span> /var/run/docker.sock <span class="token punctuation">:</span> ro <span class="token key atrule">ports</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> <span class="token datetime number">80:80</span> <span class="token key atrule">labels</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> traefik.port=8080 <span class="token punctuation">-</span> traefik.frontend.rule=Host <span class="token punctuation">:</span> traefik.lc <span class="token key atrule">ctf</span> <span class="token punctuation">:</span> <span class="token key atrule">image</span> <span class="token punctuation">:</span> containous/whoami <span class="token punctuation">:</span> v1.4.0 <span class="token key atrule">labels</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> traefik.frontend.rule=Host <span class="token punctuation">:</span> ctf.viblo.lc <span class="token key atrule">code</span> <span class="token punctuation">:</span> <span class="token key atrule">image</span> <span class="token punctuation">:</span> containous/whoami <span class="token punctuation">:</span> v1.4.0 <span class="token key atrule">labels</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> traefik.frontend.rule=Host <span class="token punctuation">:</span> code.viblo.lc |
You can build a simple stack above:
1 2 | docker-compose -f traefik-v1.yml up -d |
In Traefik v1.7, we know there are three main concepts: Entrypoint
, Frontend
and Backend
:
- Entrypoint: Are connection points between Traefik and “the world” such as entrypoint name, how many listen ports, ssl or not? …
- Frontend: Contains rules declarations for determining how to route to backend properly.
- Backend: Mapping corresponds to the service, supports loadbalancing.
Traefik v2.x
Traefik v2 now has support for static configuration files in TOML format, and also adds YAML. If you are a fan of YAML then congratulations!
In the next section we will explore new things on v2 and migrate the small stack above to v2.
Provider
Although Traefik v1 also supports a lot of Infrastructure such as: Docker, Kubernetes, Amazon ECS … but the configurations are still quite discrete. In v2, it was all referred to as a provider . The idea is that Traefik will query the provider’s APIs to find information for routing. Supported providers include:
Provider | Type | Configuration Type |
---|---|---|
Docker | Orchestrator | Label |
Kubernetes | Orchestrator | Custom Resource |
Consul Catalog | Orchestrator | Label |
Marathon | Orchestrator | Label |
Rancher | Orchestrator | Label |
File | Manual | TOML / YAML format |
In this article, I use Traefik + Docker so I will use the provider, Docker. In addition, some providers are not yet supported but will probably be provided in the near future:
# | Provider |
---|---|
first | Azure Service Fabric |
2 | BoltDB |
3 | Consul |
4 | DynamoDB |
5 | ECS |
6 | Etcd |
7 | Eureka |
8 | Mesos |
9 | Zookeeper |
Therefore, please consider carefully if you plan to upgrade Traefik to v2!
Frontend, Backend are dead?
In addition to the above Provider, Traefik also rewrote and reorganized a number of components including Frontend
and Backend
– They were all dead . And the replacement will be new components including routers, services and middleware.
- Router: Similar to
Frontend
in v1 helps detect whether the request will need to navigate to which “Service” each router will target a corresponding service. - Service: takes the same role as
Backend
in v1, only way to incomming the request will reach the actual service as desired by theRouter
. And it still comes with the same load balancer configuration as v1. - Middleware: The same role in Laravel: v It is used to refine requests before the router sends them to the service, or before the response from the services returned to the client.
Because of this big change, all the configs for routing have been changed. Details of the rules / matcher will be changed at https://docs.traefik.io/routing/routers/#rule . Some matcher changes to check basic requests include:
Rule | description |
---|---|
Headers (key , value ) | If the header contains key=value |
HeadersRegexp (key , regexp ) | If the header has a key with value satisfying regex regexp |
Host (domain-1 , …) | Request to one of domain-1 , … |
HostRegexp (traefik.io , {subdomain: [az] +}. Traefik.io, ...) | The request to the domain is satisfied by the regex |
Method (GET, ...) | Check the HTTP method |
Path (/ path, / articles / {category} / {id: [0-9] +} , ...) | Checks if the unarchived URL matches /path or regex |
PathPrefix (/ products /, / articles / {category} / {id: [0-9] +}) | Check URLs with paths starting with /products/ or regex |
Query (foo = bar, bar = baz) | If the request has a matching query string ?foo=bar or ?bar=baz |
Traefik v2 "makeover"
Also because of the refactoring as above, v2 has a lot of breaking change with v1. Now I will convert Traefik v1 configuration to v2 to see if it is any different!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <span class="token key atrule">version</span> <span class="token punctuation">:</span> <span class="token string">'3.7'</span> <span class="token key atrule">services</span> <span class="token punctuation">:</span> <span class="token key atrule">traefik</span> <span class="token punctuation">:</span> <span class="token key atrule">image</span> <span class="token punctuation">:</span> traefik <span class="token punctuation">:</span> v2.1 <span class="token key atrule">command</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> <span class="token punctuation">-</span> <span class="token punctuation">-</span> log.level=INFO <span class="token punctuation">-</span> <span class="token punctuation">-</span> <span class="token punctuation">-</span> api.insecure=true <span class="token punctuation">-</span> <span class="token punctuation">-</span> <span class="token punctuation">-</span> providers.docker <span class="token key atrule">volumes</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> /var/run/docker.sock <span class="token punctuation">:</span> /var/run/docker.sock <span class="token punctuation">:</span> ro <span class="token key atrule">ports</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> <span class="token datetime number">80:80</span> <span class="token key atrule">labels</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> traefik.http.routers.rule=Host(`traefik.lc`) <span class="token key atrule">ctf</span> <span class="token punctuation">:</span> <span class="token key atrule">image</span> <span class="token punctuation">:</span> containous/whoami <span class="token punctuation">:</span> v1.4.0 <span class="token key atrule">labels</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> traefik.http.routers.ctf.rule=Host(`ctf.viblo.lc`) <span class="token key atrule">code</span> <span class="token punctuation">:</span> <span class="token key atrule">image</span> <span class="token punctuation">:</span> containous/whoami <span class="token punctuation">:</span> v1.4.0 <span class="token key atrule">labels</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> traefik.http.routers.code.rule=Host(`code.viblo.lc`) |
Test:
1 2 | docker-compose -f traefik-v2.yml up -d |
Instead of using the label traefik.frontend.rule=Host:ctf.viblo.lc
, we will now use traefik.http.routers.ctf.rule=Host(
ctf.viblo.lc
`) . It is a breaking change in routing. We can see the new labels at the Docker Provider and Routing with Docker pages.
Some commonly used docker labels remain the same as v1:
- traefik.enable = true // override again config
exposedByDefault
- traefik.docker.network = traefik-net // specify docker network
In addition, Traefik v2 has also changed with a new modern coat, clear layout and eye-catching:
Traefik Dashboard
Traefik Routers
Traefik Service Detail, load lablancer with 5 servers
HTTPS redirection
Config to redirect from HTTP to HTTPS is removed from entryPoints
. Instead, it will be applied in the Router
using one of the middleware: RedirectRegex or RedirectScheme . Example of using RedirectScheme with docker:
1 2 3 4 | <span class="token comment"># Redirect to https</span> <span class="token key atrule">labels</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> <span class="token string">"traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https"</span> |
ACME (Let’s Encrypt)
ACME is a config to use Let’s Encrypt to automatically generate a cert key for https free. This version will replace config key acme
with certificatesResolvers
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # static configuration defaultEntryPoints = ["web-secure","web"] [entryPoints.web] address = ":80" [entryPoints.web.redirect] entryPoint = "webs" [entryPoints.web-secure] address = ":443" [entryPoints.https.tls] [acme] email = " <a class="__cf_email__" href="/cdn-cgi/l/email-protection" data-cfemail="dea7b1abacf3bbb3bfb7b2f3b6bbacbb9eb3a7f3bfa9bbadb1b3bbf3bfaeaef0b1acb9">[email protected]</a> " storage = "acme.json" entryPoint = "web-secure" onHostRule = true [acme.httpChallenge] entryPoint = "web" |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # static configuration [entryPoints] [entryPoints.web] address = ":80" [entryPoints.web-secure] address = ":443" [certificatesResolvers.sample.acme] email = " <a class="__cf_email__" href="/cdn-cgi/l/email-protection" data-cfemail="522b3d27207f373f333b3e122b3d27207f363d3f333b3c7c3d2035">[email protected]</a> " storage = "acme.json" [certificatesResolvers.sample.acme.httpChallenge] # used during the challenge entryPoint = "web" |
Traefik Logs
There is a small change to the logs configuration of Traefik. Note, there are many types of logs configuration such as Traefik log, access log, metric logs … and this part I am referring to is Traefik log. In version 2, all of the configs for the traefik log are now in [log]
; logLevel
will shorten to level
, which looks like this:
1 2 3 4 5 6 7 | logLevel = "INFO" [traefikLog] filePath = "/path/to/file" format = "json" |
1 2 3 4 5 6 | [log] level = "INFO" filePath = "/path/to/file" format = "json" |
Tracing
Traefik still implement complies with OpenTracing
. V2 will support more distributed tracing systems:
Distributed System | Version 1 | Version 2 |
---|---|---|
Jaeger | ||
Zipkin | ||
Datadog | ||
Instana | ||
Haystack |
Along with that is a small change in the config. The backend
key will no longer be available on version 2:
1 2 3 4 5 6 7 8 9 10 | # static configuration [tracing] backend = "jaeger" servicename = "tracing" [tracing.jaeger] samplingParam = 1.0 samplingServerURL = "http://12.0.0.1:5778/sampling" samplingType = "const" localAgentHostPort = "12.0.0.1:6831" |
1 2 3 4 5 6 7 8 9 | # static configuration [tracing] servicename = "tracing" [tracing.jaeger] samplingParam = 1.0 samplingServerURL = "http://12.0.0.1:5778/sampling" samplingType = "const" localAgentHostPort = "12.0.0.1:6831" |
Metrics
Metrics in version 2 will support services. In addition, Traefik still supports the same metric for entry points as version 1. As for config, it is still the same as v1.
1 2 3 4 5 | # static configuration [metrics.prometheus] buckets = [0.1,0.3,1.2,5.0] entryPoint = "metrics" |
Version 2 still supports 4 systems including:
Backend System | Version 1 | Version 2 |
---|---|---|
Datadog | ||
InfluxDB | ||
Prometheus | ||
StatsD |
No more config at Root Level
If you notice the config changes above, you will realize that the root level key
have been moved into a certain group. Actually, this version removed all the root level
keys in the config file. Such as:
1 2 3 4 5 6 7 8 9 10 11 12 13 | # static configuration checkNewVersion = false sendAnonymousUsage = true logLevel = "DEBUG" insecureSkipVerify = true rootCAs = [ "/mycert.cert" ] maxIdleConnsPerHost = 200 providersThrottleDuration = "2s" AllowMinWeightZero = true debug = true defaultEntryPoints = ["web", "web-secure"] keepTrailingSlash = false |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # static configuration [global] checkNewVersion = true sendAnonymousUsage = true [log] level = "DEBUG" [serversTransport] insecureSkipVerify = true rootCAs = [ "/mycert.cert" ] maxIdleConnsPerHost = 42 [providers] providersThrottleDuration = 42 |