Kubernetes & Traefik 101— When Simplicity Matters
Tags: microservices, traefik, kubernetes, opensource
Published: 2018-08-08 17:33:08

---
title: Kubernetes & Traefik 101— When Simplicity Matters
published: true
tags: microservices,traefik,kubernetes,opensource
canonical_url: https://medium.com/@geraldcroes/kubernetes-traefik-101-when-simplicity-matters-957eeede2cf8
---

#### The tutorial that would have spared me hours of struggling with my keyboard

![](https://cdn-images-1.medium.com/max/1024/1*8jEVYbc3AEcLcr4pQjmkJg.jpeg)

Have you ever been in a situation that started with …

> _Someone at work:_ “Look, it’s super simple, let me explain …”

… that continued with …

> [ … agony of arcane jargon …]

> _Same enthusiastic colleague:_ “See, did you get it?”

> _You (poker face):_ “Sure, gotcha, aha, no problem, whoo, super simple indeed, aha … ”

… but that ended up with you sneaking into the bathroom to babble chunks of keywords you barely remember.

> “Ok Google, what is a cluster of Ingress in a cube of nodes? … Please please please help me.”

Nope. Hasn’t happened to me. Not even once. No Sir!

But let’s _pretend_ that it did happen (_hypothetically_) several years ago, and that all the articles I stumbled upon during my research were made of such cryptic symbols that tears started to come out of my eyes (and they weren’t tears of joy).

> I said: Let’s pretend.

So based on this _fictional_ situation, let’s try to write the easiest tutorial that involves setting up Traefik as an Ingress Controller for Kubernetes. (And I promise: I will explain everything that is not obvious.)

_You can skip this part if you’re familiar with Kubernetes._

### What You Need to Know about Kubernetes

#### Kubernetes, as in Cluster

Kubernetes is a cluster technology. It means that you will see a cluster of computers as one entity. You will not deploy an application on a specific computer, but _somewhere_ in the cluster, and it’s Kubernetes’s job to determine the computer that best matches the requirements of your application.

![](https://cdn-images-1.medium.com/max/1024/1*qQ-j7P3WoogJgyZlDzxDSQ.png)<figcaption>Machines in the cluster can have different characteristics</figcaption>

#### Nodes

Each computer in the cluster is called a node. Eventually, the nodes will host your applications. The nodes can be spread throughout the world in different data centers, and it’s Kubernetes’s job to make them communicate as if they were neighbors.

![](https://cdn-images-1.medium.com/max/1024/1*2j_S_hK2c9Xc2Sgd6fPQCA.png)<figcaption>Nodes are machines in the cluster</figcaption>

#### Containers

I guess that you are already familiar with containers. Just in case you’re not, they used to be the next step of virtualization, and today they are just that: the de-facto standard for virtualization. Instead of configuring a machine to host your application, you have your application wrapped into a container (along with everything your application needs — OS, libraries, dependencies, …) and deployed on a machine that hosts the container engine which is in charge of actually running the containers.

_Containers technically don’t belong to Kubernetes; they’re just one of the tools of the trade._

![](https://cdn-images-1.medium.com/max/1024/1*9ODdq3k6CY-xKX5ryRgLtw.png)<figcaption>Container embed the required technologies</figcaption>

Basically, Kubernetes sees containers like in the following diagram:

![](https://cdn-images-1.medium.com/max/1024/1*oHF7k5YxREmWZ3HrWF9E3g.png)<figcaption>The container engine is responsible for handling the underlying technologies needed in your containers</figcaption>

#### Pods

Because Kubernetes loves layers, Kubernetes adds the notion of Pods around your containers. Pods are the smallest unit you will eventually deploy to the cluster. A single Pod can hold multiple containers, but for the sake of simplicity let’s say for now that a single Pod will host a single container.

So, in a Kubernetes world, a Pod is the new name for an instance of your application, an instance of your service. Pods will be hosted on the Nodes, and it’s Kubernetes’s job to determine which Node will host which Pod.

![](https://cdn-images-1.medium.com/max/1024/1*JEN9ir7oKMz7EfBtzN5nIQ.png)<figcaption>If a Pod consists of multiple containers, they will share the same resources / network</figcaption>

#### Deployments

Here comes the fun part! Deployments are requirements you give to Kubernetes regarding your applications (your Pods). Basically, with deployments you tell Kubernetes:

> Hey Kube, always keep 5 instances (or replicas) of these Pods running — always.

It’s Kubernetes’s job to ensure that your cluster will host 5 replicas of your Pods at any given time.

![](https://cdn-images-1.medium.com/max/1024/1*nXocwqHpCScrQZjgMapeqQ.png)<figcaption>Kubernetes is responsible for deploying the pods to the right places</figcaption>

#### Services

Oh, yet another fun concept …

Pods’ lifecycle are erratic; they come and go by Kubernetes’ will.

> Not healthy? Killed.

> Not in the right place? Cloned, and killed.

_(No, you definitely don’t want to be ruled by Kube!)_

So how can you send a request to your application if you can’t know for sure where it lives? The answer lies in services.

Services define sets of your _deployed_ Pods, so you can send a request to “whichever available Pod of your application type.”

![](https://cdn-images-1.medium.com/max/1024/1*7ylCISKaMMfnqK8lOJ41PA.png)<figcaption>When requesting your application, you don’t care about its location or about which pod answers the request</figcaption>

#### Ingress

So we have Pods in our cluster.

We have Services so we can talk to them _from within_ our cluster. (Technically, there are ways to make services available from the outside, but we’ll purposefully skip that part for now.)

Now, we’d like to expose our Services to the internet so customers can access our products.

Ingress objects are the rules that define the routes that should exist.

![](https://cdn-images-1.medium.com/max/1024/1*ZBjq0otb_77wzQc8Tz6BEw.png)<figcaption>Ingress objects are the rules that define the routes to our services</figcaption>

#### Ingress Controller

Now that you have defined the rules to access your services from the outside, all you need is a component that routes the incoming requests according to the rules … and these components are called Ingress Controllers!

And since this is the topic of this article — Traefik is a great Ingress Controller for Kubernetes.

![](https://cdn-images-1.medium.com/max/1024/1*evU3Y7fXZtrIYPmCuoKpmQ.png)

### What You Need to Know about Traefik

- It rocks.
- It’s easy to use.
- It’s production ready and used by big companies.
- It works with every major cluster technology that exists.
- It’s [open source](https://github.com/containous/traefik).
- It’s super popular; more than 150M downloads at the time of writing.

… oh? Is my opinion biased? Well, maybe … but all of the above is true!

### Let’s Start Putting Everything Together!

_This is the part where we actually start to deploy services into a Kube cluster and configure Traefik as an Ingress Controller._

#### Prerequisite

You have access to a Kubernetes cluster, and you have [_kubectl_](https://kubernetes.io/docs/reference/kubectl/overview/) that points to that cluster.

_Just so you know, here I’m using Kubernetes embedded in_ [_Docker for Mac_](https://docs.docker.com/docker-for-mac/)_._

#### What We’ll Do

- We’ll use a pre-made container — containous/whoami — capable of telling you where it is hosted and what it receives when you call it. (Sorry to disappoint you, but I can confirm we won’t build the new killer app here^^)
- We’ll define two different Pods, a _whoami_ and a _whoareyou_ that will use this container.
- We’ll create a deployment to ask Kubernetes to deploy 1 replica of _whoami_ and 2 replicas of _whoareyou_ (because we care more about others than we care about ourselves … how considerate!).
- We’ll define two services, one for each of our Pods.
- We’ll define Ingress objects to define the routes to our services.
- We’ll set up Traefik as our Ingress Controller.

And because we love diagrams, here is the picture:

![](https://cdn-images-1.medium.com/max/1024/1*1KSzpNWahErAqMi4p93JUw.png)

#### Setting Up Traefik Using Helm

[Helm](https://helm.sh) is a package manager for Kube and, for me, the most convenient way to configure Traefik without messing it up. (If you haven’t installed Helm yet, [doing so is quite easy](https://docs.helm.sh/using_helm/) and fits in two command lines, e.g. _brew install kubernetes-helm,_ and _helm init_.)

![](https://cdn-images-1.medium.com/max/200/1*9LF-XeJP9m7K9VU-bYs6fQ.png)

To set up Traefik, copy / paste the following command line:

```
helm install stable/traefik --set dashboard.enabled=true,dashboard.domain=dashboard.localhost
```

In the above command line, we enabled the dashboard (_dashboard.enabled=true_) and made it available on [http://dashboard.localhost](http://dashboard.localhost) (_dashboard.domain=localhost.domain_).

The output of the helm install command line will look like:

![](https://cdn-images-1.medium.com/max/1024/1*eoA_R3WTiHnqgK2dO5olyg.png)

In my case, _EXTERNAL-IP_ is already available and is _localhost_.

_EXTERNAL-IP_ is the address of the door to my cluster; it is the public address of the Ingress Controller (Traefik).

And as we said before, we should be able to access the dashboard right away!

![](https://cdn-images-1.medium.com/max/1024/1*Rlzppvn7upe9u4z3A3DWbQ.png)<figcaption>The dashboard shows that Traefik has detected a service (called dashboard.localhost, on the right) and has created a route to it (host:dashboard.localhost, on the left)</figcaption>

#### Let’s Deploy Some Pods!

Now it’s time to deploy our first WhoAmI!

As a reminder, we want one Pod with one container (_containous/whoami_).

![](https://cdn-images-1.medium.com/max/352/1*SooVurEI3Qc3gGftJDmvLg.png)<figcaption>Quite a straightforward Pod</figcaption>

Kubernetes uses yaml files to describe its objects, so we will describe our deployment using one.

{% gist https://gist.github.com/geraldcroes/19873ea100eeea907624cb3e157e17b5 %}

To provide some explanations about the file content:

- We define a “deployment” (_kind: Deployment_)
- The name of the object is “whoami-deployment” (_name: whoami-deployment_)
- We want one replica (_replicas: 1_)
- It will deploy pods that have the label app:whoami (_selector: matchLabels: app:whoami_)
- Then we define the pods (_template: …_)
- The Pods will have the whoami label (_metadata:labels:app:whoami_)
- The Pods will host a container using the image containous/whoami (_image:containous/whoami_)

_📗 Note: You can read more about_ [_deployments in the Kubernetes documentation._](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)

Now that we have described our deployment, we ask Kubernetes to take the file into account with the following command:

```
kubectl apply -f whoami-deployment.yml
```

And let’s check what happened with:

```
kubectl get all
```

![](https://cdn-images-1.medium.com/max/1024/1*RUrE9jytRgRmNsDs7Je0qQ.png)<figcaption>The whoami-deployment has been created</figcaption>

#### Let’s Define a Service!

If you remember correctly, we need services so we can talk to “any available Pod” of a given kind.

![](https://cdn-images-1.medium.com/max/352/1*8-km33qGON5F5V_VAh_FiQ.png)<figcaption>We need the whoami service to refer to our whoami pods</figcaption>

Once again, we need to define the object:

{% gist https://gist.github.com/geraldcroes/36de6ce6a027ac574bff8ef169f34fed %}

Some explanations:

- We define a “service” (_kind: Service_)
- The name of the object is “whoami-service” (_name: whoami-service_)
- It will listen on port 80 and redirect on port 80 (_ports: ..._)
- The target Pods have the label whoami (_selector:app:whoami_)

_📗 Note: You can read more about_ [_services in the Kubernetes documentation._](https://kubernetes.io/docs/tutorials/services/)

Now that we have described our service, we ask Kubernetes to take the file into account with the following command:

```
kubectl apply -f whoami-service.yml
```

And let’s check what happened with:

```
kubectl get all
```

![](https://cdn-images-1.medium.com/max/1024/1*tRRXmBiEvje61-lAwEHaog.png)<figcaption>Our service is available!</figcaption>

#### Ingress

At last, we’re about to define the rules so that the world can benefit from our (kick-ass) service.

![](https://cdn-images-1.medium.com/max/1024/1*waj-Cd_SWuHsDuNBkIkoHg.png)

You know the drill, let’s write the YML file to describe the new object:

{% gist https://gist.github.com/geraldcroes/5758d32f2074bee94940fe4a4d2f2880 %}

Some explanations:

- We define an “ingress” (_kind: Ingress_)
- The name of the object is “whoami-ingress” (_name: whoami-ingress_)
- The class of the Ingress is “traefik” (kubernetes.io/ingress.class:traefik). This one is important because it tells Traefik to take this Ingress into account.
- We add rules for this Ingress (rules: …)
- We want requests to host whoami.localhost (host:whoami.localhost) to be redirected to the service whoami-service (serviceName:whoami-service) using http (servicePort: http).

_📗 Note: You can read more about_ [_Ingress in the Kubernetes documentation._](https://kubernetes.io/docs/concepts/services-networking/ingress/)

Now that we have described our Ingress, we ask Kubernetes to take the file into account with the following (same old) command:

```
kubectl apply -f whoami-ingress.yml
```

And now, since Traefik is our Ingress Controller, let’s see if something has changed in the dashboard …

![](https://cdn-images-1.medium.com/max/1024/1*NqhyH_EdNcIGuECaof77pw.png)<figcaption>Traefik has automatically detected the new Ingress!</figcaption>

That’s it, no reload, no additional configuration file (there were enough). Traefik has updated its configuration and is now able to handle the route whoami.localhost!

Let’s check …

![](https://cdn-images-1.medium.com/max/1024/1*dBrGPJvzExImc57VkSyuuA.png)<figcaption>Traefik redirects the requests as expected</figcaption>

Yes, our service is useful, but its UI could use a bit of love ❤️

Here, we confirm that Traefik _is_ our Ingress Controller and that it is ready to bring its features to your services!

### May I Ask For Load Balancing in Action?

Earlier, we talked about a WhoAreYou deployment with 2 replicas.

Let’s do it in just one file :-)

{% gist https://gist.github.com/geraldcroes/98253cce7bed32ae864a35a40af3bd41 %}

There is not much to say here, except that this time we have 2 replicas … (replicas: 2)

So let’s ask Kubernetes to apply our new configuration file.

```
kubectl apply -f whoareyou.yml
```

And let’s go right away to Traefik’s dashboard.

And voilà!

![](https://cdn-images-1.medium.com/max/1024/1*QZrJV0Tf_vbsIJgFXbNpLg.png)<figcaption>Traefik detects the new Ingress and the two available Pods in the Service</figcaption>

![](https://cdn-images-1.medium.com/max/1024/1*tgngYz5SDJdc8QHpHq9Gvw.png)<figcaption>First request, one of the Pod replies</figcaption>

![](https://cdn-images-1.medium.com/max/1024/1*V1gUfSO7dmlVcNE3kjc-fQ.png)<figcaption>Second request, the other Pod replies</figcaption>

### Conclusion

If I had wanted to write an article that dealt with “just” configuring Traefik as an Ingress Controller for Kubernetes, well, it would have fit in one line:

```
helm install stable/traefik
```

Because it’s actually the only configuration operation that we’ve needed in the article. The rest is just explanations and demos.

Yes, this step was indeed as simple as that!

### Go Further With Traefik!

Now that you know how to configure Traefik, it might be a good time to delve into its documentation and learn about its [other features](https://docs.traefik.io/#features) (auto HTTPS, Let’s Encrypt automatic support, circuit breaker, load balancing, retry, websocket, HTTP2, GRPC, metrics, etc.)

[Containous](https://containo.us) is the company that helps Træfik be the successful open-source project it is (and that provides commercial support for Traefik).

Follow [me](https://twitter.com/geraldcroes) & [Træfik](https://twitter.com/traefikproxy) on Twitter :-)

Your comments & questions are welcome!

You can clone the files from my github repository [geraldcroes/kubernetes-traefik-article](https://github.com/geraldcroes/kubernetes-traefik-article).