Traefik With Lets Encrypt Wildcard SSL Certificate Using Kubernetes
Let’s encrypt has introduced wildcard certificates and traefik has released a v2 which is completely different from v1. This calls for a tutorial on how to use the two together in kubernetes.
Why wildcard certificates?
You don’t need separate https certicates for your subdomain, especially if you are used to deploying your applications as different subdomains. This will significantly reduce calls to Let’s Encrypt servers which is now important since they have introduced serious rate limits. And of course, Let’s encrypt is totally free so you have no reason to not use HTTPS anymore, not to mention its more secure than using HTTP.
Why traefik
Traefik is a beautiful piece of software which is container aware and can get/issue/renew Let’s Encrypt certificates automatically, once configured.
How?
At the time of writing this, Let’s Encrypt only supports wildcard certificates using the DNS-01
verification method so thats what this article uses as well.
This article also uses GoDaddy for domains. The API keys for GoDaddy can be generated from GoDaddy Developer Portal. Traefik supports other DNS providers, any of which can be used instead.
-
Create a subchart for traefik:
helm create traefik-server
-
Add traefik chart as a dependency by adding the following section in
Charts.yml
in thetraefik-server
chart:dependencies: - name: traefik version: 10.20.1 repository: https://helm.traefik.io/traefik
-
Add the traefik chart repo and update the dependency added.
helm repo add traefik https://helm.traefik.io/traefik helm repo update helm dependency update
-
Create the following
values.yml
file in thetraefik-server
chart:Note: Use the let’s encrypt staging endpoint while testing or the domain will get rate limited. The
traefik
section indicates that the values set are for the dependenttraefik
charttraefik: providers: kubernetesCRD: enabled: true logs: # Traefik logs concern everything that happens to Traefik itself (startup, configuration, events, shutdown, and so on). general: # By default, the logs use a text format (common), but you can # also ask for the json format in the format option # format: json # By default, the level is set to ERROR. Alternative logging levels are DEBUG, PANIC, FATAL, ERROR, WARN, and INFO. level: INFO access: # To enable access logs enabled: true # resources: # limits: # cpu: 1 # memory: 100Mi rbac: enabled: true additionalArguments: # - "--providers.kubernetesingress=true" # - "--providers.kubernetesingress.ingressclass=traefik" # Please note that this is the staging Let's Encrypt server. # Once you get things working, you should remove that whole line altogether. - "--certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory" certResolvers: letsencrypt: # for challenge options cf. https://doc.traefik.io/traefik/https/acme/ email: <your email> dnsChallenge: provider: godaddy delayBeforeCheck: 30 resolvers: - 1.1.1.1 - 8.8.8.8 # tlsChallenge: true # httpChallenge: # entryPoint: "web" # match the path to persistence storage: /data/acme.json env: - name: GODADDY_API_KEY value: <your API key> - name: GODADDY_API_SECRET value: <your API secret> ports: web: redirectTo: websecure websecure: tls: enabled: true # this is the name of a TLSOption definition options: "" certResolver: "letsencrypt" domains: - main: "<your domain>" sans: - "*.<your domain>" # If the certificates are to be persisted # persistence: # enabled: true # name: data # accessMode: ReadWriteOnce # size: 128Mi # path: /data # securityContext: # readOnlyRootFilesystem: false # runAsGroup: 0 # runAsUser: 0 # runAsNonRoot: false # deployment: # initContainers: # - name: volume-permissions # image: busybox:1.31.1 # command: ["sh", "-c", "chmod -Rv 600 /data/*"] # volumeMounts: # - name: data # mountPath: /data
-
Deploy the
traefik-server
charthelm upgrade --install traefik-server traefik-server
-
Point the loadbalancer IP to the deomain
Wait for a few minutes for DNS propagation, challenge andmthe SSL cetrificate to be issued.
-
For every service add an ingress route as follows:
apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: {{ .Values.appName }}-ingress-route labels: chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" release: "{{ .Release.Name }}" spec: entryPoints: - websecure routes: - match: Host(`{{ .Values.appName }}.{{ .Values.ingressHost }}`) kind: Rule services: - name: {{ .Values.appName }}-service port: 80 tls: certResolver: "letsencrypt" domains: - main: "<your domain>" sans: - "*."<your domain>"
Note: The
tls
section here. The cert resolver and the domains has to match with the ones in thetraefik-server
chart’svalues.yml
file -
Switch to Let’s Encrypt’s production endpoints once everything is working by removing/commenting the following line from
values.yml
file:# Please note that this is the staging Let's Encrypt server. # Once you get things working, you should remove that whole line altogether. - "--certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
-
That’s it