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

Exposing Services to External Clients

About Traefik

Image for post
Image for post

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

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

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

Image for post
Image for post

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

  1. Docker image: errm/cheese:wensleydale
  2. Docker image: errm/cheese:cheddar
  3. Docker image: errm/cheese:stilton
Image for post
Image for post

Name Based Routing

Deployment of Cheese Web 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

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

Image for post
Image for post
Image for post
Image for post

PATH Based Routing

Image for post
Image for post

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

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:

Written by

Follow me to keep abreast with the latest technology news, industry insights, and developer trends.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store