Auto TLS with cert-manager and Traefik

Cover image taken from

On my previous post, Traefik in actions. The Cloud Native Edge Router, we have learnt how to setup Traefik and introduce some feature. It was using default ACME for https setup. On recent twitter discussion, I learnt that we can use cert-manager as alternative to the default ACME.

Also, if want to achieve High Availability (HA) on Traefik open source version, can't rely on default ACME.

If you require LetsEncrypt with HA in a kubernetes environment, we recommend using Traefik Enterprise where distributed LetsEncrypt is a supported feature.

If you are wanting to continue to run Traefik Community Edition, LetsEncrypt HA can be achieved by using a Certificate Controller such as Cert-Manager.

from CRD docs

In this post, we will try out cert-manager for that.

Table of contents generated with markdown-toc


I will walk through the demo on Google Cloud (GKE and Google DNS) with terraform, but the concept can be applied to other hosted Kubernetes or distribution

The source code can be found at cncf-demo

If you wish to follow along, make sure you have Google Cloud project created, and download service account with appropriate IAM roles assigned, to be used with terraform.

Also, create another service account for with DNS Administrator role assigned for DNS validation purposes.

git clone
cd terraform/gke-traefik-cert-manager
terraform init
# it will provision GKE cluster
# install traefik and cert-manager with helm
# and create kubernetes secret for Google Cloud DNS
terraform apply

optionally you can create terraform.tfvars to store variables for terraform

$ cat terraform.tfvars
credentials_file = "google-cloud-service-account.json"
google_dns_sa_file = "dns-service-account.json"
project = "your-project-id"

Verify the installation, alternatively you can use console provided by cloud providers or Kubernetes dashbaord

$ kubectl get deploy,svc -n traefik
NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/traefik   1/1     1            1           24h

NAME              TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                      AGE
service/traefik   LoadBalancer    SOME_EXTERNAL_IP   80:30619/TCP,443:30267/TCP   24h

$ kubectl get deploy,svc -n cert-manager
NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/cert-manager              1/1     1            1           24h
deployment.apps/cert-manager-cainjector   1/1     1            1           24h
deployment.apps/cert-manager-webhook      1/1     1            1           24h

NAME                           TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/cert-manager           ClusterIP   <none>        9402/TCP   24h
service/cert-manager-webhook   ClusterIP     <none>        443/TCP    24h

You should be able to access Traefik on the external IP on port 80, add the external IP to your DNS nameserver.

Create sample apps

Let's create some sample apps, to be routed by Traefik

cd kubernetes
kubectl apply -f whoami.yaml -f zone-printer.yaml

Create ClusterIssuer and Certificate

The configuration below uses DNS Validation, which support wildcard certificates. Checkout the docs for HTTP Validation. For supported DNS validation, can view from supported dns01 providers docs

kind: ClusterIssuer
  name: cert-wildcard-issuer
  namespace: default
    # You must replace this email address with your own.
    # Let's Encrypt will use this to contact you about expiring
    # certificates, and issues related to your account.
      # Secret resource used to store the account's private key.
      name: cert-wildcard-issuer
      - selector: { }
            project: YOUR_PROJECT_ID
              name: google-dns-sa
              key: key.json

kind: Certificate
  name: wildcard-cert
  namespace: default
  secretName: wildcard-yongweilun-me-tls
    kind: ClusterIssuer
    name: cert-wildcard-issuer
    - "*"
kubectl apply -f cert-manager.yaml

Check the certificate creation progress

kubectl get certificates
kubectl describe certificates wildcard-cert

It should be ready in a few minutes. If you stuck at Issuing state, might need to troubleshoot it.

Once it is done, verify the tls secret is created

$ kubectl get secret
NAME                         TYPE                                  DATA   AGE
wildcard-yongweilun-me-tls                     2      22h

Create ingressRoute

kind: IngressRoute
  name: myingressroute-secure
  namespace: default

    - websecure
    - match: Host(``) && PathPrefix(`/`)
      kind: Rule
        - name: zone-printer-service
          port: 80
    - match: Host(``) && PathPrefix(`/whoami`)
      kind: Rule
        - name: whoami
          port: 80
    - match: Host(``) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))
      kind: Rule
        - name: api@internal
          kind: TraefikService
        - name: basic-auth
    - match: Host(``) && PathPrefix(`/`)
      kind: Rule
        - name: whoami
          port: 80
    secretName: wildcard-yongweilun-me-tls # -> the tls secret is applied here
kubectl apply -f ingress-route-cert-manager.yaml

If you need to see the error log , if there is any, can check with kubectl. If any error with ingress route, it will be visible here.

kubectl logs -f deployment/traefik -n traefik

Verify the certificate

Screenshot 2020-11-25 at 10.30.23 PM.png

Clean up

All cloud resources cost money, make sure you clean up after experiment.

cd terraform/gke-traefik-cert-manager
terraform destroy

The source code can be view at cncf-demo. That's all for today, if you have any feedback, feel free to comment below.


No Comments Yet