Traefik and External-dns: Naming Magic


I have spoken in a previous story about setting up Traefik on Kubernetes to act as an ingress controller. Now let’s image you have a cluster that you want your developers to use. They are good guys (like all Developers right?) and have designed some nice Helm charts that allow them to spin up a new web site from Jenkins using your shiny ingress controller. But hang on why am I getting 404?

Well Traefik normally uses the value of the Host HTTP header to know which backend to route traffic two. But hang on everything points at the same Load Balancer and therefore the same DNS?

NOPE!(Copyright The Oatmeal)

DNS allows you to overload an IP or set of IP’s with multiple names which for us is confusing as heck, but for Traefik it’s all in a days work. Here is an example. First we setup our Load Balancer point to our Traefik Daemonset and create the alias traefik.uat.example.com. Next we create two more aliases called fry.example.com and leela.example.com also pointing to the same load balancer. Now as far as DNS is concerned all is great because all three address point to the same Load Balancer.

So you hit one of those URL’s it goes to the Load Balancer, which in turn sends the request to a nodes Traefik pod, which inspects the Host Header and selects the correct backend. Groovy right kids?

But you shout from back “the title says dynamic? Why have I just had to create manually the two domains?”. Yes your right, I am sorry….not. For you have fallen into by obvious and somewhat awkward trap!

External DNS Logo

This is where the totally awesome external-dns project comes in. Come on it has a logo for a start! Who doesn’t love a logo? Even security issues get “branded” these days, anyway I digress. Put simply external-dns allows you to update a cloud provider DNS of your choice using nothing more than the magic of annotations. I won’t go though how to set it up as there is already doc for that from the developers which is really good. From here on in we don’t care which DNS provider your using, we only care about how we interface with external-dns. Yay for abstraction!

Now the issue here is that out the box external-dns doesn’t support Traefik which is both mildly annoying, but also frustrating as the documentation on how to get it working is worse than a Ikea manual is a lost ancient language. But there is hope! The solution is really easy, like super easy.

The first part of the story is that you need to add an annotation to the Traefik service that the load balancer will point at.

external-dns.alpha.kubernetes.io/hostname: traefik.example.com

This creates a target in external-dns that we can then point out ingress at. Now the DNS entry that the annotation points to needs to exist as external-dns won’t create it. So now on the ingress you can add the following annotations:

kubernetes.io/ingress.class: traefik
external-dns.alpha.kubernetes.io/target: traefik.example.com

The above annotation tells external-dns to create a record to point at the target. Now how simple is that?

So now when you create a new ingress rule with the annotations set external-dns is able to create a record and boom your site is now live.

Another handy feature of external-dns is the assume role parameter. As the name suggests, in an AWS environment you can pass the full ARN on a role that external-dns will assume. This has a couple of uses, the first being a way of delegating the access via a separate role rather than say using the node IAM role to improve the audit trail. Secondly this can be used to allow external-dns to assume a role in another account so that it update records in hosted zone there.

So you can see here that external-dns is super handy and when combined with Traefik (or any other ingress controller) you can start to develop very dynamic deployments that allow for higher levels of automation.

See also