How to Configure Traefik for Routing Applications in Kubernetes
By Anish Nath, Alibaba Cloud Tech Share Author. Tech Share is Alibaba Cloud’s incentive program to encourage the sharing of technical knowledge and best practices within the cloud community.
This tutorial explains how to use Traefik as an Ingress controller for a Kubernetes cluster. We will be covering:
- Setting up Traefik
- Traefik Dashboard configuration
- Define Name based Routing
- Define Path Based routing
Before You Begin
You only need to have running Kubernetes cluster. In case you are new to Alibaba Cloud, you can get $10 worth in credit through my referral link to get started. Then, head on to this tutorial to learn how you can set up a fully functioning Kubernetes cluster.
Exposing Services to External Clients
In Kubernetes, you can make service accessible externally through NodePort, Loadbalancer, and Ingress Resource. This tutorial is dedicated to using Ingress Resource through the Traefik Kubernetes Ingress Controller
About Traefik
Traefik is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy. Traefik integrates with your existing infrastructure components and configures itself automatically and dynamically. Pointing Traefik at your orchestrator should be the only configuration step you need.

Traefik Ingresses operate at the application layer of the network stack (HTTP) and can provide features such as cookie-based session affinity and the like, which services can’t.
Setting Up Traefik
Helm is a tool for managing Kubernetes charts. Charts are packages of pre-configured Kubernetes resources. Before setting up Traefik, we need to setup helm first install helm and then configure it on the k8s cluster. You can ignore these steps and jump directly to helm Traefik installation if the helm is already configured.
Download the latest version of helm
root@kube-master:# gunzip helm-v2.8.1-linux-amd64.tar.gz**
root@kube-master:# tar -xvf helm-v2.8.1-linux-amd64.tar**
root@kube-master:# sudo mv l*/helm /usr/local/bin/.**
Then, initialize helm to both set up the local environment and to install the server portion, Tiller, on your cluster
root@kube-master:# helm init
root@kube-master:# kubectl create serviceaccount --namespace kube-system tiller
root@kube-master:# kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
root@kube-master:# kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
Make sure Tiller, on your cluster is up and running.
root@kube-master:# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-78fcdf6894-jvmlb 1/1 Running 0 1h
coredns-78fcdf6894-xstbn 1/1 Running 0 1h
etcd-kube-master 1/1 Running 0 1h
kube-apiserver-kube-master 1/1 Running 0 1h
kube-controller-manager-kube-master 1/1 Running 0 1h
kube-flannel-ds-5gzn9 1/1 Running 0 1h
kube-flannel-ds-tlc8j 1/1 Running 0 1h
kube-proxy-kl4fg 1/1 Running 0 1h
kube-proxy-krt6n 1/1 Running 0 1h
kube-scheduler-kube-master 1/1 Running 0 1h
tiller-deploy-85744d9bfb-wh98g 1/1 Running 0 1h
Installing Traefik Using Helm
The below command will setup the traefik ingress in the kube-system namespace, and setup necessary RBAC in k8 cluster to operated ingress correctly and also setup the traefik dashboard, which is accessible through http://dashboard.traefik
root@kube-master:# helm install stable/traefik --name traefik --set dashboard.enabled=true,dashboard.domain=dashboard.traefik,rbac.enabled=true --namespace kube-system
This command produces a lot of output, so let’s take it one step at a time. First, we get information about the release that’s been deployed
NAME: traefik
LAST DEPLOYED: Wed Jan 23 11:00:50 2019
NAMESPACE: kube-system
STATUS: DEPLOYED
Next, we get the resources that were actually deployed by the stable/traefik chart
RESOURCES:
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
traefik-8dc967bf9-lxrzs 0/1 Pending 0 3s==> v1/ConfigMap
NAME DATA AGE
traefik 1 3s==> v1/ServiceAccount
NAME SECRETS AGE
traefik 1 3s==> v1/ClusterRole
NAME AGE
traefik 3s==> v1/ClusterRoleBinding
NAME AGE
traefik 3s==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
traefik-dashboard ClusterIP 10.102.119.154 <none> 80/TCP 3s
traefik LoadBalancer 10.108.205.70 <pending> 80:31346/TCP,443:31530/TCP 3s==> v1/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
traefik 1 1 1 0 3s==> v1beta1/Ingress
NAME HOSTS ADDRESS PORTS AGE
traefik-dashboard dashboard.traefik 80 3s
Well if everything goes well then, Check the traefik pods are running in the kube-system namespace
root@kube-master:/home/ansible# kubectl get svc traefik --namespace kube-system -w
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
traefik LoadBalancer 10.105.34.152 172.16.2.13 80:30734/TCP,443:32254/TCP 19m
Once ‘EXTERNAL-IP’ is no longer ‘’: it’s time to access your traefik dashboard, open the url http://dashboard.traefik

In the Traefik dashboard and you should see a frontend for dashboard.traefik host. Along with a backend listing for dashboard.traefik service with a server set up for each pod.
Upto this point we have successfully installed and configured traefik, now let’s define the routing (name based and path based ) of your application.
Launching Demo Application
We are going here to setup three sample nginx cheese web application, the docker images are located here .
- Docker image: errm/cheese:wensleydale
- Docker image: errm/cheese:cheddar
- Docker image: errm/cheese:stilton

