Installing Traefik to a DigitalOcean cluster the custom resource way
I wanted to try the Traefik edge router for a long time. I have recently created a DigitalOcean managed Kubernetes cluster primarily for learning and experimenting, so it seemed the perfect opportunity to install Traefik.
This guide was tested on Kubernetes 1.18 and Traefik 2.2
Prerequisites
- a working Kubernetes cluster
- kubectl configured and context set to cluster
0. If you don’t have a cluster
You can get $100 in credit over 60 days using this referral link.
1. Apply custom resource and RBAC definitions
Save the following definitions to a file and apply them using kubectl apply -f [filename]
The definitions can also be downloaded from the Traefik website.
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: 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: 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: 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
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tlsstores.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: TLSStore
plural: tlsstores
singular: tlsstore
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressrouteudps.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRouteUDP
plural: ingressrouteudps
singular: ingressrouteudp
scope: Namespaced
---
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
- ingressrouteudps
- tlsoptions
- tlsstores
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
2. Create a service account
Save the following service account definition to a file and apply it using kubectl apply -f [filename]
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: default
name: traefik-ingress-controller
3. Create the Traefik deployment
Save the following deployment definition to a file, substitute the YOUR_EMAIL string (in the args section) with your email address, change the Traefik image version if needed, then apply it using kubectl apply -f [filename]
It differs a bit from the one on the Traefik website. Note in the args that the ping endpoint is enabled and set to the web entrypoint, we’ll be needing this for the load balancer’s health check configuration.
kind: Deployment
apiVersion: apps/v1
metadata:
namespace: default
name: traefik
labels:
app: traefik
spec:
replicas: 1
selector:
matchLabels:
app: traefik
template:
metadata:
labels:
app: traefik
spec:
serviceAccountName: traefik-ingress-controller
containers:
- name: traefik
image: traefik:v2.2
args:
- --api
- --entrypoints.web.Address=:8000
- --entrypoints.websecure.Address=:4443
- --ping.entryPoint=web
- --providers.kubernetescrd
- --certificatesresolvers.default.acme.tlschallenge
- --certificatesresolvers.default.acme.email=YOUR_EMAIL
- --certificatesresolvers.default.acme.storage=acme.json
ports:
- name: web
containerPort: 8000
- name: websecure
containerPort: 4443
- name: admin
containerPort: 8080
4. Create a Traefik service and a DigitalOcean load balancer
Save the following service definition to a file and apply it using kubectl apply -f [filename]
kind: Service
apiVersion: v1
metadata:
name: traefik-lb
namespace: default
annotations:
service.beta.kubernetes.io/do-loadbalancer-healthcheck-port: "80"
service.beta.kubernetes.io/do-loadbalancer-healthcheck-protocol: "http"
service.beta.kubernetes.io/do-loadbalancer-healthcheck-path: "/ping"
service.beta.kubernetes.io/do-loadbalancer-protocol: "http"
service.beta.kubernetes.io/do-loadbalancer-tls-ports: "443"
service.beta.kubernetes.io/do-loadbalancer-tls-passthrough: "true"
service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: "true"
service.beta.kubernetes.io/do-loadbalancer-redirect-http-to-https: "true"
spec:
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8000
- name: https
protocol: TCP
port: 443
targetPort: 4443
selector:
app: traefik
type: LoadBalancer
Applying the definition will automatically spin up a DigitalOcean load balancer, with health check, TLS passthrough and HTTPS redirect enabled. You can find more information on configuring DigitalOcean load balancers here.
The newly created load balancer will be visible on the DigitalOcean dashboard, but it is recommended not to edit Kubernetes load balancers there. They should only be edited by using kubectl commands (modifying the service configuration below).
5. Create a DNS record for the Traefik dashboard
The public IP address of the load balancer, created in the previous step, is visible on the DigitalOcean dashboard or can be fetched with the kubectl get svc
command.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.242.0.1 <none> 443/TCP 21h
traefik-lb LoadBalancer 10.242.12.47 [THIS IS THE PUBLIC IP] 80:32265/TCP,443:30086/TCP 10m
Create a DNS record for the traefik.yourdomain.com subdomain pointing to the load balancer’s IP address or make sure the wildcard DNS record for your domain points to the load balancer’s IP address.
6. Make Traefik dashboard available with basic authentication
In this step we’ll make the dashboard available by defining a route for the previously created subdomain. We’ll use a middleware to add basic authentication to the dashboard while storing the credentials in a Kubernetes secret.
Save the following service account definition to a file. Substitute the USER_SECRET string in the secret definition with an encoded user-password pair created using the following command:
htpasswd -nb user password | openssl base64
Replace yourdomain.com with your domain name in the IngressRoute definition.
Apply the file using kubectl apply -f [filename]
apiVersion: v1
kind: Secret
metadata:
name: traefik-dashboard-login
namespace: default
data:
users: USER_SECRET
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: traefik-dashboard-auth
namespace: default
spec:
basicAuth:
secret: traefik-dashboard-login
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard-route
namespace: default
spec:
entryPoints:
- websecure
routes:
- match: Host(`traefik.yourdomain.com`)
kind: Rule
services:
- name: api@internal
kind: TraefikService
middlewares:
- name: traefik-dashboard-auth
tls:
certResolver: default
After applying the configuration the dashboard should be available at traefik.yourdomain.com.
Update notes
2020-12-06 - The guide was updated to use DigitalOcean’s Kubernetes resource based load balancers and Traefik v2.2.