K3s Helm Traefik + LetsEncrypt
March 31, 2022 | ClusterBy default Traefik is deployed in K3s. So, in production we would like automating valid wildcard certificate creation. In this case there are two main approaches to generate and store certificates; cert-manager and traefik acme. On it's own Traefik acme can be used to create and store the certificate, but to get HA this way is only supported on the Enterprice version of Traefik. I'll try to use Cert-manager to handle the certificates, which I also consider a better solution for control and isolation of the Certificates and the added bonus of HA.
The Cert-manager way
You should allready have Cert-manager up and running, before continuing. When that's done Cert-manager have a Issuer/ClusterIssuer which will represent the CA. The deployment looks like this:
# Staging
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
namespace: cert-manager
spec:
acme:
email: ...
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-staging-key
solvers:
# An empty 'selector' means that this solver matches all domains
- selector: { }
http01:
ingress: { }
---
# And Production would look something like this
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
namespace: cert-manager
spec:
acme:
email: ...
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-prod-key
solvers:
# An empty 'selector' means that this solver matches all domains
- selector: { }
http01:
ingress: { }
# DNS challange something like this
# - dns01:
# digitalocean:
# tokenSecretRef:
# name: digitalocean-dns
# key: access-token
Deploy the above ClusterIssuer
To create a certificate, for a domain/subdomain apply the following:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: yourdomain-cert
namespace: your-namespace
spec:
commonName: '*.yourdomain.com'
secretName: yourdomain-cert
dnsNames:
- yourdomain.com
- '*.yourdomain.com'
# or [sub]. instead of wildcard (*)
issuerRef:
name: letsencrypt-staging
kind: ClusterIssuer
Apply the two and se if a staging cert has been generated.
kubectl describe certificate my-app-com
and for troubleshooting:
kubectl describe certificaterequest selfsigned-cert-2gd9x
Traefik IngressRoute
Last apply the IngressRoute:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: my-ingress
spec:
entryPoints:
- web
- websecure
routes:
- match: Host(`yourdomain.com`)
kind: Rule
services:
- name: my-app-svc
port: 3000
tls:
# Reference the Secret
secretName: yourdomain-cert