Name Based Routing
The Name-Based Routing performs routing by name and support routing HTTP traffic to multiple host names at the same IP address but different domain names. Let’s start by launching the pods for the cheese websites.
Deployment of Cheese Web Application
The YAML file for the cheese application
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: stilton
labels:
app: cheese
cheese: stilton
spec:
replicas: 2
selector:
matchLabels:
app: cheese
task: stilton
template:
metadata:
labels:
app: cheese
task: stilton
version: v0.0.1
spec:
containers:
- name: cheese
image: errm/cheese:stilton
resources:
requests:
cpu: 100m
memory: 50Mi
limits:
cpu: 100m
memory: 50Mi
ports:
- containerPort: 80
To provide some explanations about the file content:
- We define a deployment (
kind: Deployment
) - The name of the object is “stilton” (
name: stilton
) - We want one replica (
replicas: 2
) - It will deploy pods that have the label app:cheese (
selector: matchLabels: app:cheese
) - Then we define the pods (
template: ...
) - The Pods will have the cheese label (
metadata:labels:app:cheese
) - The Pods will host a container using the image tag errm/cheese:stilton (
image: errm/cheese:stilton
) - The same deployment is repeated for cheddar and wensleydale
Now provision these nginx cheese application.
root@kube-master:# kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-deployments.yaml
deployment.extensions/stilton created
deployment.extensions/cheddar created
deployment.extensions/wensleydale created
Make sure all the cheese deployment pods are up and running
root@kube-master:/home/ansible# kubectl get pods
NAME READY STATUS RESTARTS AGE
cheddar-6c895c7cc7-2qztp 1/1 Running 0 7m
cheddar-6c895c7cc7-mzq9v 1/1 Running 0 7m
stilton-7989d7c86f-62wrt 1/1 Running 0 7m
stilton-7989d7c86f-fjttz 1/1 Running 0 7m
wensleydale-58784fc6f7-f8szd 1/1 Running 0 7m
wensleydale-58784fc6f7-prb8z 1/1 Running 0 7m
Service Cheese Web Application
Next we need to setup a Service for each of the cheese pods.
root@kube-master:# kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-services.yaml
service/stilton created
service/cheddar created
service/wensleydale created
All the
root@kube-master:/home/ansible# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cheddar ClusterIP 10.108.200.238 <none> 80/TCP 30s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 1h
stilton ClusterIP 10.102.20.8 <none> 80/TCP 30s
wensleydale ClusterIP 10.109.58.21 <none> 80/TCP 30s
At this point, we have deployment and Service ready in the K8 cluster, and we’re about to define the ingress rules so that the world can eat the required service.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: cheese
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: stilton.minikube
http:
paths:
- path: /
backend:
serviceName: stilton
servicePort: http
- host: cheddar.minikube
http:
paths:
- path: /
backend:
serviceName: cheddar
servicePort: http
- host: wensleydale.minikube
http:
paths:
- path: /
backend:
serviceName: wensleydale
servicePort: http
To provide some explanations about the file content:
- We define a Ingress (
kind: Ingress
) - The name of the object is “cheese” (
name: cheese
) - Then we define the rules (
rules: ...
) - For each service there is hostname defined for example the hostname stilton.minikube is mapped to stilton service.
- The rules are repeated for each service.
- Let’s apply this rule in k8 cluster
root@kube-master:/home/ansible# kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-ingress.yaml
ingress.extensions/cheese created
Verify the Ingress, all the hosts can be accessed with the ingress port 80
root@kube-master:/home/ansible# kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
cheese stilton.minikube,cheddar.minikube,wensleydale.minikube 80 31s
Now visit the Traefik dashboard and you should see a frontend for each host. Along with a backend listing for each service with a server set up for each pod.
Open the web browser and start eating your favorite cheese


PATH Based Routing
Path based routing differ from Name based routing in a sense, we don’t have multiple domains names, all the URI is distinguished and routed from the PATH prefix under a single domain, for example the above cheese application can be access through the single URI.

Let’s create the PATH base routing for the cheese application
root@kube-master:/home/ansible# kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheeses-ingress.yaml
ingress.extensions/cheeses created
View the Ingress, as you can notices the newly created ingress cheeses can be accessed through the hostname cheeses.minikube
root@kube-master:/home/ansible# kubectl get ingressNAME HOSTS ADDRESS PORTS AGE
cheese stilton.minikube,cheddar.minikube,wensleydale.minikube 80 13m
cheeses cheeses.minikube 80 1m
You should now be able to visit the websites in your browser.
Final Notes
- The above traefik installation is not secure, and shouldn’t be used for production, for production setting refer the helm stable/traefik charts, for example the below chart value will set traefik in SSL mode, and set the BASIC AUTH enabled
helm install stable/traefik --name traefik --set dashboard.enabled=true,dashboard.domain=dashboard.traefik,rbac.enabled=true,dashboard.auth.basic.traefik='$apr1$vUmd7ddA$CoklUZpHBbRzvnZUz6eFY.',ssl.enabled=true,ssl.enforced=true --namespace kube-system
- It is advisable to install the traefik in the kube-system namespace
- Always measure your resource needs, and adjust requests and limits accordingly.
Reference:
https://www.alibabacloud.com/blog/594720?spm=a2c41.12820772.0.0