Deploying Traefik as Ingress Controller on Kubernetes
Traefik is a powerful cloud-native edge router that can be utilised in many different environments, the most popular being Kubernetes and Docker. The built-in ACME client, amongst other features, makes Traefik a great choice as an edge router.
Traefik has two types of configuration: Dynamic configuration, which is set on the Kubernetes services we want to expose as annotations, and static configuration, which configures Traefik itself.
The first configuration that needs to be defined is the static configuration, used when Helm installs Traefik. The static configuration can be declared using CLI, YAML or TOML. In this case, we will use YAML.
First, set Traefik as the default Ingress Controller for Kubernetes:
ingressClass:
enabled: true
isDefaultClass: true
Disable the Traefik dashboard. The dashboard is not something we want to expose to the internet:
ingressRoute:
dashboard:
enabled: false
Configure Traefik to obtain SSL certificates from LetsEncrypt. Because we are using HTTP verification, ensure your domain name is already pointing to the IP address your Kubernetes cluster will be exposed on.
additionalArguments:
- --certificatesresolvers.letsencrypt.acme.caServer=https://acme-v02.api.letsencrypt.org/directory
- --certificatesresolvers.letsencrypt.acme.httpChallenge.entryPoint=web
- --certificatesresolvers.letsencrypt.acme.storage=/ssl-certs/acme-generic.json
The certificate issued by LetsEncrypt is saved in /ssl-certs/acme-generic.json. Use a persistent volume to save and re-use this certificate across new Traefik containers:
persistence:
enabled: true
name: ssl-certs
size: 1Gi
path: /ssl-certs
Sometimes, there can be permission issues when Traefik tries to save or read the certificate from the persistent volume. Deploying this busybox container will ensure the permissions are correct within the volume:
deployment:
initContainers:
- name: volume-permissions
image: busybox:1.31.1
command: ["sh", "-c", "chmod -Rv 600 /ssl-certs/*"]
volumeMounts:
- name: ssl-certs
mountPath: /ssl-certs
Lastly, the ports used to connect to Traefik from the internet need to be configured. By default, the Traefik Helm chart refers to port 443 as websecure, and port 80 as web. We can configure web traffic on port 80 to be redirected to port 443, to ensure all web traffic to Traefik is encrypted. We can also define which certificate resolver to use on port 443:
ports:
web:
redirectTo: websecure
websecure:
tls:
enabled: true
certResolver: letsencrypt
Additional configuration options and default values for Traefik’s static configuration when installing with Helm can be found in the Traefik Helm chart GitHub.
To install Traefik with your static configuration YAML file with Helm:
- Add the Traefik Helm repo:
helm repo add traefik https://helm.traefik.io/traefik
- Update the Helm chart repository:
helm repo update
- Install the Traefik Helm chart with your static configuration file:
helm install traefik/traefik -values traefik-static-configuration.yaml
After Traefik has been installed, we can use Traefik to expose Kubernetes services.
First of all, we need to define a Kubernetes deployment. For example, an Nginx deployment exposed on port 5000:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 5000
Next, we need to define a ClusterIP service:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: ClusterIP
ports:
- port: 5000
targetPort: 5000
selector:
app: nginx
Lastly, we create an Ingress definition which includes the Traefik dynamic configuration:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
spec:
rules:
- host: "cloudcover.ch"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx
port:
number: 5000
A big thank you to The Digital Life on YouTube, who provide templates for this deployment method on their GitHub page.