Traefik 2.0 – Configuration & new routing rule syntax

No Comments

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.

Parts

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')

Conclusion

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.

Avatar

Manuel joined codecentric AG back in September 2018 as an IT Consultant. His special interest is in deploying applications scalable by using cloud and container technologies. Language-wise, his favorites are go, nodejs and java including spring boot. Also, he’s a maintainer of the Open Source Proxy Traefik.

Comment

Your email address will not be published. Required fields are marked *