Traefik, cert-manager, Cloudflare, and Let’s Encrypt are a winning combination when it comes to securing your services with certificates in Kubernetes. Today, we’ll install and configure Traefik, the cloud native proxy and load balancer, as our Kubernetes Ingress Controller. We’ll then install and configure cert-manager to manage certificates for our cluster. We’ll set up Let’s Encrypt as our Cluster Issuer so that cert-manager can automatically provision TLS certificates and even wildcard certificates using Cloudflare DNS challenge absolutely free. We’ll walk through all of this, step by step, so you can help secure your cluster today.
A HUGE thanks to Datree for sponsoring this video!
Combat misconfigurations. Empower engineers.
Getting Started
If you need to install a new kubernetes cluster you can use my Ansible Playbook to install one.
Resources
You can find all of the resources for this tutorial here
Helm
1
2
3
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
For other ways to install Helm see the installation docs here
Installing
Verify you can communicate with your cluster
1
kubectl get nodes
You should see
1
2
3
4
5
6
NAME STATUS ROLES AGE VERSION
k3s-01 Ready control-plane,etcd,master 10h v1.23.4+k3s1
k3s-02 Ready control-plane,etcd,master 10h v1.23.4+k3s1
k3s-03 Ready control-plane,etcd,master 10h v1.23.4+k3s1
k3s-04 Ready <none> 10h v1.23.4+k3s1
k3s-05 Ready <none> 10h v1.23.4+k3s1
Verify helm is installed
1
helm version
You should see
1
version.BuildInfo{Version:"v3.8.0", GitCommit:"d14138609b01886f544b2025f5000351c9eb092e", GitTreeState:"clean", GoVersion:"go1.17.5"}
Traefik
These resources are in the
launchpad/kubernetes/traefik-cert-manager/traefik/
folder
Add repo
1
helm repo add traefik https://helm.traefik.io/traefik
Update repo
1
helm repo update
Create our namespace
1
kubectl create namespace traefik
Get all namespaces
1
kubectl get namespaces
We should see
1
2
3
4
5
6
7
NAME STATUS AGE
default Active 21h
kube-node-lease Active 21h
kube-public Active 21h
kube-system Active 21h
metallb-system Active 21h
traefik Active 12s
Install traefik
1
helm install --namespace=traefik traefik traefik/traefik --values=values.yaml
Check the status of the traefik ingress controller service
1
kubectl get svc --all-namespaces -o wide
We should see traefik with the specified IP
1
2
3
4
5
6
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
default kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 16h <none>
kube-system kube-dns ClusterIP 10.43.0.10 <none> 53/UDP,53/TCP,9153/TCP 16h k8s-app=kube-dns
kube-system metrics-server ClusterIP 10.43.182.24 <none> 443/TCP 16h k8s-app=metrics-server
metallb-system webhook-service ClusterIP 10.43.205.142 <none> 443/TCP 16h component=controller
traefik traefik LoadBalancer 10.43.156.161 192.168.30.80 80:30358/TCP,443:31265/TCP 22s app.kubernetes.io/instance=traefik,app.kubernetes.io/name=traefik
Get all pods in traefik
namespace
1
kubectl get pods --namespace traefik
We should see pods in the traefik
namespace
1
2
3
4
NAME READY STATUS RESTARTS AGE
traefik-76474c4d47-l5z74 1/1 Running 0 11m
traefik-76474c4d47-xb282 1/1 Running 0 11m
traefik-76474c4d47-xx5lw 1/1 Running 0 11m
middleware
Apply middleware
1
kubectl apply -f default-headers.yaml
Get middleware
1
kubectl get middleware
We should see our headers
1
2
NAME AGE
default-headers 25s
dashboard
Install htpassword
1
2
sudo apt-get update
sudo apt-get install apache2-utils
Generate a credential / password that’s base64 encoded
1
htpasswd -nb techno password | openssl base64
Apply secret
1
kubectl apply -f secret-dashboard.yaml
Get secret
1
kubectl get secrets --namespace traefik
Apply middleware
1
kubectl apply -f middleware.yaml
Apply dashboard
1
kubectl apply -f ingress.yaml
Visit https://traefik.local.example.com
Sample Workload
These resources are in the
launchpad/kubernetes/traefik-cert-manager/nginx/
folder
1
2
3
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml
Or you can apply an entire folder at once!
1
kubectl apply -f nginx
cert-manager
These resources are in the
launchpad/kubernetes/traefik-cert-manager/cert-manager/
folder
Add repo
1
helm repo add jetstack https://charts.jetstack.io
Update it
1
helm repo update
Create our namespace
1
kubectl create namespace cert-manager
Get all namespaces
1
kubectl get namespaces
We should see
1
2
3
4
5
6
7
8
NAME STATUS AGE
cert-manager Active 12s
default Active 21h
kube-node-lease Active 21h
kube-public Active 21h
kube-system Active 21h
metallb-system Active 21h
traefik Active 4h35m
Apply crds
Note: Be sure to change this to the latest version of
cert-manager
1
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.crds.yaml
Install with helm
1
helm install cert-manager jetstack/cert-manager --namespace cert-manager --values=values.yaml --version v1.9.1
Apply secrets
Be sure to generate the correct token if using Cloudflare. This is using an API Token and not a global key.
From issuers
folder
1
kubectl apply -f secret-cf-token.yaml
Apply staging ClusterIssuer
From issuers
folder
1
kubectl apply -f letsencrypt-staging.yaml
Create certs
staging
From certificates/staging
folder
1
kubectl apply -f local-example-com.yaml
Check the logs
1
kubectl logs -n cert-manager -f cert-manager-877fd747c-fjwhp
Get challenges
1
kubectl get challenges
Get more details
1
kubectl describe order local-technotim-live-frm2z-1836084675
production
Apply production ClusterIssuer
From issuers
folder
1
kubectl apply -f letsencrypt-production.yaml
From certificates/production
folder
1
kubectl apply -f local-example-com.yaml
Links
⚙️ See all the hardware I recommend at https://l.technotim.live/gear
🚀 Don’t forget to check out the 🚀Launchpad repo with all of the quick start source files