My previous basic Traefik install guide used the built-in easy approach to certificate handling. For production use-cases, it is better to use the cert-manager tool as it stores the certificates as cluster resources and does not regenerate them on every Traefik restart. With the built-in approach it is easy to bump into Let’s Encrypt’s weekly limit. Using cert-manager also enables us to run more than one Traefik instances on a Kubernetes cluster.

This guide mainly focuses on creating wildcard certificates, because I wanted to generate a certificate which I can use for dynamically created subdomains, but the certificate’s configuration below can be easily changed to create a certificate for specific subdomains.

This guide was tested on Kubernetes 1.18 and Traefik 2.2

Prerequisites

  • a working Kubernetes cluster
  • a working Traefik install
  • kubectl configured and context set to cluster

0. If you don’t have a cluster

You can get $100 in credit over 60 days using this referral link.

1. Installing cert-manager

To be able to store and automatically renew certificates, at first we need to install cert-manager into our cluster. It can be done easily following these guidelines. I have installed v1.1 just by issuing the following command from the guide:

kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.1.0/cert-manager.yaml

2. Configuring a ClusterIssuer for Let’s Encrypt

As stated in the cert-manager documentation, an Issuer (or ClusterIssuer) represents a certificate authority which is able to generate signed certificates.

To make Let’s Encrypt issuer work with DigitalOcean, an API access token is needed. An access token can be generated using the admin panel. The API access is needed because this setup uses the DNS-01 challange for issuing certificates and cert-manager needs to do some DNS manipulation to prove that we are in control of the domain.

After generating an access token, substitute the YOUR_ACCESS_TOKEN string with it in the following command, then run it. Running the command creates a secret in the cert-manager namespace containing the access token.

kubectl create secret generic digitalocean-dns -n cert-manager --from-literal=access-token=YOUR_ACCESS_TOKEN

After creating the secret, substitute the YOUR_EMAIL string with your e-mail address in the following ClusterIssuer definition, save it to a file and apply it using kubectl apply -f [filename].

apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
  namespace: cert-manager
spec:
  acme:
    email: YOUR_EMAIL
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: issuer-account-key
    solvers:
    - dns01:
        digitalocean:
          tokenSecretRef:
            name: digitalocean-dns
            key: access-token

You can change the server url to https://acme-staging-v02.api.letsencrypt.org/directory if you want to try out generating certificates in the staging environment first. The rate limits in this environment are higher which is good for testing.

3. Creating a certificate

The domain name’s DNS records we want to create a wildcard certificate for needs to be managed by DigitalOcean. If your domain’s DNS records are not managed by DigitalOcean follow this guide.

To create a wildcard certificate replace yourdomain.com in the commonName and dnsNames fields with your real domain. Notice that we reference the ClusterIssuer created in the previous step. Save it to a file and apply it using kubectl apply -f [filename]

apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
  name: yourdomain-cert
spec:
  commonName: '*.yourdomain.com'
  secretName: yourdomain-cert
  dnsNames:
    - yourdomain.com
    - '*.yourdomain.com'
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer

After applying the file, the certificate’s status can be checked by issuing the following command: kubectl describe Certificate yourdomain-cert

The current actual certificate will be stored in a yourdomain-cert named TLS type secret, which can be checked by issuing the following command: kubectl describe secrets yourdomain-cert

Note: To create a specific (not wildcard) certificate, replace the ‘*’ character in the configuration file above with a subdomain.

4. Using the certificate in an IngressRoute

To use the generated certificate in a Traefik IngressRoute, reference the secret containing the certificate in your route’s configuration just like in the example below. Note the tls/secretName field in the bottom.

To be able to actually use this example, you need to make sure that the secretName is the same as you have given in the previous step and the placeholders in the match and services/name fields are pointing to your real domain and a valid service running in your cluster. After setting the correct values, save this route configuration to a file and apply it using ```kubectl apply -f [filename]``

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: my-website-with-certificate-route
spec:
  entryPoints:
    - websecure
  routes:
  - match: Host(`yourdomain.com`) || Host(`www.yourdomain.com`)
    kind: Rule
    services:
    - name: my-website
      port: 80
  tls:
    secretName: yourdomain-cert