Back in 2015, the first version of the by now famous edge router Traefik saw the light of day. Lots and lots of work has been put into the application, making it one of the most used proxies in the whole containerized infrastructures landscape. Recently, they announced a huge overhaul and refactoring to make Traefik future-ready. In this blog post series, we will showcase some of the new features in Traefik 2.0, highlight changes and see what the future may look like.
As written in their announcement, Traefik 2.0 brings in a lot of new features, along with internal changes.
- configuration & new routing rule syntax
- Kubernetes CRD
- TCP Support
- Cross Provider Support
But without further ado, let’s start.
Configuration in Traefik 2.0
The whole configuration structure itself changed. A simple v1 configuration would have looked like this:
checkNewVersion = true [entryPoints] [entryPoints.http] address = ":80" [file] [backends] [backends.backend1] # ... [frontends] [frontends.frontend1] # ...
A simple v2, would look like this
[Global] checkNewVersion = true [entrypoints] [entrypoints.http] address = ":80" [providers] [providers.file] [http] [http.routers] [http.routers.my-router] rule = "Path(`/test`)" service = "whoami" entrypoint=["http"] [http.services] [http.services.whoami.loadbalancer] [[http.services.whoami.loadbalancer.servers]] url = "http://localhost:8080"
As you can see, there is no root level configuration any more. All root-related configuration has moved below the Global section, which makes it more readable.
Also, a provider is now prefixed and enabled with
providers.Name. In that example, it’s therefore the file provider with a basic entrypoint, a default router and service. More about that vocabulary (router and service) and also an introduction to the middleware can be found here .
Given that new structure of routers, middleware and services, it’s also possible to reuse middleware across routers and unify behavior.
[http] [http.routers] [http.routers.whoami-router] rule = "Host(`whoami.mydomain.com`)" service = "whoami" entrypoint=["http"] middlewares = ["test-user"] [http.routers.whoami2-router] rule = "Host(`whoami2.mydomain.com`)" service = "whoami" entrypoint=["http"] middlewares = ["test-user"] [http.middlewares] [http.middlewares.test-user.basicauth] users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"] [http.services] [http.services.whoami.loadbalancer] [[http.services.whoami.loadbalancer.servers]] url = "http://localhost:8080"
In that example, the test-user middleware, which adds basic authentication, is shared and reused across two routers. Therefore, it could be used for 2 different services, which in the end reduces configuration complexity as there is no need to configure the same option multiple times.
New routing rule syntax
Previously, routing rules were a bit fuzzy to implement. Especially if you wanted to implement rules which were more difficult than matching a given hostname. The new rule syntax in Traefik 2.0 gives you an expressive syntax with well-known DSL keywords such as AND, OR or even parenthesis
First, let’s match a simple request against www.mydomain.com/myapp.
The first line will always be an example from v1 and the second from v2
rule = Host: `www.mydomain.com`, PathPrefix:`/myapp` rule = Host: (`www.mydomain.com`) && PathPrefix:(`/myapp`)
That’s not that huge of a difference. Now, let’s check for two different hosts in a logical or.
rule = Host: `www.mydomain.com`, Host: `www.myseconddomain.com`, PathPrefix:`/myapp` rule = (Host: (`www.mydomain.com`) || Host: (`www.myseconddomain.com`) && PathPrefix:(`/myapp`)
That’s a difference already. With v2, you can also combine a lot more items:
rule = (Method(`PUT`) || (Method(`POST`) && Query(`action`, `update`))) && Host('api.domain')
The new configuration options and especially the new rule syntax in Traefik 2.0 provide a lot more flexibility – especially in terms of how you want to route traffic to your applications or in reducing complexity, as you don't have to implement the same action multiple times.
In the next post, we will have a brief look at the new Kubernetes CRD and how the handling will change compared to the "old" Ingress style configuration.