2016-05-06 10:34:30 +00:00
# Kubernetes Ingress Controller
2017-02-03 16:47:48 +00:00
This guide explains how to use Træfɪ k as an Ingress controller in a Kubernetes cluster.
2016-05-06 10:34:30 +00:00
If you are not familiar with Ingresses in Kubernetes you might want to read the [Kubernetes user guide ](http://kubernetes.io/docs/user-guide/ingress/ )
The config files used in this guide can be found in the [examples directory ](https://github.com/containous/traefik/tree/master/examples/k8s )
## Prerequisites
1. A working Kubernetes cluster. If you want to follow along with this guide, you should setup [minikube ](http://kubernetes.io/docs/getting-started-guides/minikube/ )
on your machine, as it is the quickest way to get a local Kubernetes cluster setup for experimentation and development.
2. The `kubectl` binary should be [installed on your workstation ](http://kubernetes.io/docs/getting-started-guides/minikube/#download-kubectl ).
2017-03-31 07:57:06 +00:00
## Deploy Træfik using a Deployment object
2016-05-06 10:34:30 +00:00
We are going to deploy Træfɪ k with a
[Deployment ](http://kubernetes.io/docs/user-guide/deployments/ ), as this will
allow you to easily roll out config changes or update the image.
```yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: traefik-ingress-controller
namespace: kube-system
labels:
k8s-app: traefik-ingress-lb
spec:
replicas: 1
selector:
matchLabels:
k8s-app: traefik-ingress-lb
template:
metadata:
labels:
k8s-app: traefik-ingress-lb
name: traefik-ingress-lb
spec:
terminationGracePeriodSeconds: 60
containers:
2016-11-10 18:14:53 +00:00
- image: traefik
2016-05-06 10:34:30 +00:00
name: traefik-ingress-lb
resources:
limits:
cpu: 200m
memory: 30Mi
requests:
cpu: 100m
memory: 20Mi
ports:
- containerPort: 80
hostPort: 80
- containerPort: 8080
args:
- --web
- --kubernetes
```
[examples/k8s/traefik.yaml ](https://github.com/containous/traefik/tree/master/examples/k8s/traefik.yaml )
> notice that we binding port 80 on the Træfɪ k container to port 80 on the host.
> With a multi node cluster we might expose Træfɪ k with a NodePort or LoadBalancer service
> and run more than 1 replica of Træfɪ k for high availability.
To deploy Træfɪ k to your cluster start by submitting the deployment to the cluster with `kubectl` :
```sh
kubectl apply -f examples/k8s/traefik.yaml
```
### Check the deployment
Now lets check if our deployment was successful.
Start by listing the pods in the `kube-system` namespace:
```sh
$kubectl --namespace=kube-system get pods
NAME READY STATUS RESTARTS AGE
kube-addon-manager-minikubevm 1/1 Running 0 4h
kubernetes-dashboard-s8krj 1/1 Running 0 4h
traefik-ingress-controller-678226159-eqseo 1/1 Running 0 7m
```
You should see that after submitting the Deployment to Kubernetes it has launched
2017-02-02 13:36:06 +00:00
a pod, and it is now running. _It might take a few moments for kubernetes to pull
2016-05-06 10:34:30 +00:00
the Træfɪ k image and start the container._
> You could also check the deployment with the Kubernetes dashboard, run
> `minikube dashboard` to open it in your browser, then choose the `kube-system`
> namespace from the menu at the top right of the screen.
You should now be able to access Træfɪ k on port 80 of your minikube instance.
```sh
curl $(minikube ip)
404 page not found
```
> We expect to see a 404 response here as we haven't yet given Træfɪ k any configuration.
2017-03-31 07:57:06 +00:00
## Deploy Træfik using Helm Chart
Instead of installing Træfik via a Deployment object, you can also use the Træfik Helm chart.
Install Træfik chart by:
```sh
helm install stable/traefik
```
For more information, check out [the doc ](https://github.com/kubernetes/charts/tree/master/stable/traefik ).
2016-05-06 10:34:30 +00:00
## Submitting An Ingress to the cluster.
Lets start by creating a Service and an Ingress that will expose the
[Træfɪ k Web UI ](https://github.com/containous/traefik#web-ui ).
```yaml
apiVersion: v1
kind: Service
metadata:
name: traefik-web-ui
namespace: kube-system
spec:
selector:
2017-02-03 16:47:48 +00:00
k8s-app: traefik-ingress-lb
2016-05-06 10:34:30 +00:00
ports:
- port: 80
targetPort: 8080
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik-web-ui
namespace: kube-system
2017-03-03 19:30:22 +00:00
annotations:
kubernetes.io/ingress.class: traefik
2016-05-06 10:34:30 +00:00
spec:
rules:
- host: traefik-ui.local
http:
paths:
- backend:
serviceName: traefik-web-ui
servicePort: 80
```
[examples/k8s/ui.yaml ](https://github.com/containous/traefik/tree/master/examples/k8s/ui.yaml )
```sh
kubectl apply -f examples/k8s/ui.yaml
```
Now lets setup an entry in our /etc/hosts file to route `traefik-ui.local`
2017-02-03 16:47:48 +00:00
to our cluster.
2016-05-06 10:34:30 +00:00
> In production you would want to set up real dns entries.
> You can get the ip address of your minikube instance by running `minikube ip`
```
echo "$(minikube ip) traefik-ui.local" | sudo tee -a /etc/hosts
```
We should now be able to visit [traefik-ui.local ](http://traefik-ui.local ) in the browser and view the Træfɪ k Web UI.
## Name based routing
In this example we are going to setup websites for 3 of the United Kingdoms
best loved cheeses, Cheddar, Stilton and Wensleydale.
First lets start by launching the 3 pods for the cheese websites.
```yaml
---
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
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: cheddar
labels:
app: cheese
cheese: cheddar
spec:
replicas: 2
selector:
matchLabels:
app: cheese
task: cheddar
template:
metadata:
labels:
app: cheese
task: cheddar
version: v0.0.1
spec:
containers:
- name: cheese
image: errm/cheese:cheddar
resources:
requests:
cpu: 100m
memory: 50Mi
limits:
cpu: 100m
memory: 50Mi
ports:
- containerPort: 80
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: wensleydale
labels:
app: cheese
cheese: wensleydale
spec:
replicas: 2
selector:
matchLabels:
app: cheese
task: wensleydale
template:
metadata:
labels:
app: cheese
task: wensleydale
version: v0.0.1
spec:
containers:
- name: cheese
image: errm/cheese:wensleydale
resources:
requests:
cpu: 100m
memory: 50Mi
limits:
cpu: 100m
memory: 50Mi
ports:
- containerPort: 80
```
[examples/k8s/cheese-deployments.yaml ](https://github.com/containous/traefik/tree/master/examples/k8s/cheese-deployments.yaml )
```sh
kubectl apply -f examples/k8s/cheese-deployments.yaml
```
Next we need to setup a service for each of the cheese pods.
```yaml
---
apiVersion: v1
kind: Service
metadata:
name: stilton
spec:
ports:
- name: http
targetPort: 80
port: 80
selector:
app: cheese
task: stilton
---
apiVersion: v1
kind: Service
metadata:
name: cheddar
spec:
ports:
- name: http
targetPort: 80
port: 80
selector:
app: cheese
task: cheddar
---
apiVersion: v1
kind: Service
metadata:
name: wensleydale
2017-02-03 16:47:48 +00:00
annotations:
traefik.backend.circuitbreaker: "NetworkErrorRatio() > 0.5"
2016-05-06 10:34:30 +00:00
spec:
ports:
- name: http
targetPort: 80
port: 80
selector:
app: cheese
task: wensleydale
```
2017-02-03 16:47:48 +00:00
> Notice that we also set a [circuit breaker expression](https://docs.traefik.io/basics/#backends) for one of the backends
> by setting the `traefik.backend.circuitbreaker` annotation on the service.
2016-05-06 10:34:30 +00:00
[examples/k8s/cheese-services.yaml ](https://github.com/containous/traefik/tree/master/examples/k8s/cheese-services.yaml )
```sh
kubectl apply -f examples/k8s/cheese-services.yaml
```
Now we can submit an ingress for the cheese websites.
```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: cheese
2017-03-03 19:30:22 +00:00
annotations:
kubernetes.io/ingress.class: traefik
2016-05-06 10:34:30 +00:00
spec:
rules:
- host: stilton.local
http:
paths:
- path: /
backend:
serviceName: stilton
servicePort: http
- host: cheddar.local
http:
paths:
- path: /
backend:
serviceName: cheddar
servicePort: http
- host: wensleydale.local
http:
paths:
- path: /
backend:
serviceName: wensleydale
servicePort: http
```
[examples/k8s/cheese-ingress.yaml ](https://github.com/containous/traefik/tree/master/examples/k8s/cheese-ingress.yaml )
> Notice that we list each hostname, and add a backend service.
```sh
kubectl apply -f examples/k8s/cheese-ingress.yaml
```
Now visit the [Træfɪ k dashboard ](http://traefik-ui.local/ ) 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.
If you edit your `/etc/hosts` again you should be able to access the cheese
websites in your browser.
```sh
echo "$(minikube ip) stilton.local cheddar.local wensleydale.local" | sudo tee -a /etc/hosts
```
* [Stilton ](http://stilton.local/ )
* [Cheddar ](http://cheddar.local/ )
* [Wensleydale ](http://wensleydale.local/ )
## Path based routing
Now lets suppose that our fictional client has decided that while they are
super happy about our cheesy web design, when they asked for 3 websites
they had not really bargained on having to buy 3 domain names.
No problem, we say, why don't we reconfigure the sites to host all 3 under one domain.
```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: cheeses
annotations:
2017-03-03 19:30:22 +00:00
kubernetes.io/ingress.class: traefik
2016-05-06 10:34:30 +00:00
traefik.frontend.rule.type: pathprefixstrip
spec:
rules:
- host: cheeses.local
http:
paths:
- path: /stilton
backend:
serviceName: stilton
servicePort: http
- path: /cheddar
backend:
serviceName: cheddar
servicePort: http
- path: /wensleydale
backend:
serviceName: wensleydale
servicePort: http
```
[examples/k8s/cheeses-ingress.yaml ](https://github.com/containous/traefik/tree/master/examples/k8s/cheeses-ingress.yaml )
> Notice that we are configuring Træfɪ k to strip the prefix from the url path
> with the `traefik.frontend.rule.type` annotation so that we can use
> the containers from the previous example without modification.
```sh
kubectl apply -f examples/k8s/cheeses-ingress.yaml
```
```sh
echo "$(minikube ip) cheeses.local" | sudo tee -a /etc/hosts
```
You should now be able to visit the websites in your browser.
* [cheeses.local/stilton ](http://cheeses.local/stilton/ )
* [cheeses.local/cheddar ](http://cheeses.local/cheddar/ )
* [cheeses.local/wensleydale ](http://cheeses.local/wensleydale/ )
2017-02-15 21:37:47 +00:00
## Disable passing the Host header
By default Træfɪ k will pass the incoming Host header on to the upstream resource. There
are times however where you may not want this to be the case. For example if your service
is of the ExternalName type.
2017-02-16 00:11:31 +00:00
### Disable entirely
Add the following to your toml config:
```toml
disablePassHostHeaders = true
```
### Disable per ingress
To disable passing the Host header per ingress resource set the "traefik.frontend.passHostHeader"
annotation on your ingress to "false".
2017-02-15 21:37:47 +00:00
Here is an example ingress definition:
```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: example
annotations:
2017-03-03 19:30:22 +00:00
kubernetes.io/ingress.class: traefik
2017-02-15 21:37:47 +00:00
traefik.frontend.passHostHeader: "false"
spec:
rules:
- host: example.com
http:
paths:
- path: /static
backend:
serviceName: static
servicePort: https
```
And an example service definition:
```yaml
apiVersion: v1
kind: Service
metadata:
name: static
spec:
ports:
- name: https
port: 443
type: ExternalName
externalName: static.otherdomain.com
```
If you were to visit example.com/static the request would then be passed onto
static.otherdomain.com/static and static.otherdomain.com would receive the
2017-02-16 00:11:31 +00:00
request with the Host header being static.otherdomain.com.
Note: The per ingress annotation overides whatever the global value is set to. So you
could set `disablePassHostHeaders` to true in your toml file and then enable passing
2017-03-03 19:30:22 +00:00
the host header per ingress if you wanted.
## Excluding an ingress from Træfɪ k
You can control which ingress Træfɪ k cares about by using the "kubernetes.io/ingress.class"
annotation. By default if the annotation is not set at all Træfɪ k will include the
ingress. If the annotation is set to anything other than traefik or a blank string
Træfɪ k will ignore it.