Traefik 2.1 in Kubernetes
As I migrate from Docker Swarm to Kubernetes I decided to use Traefik. Here's how to replace NGINX with Traefik 2.1 for Kubernetes Ingress.
As I migrate from Docker Swarm to Kubernetes I decided to use Traefik. Here's how to replace NGINX with Traefik 2.1 for Kubernetes Ingress.
The documentation was sparse and sporadic. It was a gloomy weekend. I was grumpy and cranky. Seems to be my general mindset with Kubernetes. Anyways, after digging through tons of documentation, a couple of days of trial and error, I finally got the Traefik 2.1 container working in Kubernetes and dynamically updating it's configuration.
I'm first going to go over a little bit of what's needed.
Kind | Name | Purpose |
---|---|---|
ClusterRole |
- | This is to set up the permissions so Traefik can talk to the Kubernetes API |
ClusterRoleBinding |
- | Binds the role to the Traefik containers |
CustomResourceDefinition |
IngressRoute |
HTTP ingress type |
CustomResourceDefinition |
Middleware |
Middleware types so you can use the Traefik middleware |
CustomResourceDefinition |
IngressRouteTCP |
Raw TCP port ingress type |
CustomResourceDefinition |
TLSOption |
TLS Options |
CustomResourceDefinition |
TraefikService |
Traefik special services |
DaemonSet |
- | The actual running Traefik containers |
Service |
- | The Traefik service |
Those types and objects are needed for Traefik to function. I split them into 3 distinct files, RBAC.yml
, ResourceDefinitions.yml
and Traefik.yml
. It's pretty simple as to what is in each, so I will just give you the files.
RBAC.yml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses/status
verbs:
- update
- apiGroups:
- traefik.containo.us
resources:
- middlewares
- ingressroutes
- traefikservices
- ingressroutetcps
- tlsoptions
verbs:
- get
- list
- watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller
namespace: default
ResourceDefinitions.yml
# All resources definition must be declared
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressroutes.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRoute
plural: ingressroutes
singular: ingressroute
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: middlewares.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: Middleware
plural: middlewares
singular: middleware
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressroutetcps.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRouteTCP
plural: ingressroutetcps
singular: ingressroutetcp
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tlsoptions.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: TLSOption
plural: tlsoptions
singular: tlsoption
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: traefikservices.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: TraefikService
plural: traefikservices
singular: traefikservice
scope: Namespaced
Traefik.yml
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-ingress-controller
---
kind: DaemonSet
apiVersion: apps/v1
metadata:
name: traefik
labels:
app: traefik
spec:
selector:
matchLabels:
app: traefik
template:
metadata:
labels:
app: traefik
spec:
serviceAccountName: traefik-ingress-controller
containers:
- name: traefik
image: traefik:v2.1
args:
- --log.level=DEBUG
- --api
- --api.insecure
- --entrypoints.web.address=:80
- --providers.kubernetescrd
ports:
- name: web
containerPort: 80
hostPort: 80
- name: admin
containerPort: 8080
hostPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: traefik
spec:
selector:
app: traefik
ports:
- protocol: TCP
port: 80
name: web
targetPort: 80
- protocol: TCP
port: 8080
name: admin
targetPort: 8080
I chose to use DaemonSet instead of deployment because a DaemonSet will make sure that an instance of the service is running on every Kubernetes node. Thus it gives us instant high availability. And I like that.
I put each file into the same directory, they are the only files in that directory. Because I'm an original and creative person, I named the folder traefik. See, its original, I used a lowercase t.
I then ran the kubectl
command to apply the configs. kubectl apply -f ./traefik
. Now when I go to my Kubernetes cluster in a browser I don't get the ugly NGINX service unavailable page. Instead I get the non-customizable, not as ugly, 404 page from Traefik.
And we're done with getting Traefik 2.1 into Kubernetes. And now to figure out HTTPS with my own SSL cert and not use Lets Encrypt...because apparently I like doing things that don't have any documentation.