The Wait Is Over!

When we started our journey toward 2.0, we had high expectations (since you had high expectations), and huddled around the whiteboard.

We designed Version 2 as if there were no constraints: we forgot our codebase, put aside technical challenges, and developed a new configuration structure that would welcome everything we had ever dreamed of for Traefik.

We forgot what was impossible so we could build it!

A year later, we proudly present to you Traefik 2.0. Make sure you grab your cup of coffee/cup of tea before going further because this is probably the biggest new features list we’ve ever had to write!

TCP Support with SNI Routing & Multi-Protocol Ports

We talked about this flagship feature in the 2.0 alpha announcement, but since it was feature request #10, we thought we would dedicate some time to discussing this key element in a world of new possibilities.

Let’s see a sample configuration — using the newly supported YAML format — that routes requests to a database:

tcp: routers: to-database: entrypoints: - database-entrypoint rule: HostSNI(`*`) service: database-service services: database-service: loadBalancer: servers: - address: xx.xx.xx.xx:xx

In the example above, every request ending on database-entrypoint will be routed to our database-service .

Over TLS, Traefik routes TCP

requests based on the SNI

In the following example, Traefik routes requests to two databases based on the SNI (Server Name Indication):

tcp: routers: to-db-1: entrypoints: - web-secure rule: "HostSNI(`db1.domain`)" service: "db1" tls: {} to-db-2: entrypoints: - web-secure rule: "HostSNI(`db2.domain`)" service: "db2" tls: {}

HTTP & TCP on the same port?

Yes, there is Traefik for that!

If you ever want to have the same entrypoint get both HTTP and TCP requests, know that Traefik will handle it perfectly!

tcp: routers: to-db-1: entrypoints: - web-secure rule: "HostSNI(`db1.domain`)" service: "db-1" tls: {} http: routers: to-db1-dashboard: entrypoints: - web-secure rule: "Host(`dashboard.db1.domain`)" service: "db1-dashboard" tls: {}

In the above example, HTTP requests on dashboard.db1.domain will be routed to the database dashboard service, and TCP requests on db1.domain will be routed to the database.

Fully Customize Your Routes with Middleware

Traefik 2.0 introduces middleware: a common banner for features that tweak requests before/after routing them to their destinations.

You can declare Middleware and reuse them on as

many routers as you like.

Want to see how to configure them? Let’s declare a BasicAuth middleware to control access to our service! (this time using TOML)

# Declaring a basicauth middleware with two users [http.middlewares.test-auth.basicAuth] users = ["user1:hashed", "user2:hashed"] # Applying the middleware to our router [http.routers.my-router.to-service] rule = "host(`my-protected.domain`)" middlewares = ["test-auth"] service = "service1"

A Chain to Bind Them All

If you have a classic combination you often use together, you can declare chains, and reuse them over and over. What’s even better for our Kubernetes users, you can use Traefik’s new CRD (Custom Resource Definition) for a crystal clear configuration that doesn’t involve intricate annotations. (You can find more information on the IngressRoute object in our documentation.)

apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: test namespace: default spec: entryPoints: - web routes: - match: Host(`mydomain`) kind: Rule services: - name: whoami port: 80 middlewares: - name: secured --- apiVersion: traefik.containo.us/v1alpha1 kind: Middleware metadata: name: secured spec: chain: middlewares: - name: https-only - name: known-ips - name: auth-users --- apiVersion: traefik.containo.us/v1alpha1 kind: Middleware metadata: name: auth-users spec: basicAuth: secret: secretUsers #yes! Compatible with K8S secrets --- apiVersion: traefik.containo.us/v1alpha1 kind: Middleware metadata: name: https-only spec: redirectScheme: scheme: https --- apiVersion: traefik.containo.us/v1alpha1 kind: Middleware metadata: name: known-ips spec: ipWhiteList: sourceRange: - 192.168.1.7 - 127.0.0.1/32

At release, Traefik comes with many pieces of middleware: path manipulation, several authentication mechanisms, buffering, circuit breaker, retry, compression, error handling, headers, IP whitelisting, rate limiting, redirections, and more.

Also, we’ve re-architectured the code to make it easier for contributors to provide additional pieces of middleware, and I’m sure we’ll find a way to do even better.

A New Dashboard & WebUI

Our goal with the new WebUI was to show users what was happening on their cluster at a glance. We also wanted to display what features they can enable.

