Here I share the recipe for how to setup High Availability Traefik Proxy (multiple instances) for Kubernetes with TLS certificates obtained from LetsEncrypt with help of Cert Manager.
To get high availability setup for Traefik we will host multiple instances of Traefik on different hosts (or even in different availability zones). All of the Traefik instances need to load the same TLS certificates and equally participate in ACME http challenge process during obtaining the certificates from LetsEncrypt. Both can be achieved by using Cert Manager, which stores the TLS certificates in Kubernetes secrets (no need for PVC) and carries out LetEncrypt ACME http challenge through Kubernetes Ingress entities. We leave deployment of Cert Manager out of scope for this post. The following assumes that you have Cert Manager deployed.
Configuring Cert Manager for LetsEncrypt
In order to get certificates from LetsEncrypt we can define the following Issuers (CRD used by Cert Manager):
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: hostmaster@your-domain.tld # Replace this with your mail address
privateKeySecretRef:
name: letsencrypt-staging
solvers:
- http01:
ingress:
class: traefik
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: hostmaster@your-domain.tld # Replace this with your mail address
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: traefik
Configuring Traefik for Cert Manager
Note that we specified the “traefik” ingress class among ACME solvers. That is how Cert Manager will get the TLS certificates for our domains. Cert Manager can’t use IngressRoute CRD defined for Traefik as they are too application specific. Instead, it can use standard Ingress or newly emerged Gateway API Kubernetes entities. Here we use Ingress. That means that we need to enable Traefik to serve Kubernetes Ingress entities. That can be done, for instance, through CLI args:
...
spec:
containers:
- name: traefik
image: traefik:v2.9
args:
- --entrypoints.web.Address=:80
- --entrypoints.websecure.Address=:443
- --providers.kubernetescrd # needed for IngressRoutes
- --providers.kubernetesingress # needed for cert-manger
ports:
- name: web
containerPort: 80
- name: websecure
containerPort: 443
If you use IngressRoutes then you will have to enable both kubernetescrd and kubernetesingress Traefik configuration providers.
Defining “certificate” for IngressRoute
Now the Cert Manager will be able to finish the ACME http challenge for our domains. At this point we can define a certificate to obtain from LetsEncrypt. The following example defines the certificate that is used at this blog (note that you can define multiple DNS names for single certificate).
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: grechka.family-tls-cert
spec:
secretName: grechka.family-tls-secret
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- grechka.family
- www.grechka.family
Right after we create this entity in Kubernetes, Cert Manager will acquire the certificate. Now we can use the certificate in Traefik IngressRoute, like in the following example:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: tls-dmitry-web-blog
spec:
...
tls:
secretName: grechka.family-tls-secret
That’s it! We have high availability Traefik with LetsEncrypt certificates.