Since the flow has changed, we wanted to display every path that leads to services, with every configuration option.

Canary Deployments with Service Load Balancers

Another long-awaited feature — canary deployments, A/B testing — makes its way into Traefik 2.0 in the form of Service Load Balancers.

Service Load Balancers can be seen as virtual services that are responsible for forwarding the request to the actual services.

Let’s take a classic scenario where you have an existing route to an API:

http: routers: my-route: rule: "Host(`my.domain`)" service: my-api-v1 services: my-api-v1: loadBalancer: servers: - url: "http://private-ip-server-1/"

Now you want to deploy a new version of this service, but would like to deploy it progressively, let’s say approximately a third of the requests. What you’ll do is deploy the new service, with its own ID (here it’s my-api-v2 ).

http: services: my-api-v2: loadBalancer: servers: - url: "http://private-ip-server-2/"

Then, instead of pointing directly to this new version, you’ll first define a Service Load Balancer (in the example canary-api ) and define the proportion for each version (with the weight option).

http: services: canary-api: weighted: services: - name: my-api-v1 weight: 3 - name: my-api-v2 weight: 1

Finally, point to this canary-api service from your router.

http: routers: my-route: rule: "Host(`my.domain`)" service: canary-api

Later, you’ll be able to update the weight without having to redeploy your actual services. You’ll also be able to scale them without any impact on the canary deployment itself.

Mirroring with Service Load Balancers

Canary deployments aren’t the only tricks available in the service family. Traefik 2.0 introduces Mirroring Services — a way to duplicate the incoming request and send it to different services at the same time. The mirror will get a given percentage of requests, and its answers will be ignored.

[http.services.mirrored-api] [http.services.mirrored-api.mirroring] service = "api" [[http.services.mirrored-api.mirroring.mirrors]] name = "api-v2" percent = 10 [http.services.api] [http.services.api.loadBalancer] [[http.services.api.loadBalancer.servers]] url = "http://private-ip-server-1/" [http.services.api-v2] [http.services.api-v2.loadBalancer] [[http.services.api-v2.loadBalancer.servers]] url = "http://private-ip-server-2/"

In the above example, we’re sending 10% of the requests to the mirror.

And Much, Much More!

Traefik 2.0 introduces a syntax ( @provider ) to allow users to declare elements (middleware, services, routers) in a provider and to reference them from an other one. It provides an easier way to configure CORS headers, embeds a redesigned constraint management to better control services you want to expose, and improves the default rule generation for a quick and easy way to define routes for containers.

On top of many enhancements, the API now embeds status information for your middleware, services, routers, and reports errors to help you identify and fix problems.

The polished configuration options ensure that configuring Traefik is always achieved the same way whether expressed with TOML, YAML, labels, or keys, and the revamped documentation includes examples for every syntax.

You can define TLS termination separately on each router, configure TLS passthrough, use the new CertResolver to benefit from different challenges for certificate generation (yes, it’s now multiple-DNS-providers-proof!), and dynamically generate wildcard certificates.

Router rules now use a go-like syntax with operators and parenthesis for powerful and readable combinations.

The list goes on and on with bug fixes and other significant tweaks!

Migrating From 1.x

With so many new features, bug fixes, and enhancements, Traefik 2.0 might ask you to re-think the way you used to route your requests. In order to facilitate the transition and help you leverage the power of these new options, we initiated a migration guide that goes through every change we made.

For our Kubernetes user-base, we’ve also written a migration tool to help you convert your Ingress objects to the new IngressRoute format. (This migration tool will also help all users convert their acme.json file.)

All this is designed for the thousands of people already using Traefik.

Behind the Curtain

Traefik 2.0 is not the only thing that has improved! By the time we released 2.0, we launched TraefikEE, Yaegi, Maesh, and you can bet we’ll keep going further. We also constantly monitor our processes and tools. We’ve launched a Community Forum to foster better communication amongst users, introduced a monthly journal, and scheduled Traefik Online Meetups to promote the community talent.

Next Steps

More than anything, this release shows the importance of the community. Every feature that has been discussed today was born from a user asking for a new feature, reporting a bug, or just asking for “better.”

Traefik 1.X has been downloaded more than a billion times, and we hope to double that number with Traefik 2.X.

❤️ Thank you for your support!❤️

… and keep raising your voice for the (many) version(s) to come!

P.S. — Stay tuned! There is so much to show you with this new version that our developer team is preparing an Online Meetup for you. :-)