Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Let's encrypt wildcard TLS certificates for Azure DNS using cert-manager on AKS (Azure Kubernetes Service)

This gist will guide you through the setup of a wildcard Let's encrypt TLS certificate.

Let's encrypt

Let’s encrypt is one of a new kind of Certificate Authority. You can get a TLS certificate from them for your website free of charge and without any manual overhead. These certificates are trusted in most browsers that are out there and will show up as valid. Instead of sending Mails or even paper around you can call an API and prove your domain ownership with simple challenges. Basically you call the API with a hostname or domain name you need a TLS certificate for and you get back a challenge string that you need to put in a well known location on your http host or as a txt record in your dns system.

The little helper for Kubernetes: Cert-Manager

You can find many clients that manage the process and keep your TLS certificates up to date. In the area of kubernetes I can highly recommend cert-manager which is the successor of kube-lego. It’s quite easy to deploy via the helm chart.

DNS01 Challenge with AzureDNS for a Wildcard Certificate

If you have a bigger installation which is more dynamic - hostnames come and go - you will hit rate limits pretty soon which will block your account from getting new TLS certificates for quite some time. If you for example want every developer to have a dedicated API endpoint in the cluster to test a micro service app you can create an isolated environment. So something like and should be deployable. If you are using the simple http proof you get the system up and running but you can’t scale the installation.

The cert-manager has the ability to use the dns proof with Azure-DNS and will create the TXT record and maintain the certificates. You pretty much don’t have to worry about the details.

Installation and Configuration

Cert-Manager via helm

First make sure to install the cert-manager helm chart in your cluster. You can follow along the guide on the cert-manager website.

Setup the Cluster-Issuer

Now it’s time to configure a ClusterIssuer that can be used to create certificates. As mentioned you can find the config for azure DNS here. You need to feed the API with the client id and client secret of a ServicePrinicipal that has the privilege to update DNS entries.

kind: ClusterIssuer
  name: letsencrypt-prod
    commonName: '*'
    - "*"
	server: ""
	  name: letsencrypt-prod
	  - name: azure-dns
		- '*'
		  clientID: "###CLIENT_ID###"
			key: client-secret
			name: azuredns-config
		  hostedZoneName: ""
		  resourceGroupName: "infrastructure"
		  subscriptionID: "###SUBSCRIPTION_ID###"
		  tenantID: "###TENANT_ID###"

Don’t forget to provide the client secret.

kubectl -n kube-system create secret generic azuredns-config --from-literal=client-secret="$CLIENT_SECRET"

Now you have configured how new tls certificates can be retrieved.

Setup the wildcard certificate

Now you can define a Certificate API object that describes the validity of the desired format. The format will be retrieved using the letsencrypt-prod ClusterIssuer defined by the issuerRef. The certificate will be placed in a secret named wildcard-domain-tls-secret that can be wired up to an ingress resource.

kind: Certificate
  name: wildcard-domain
  namespace: default
  secretName: wildcard-domain-tls-secret
	name: letsencrypt-prod
	kind: ClusterIssuer
  commonName: '*'
  - '*'
	- dns01:
		provider: azure-dns
	  - '*'

Use the wildcard certificate

And the final part is to use the wildcard certificate.

apiVersion: extensions/v1beta1
kind: Ingress
  name: {{ template "my-app.fullname" . }}-ingress
	type: infrastructure
	app: {{ template "my-app.fullname" . }}
	chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
	release: "{{ .Release.Name }}"
	heritage: "{{ .Release.Service }}"
  - host: {{ }}
	  - path: /
		  serviceName: {{ template "my-app.fullname" $ }}-frontend
		  servicePort: 80
  {{ if .Values.ingress.tls.enabled }}
  - hosts:
	- {{ }}
	{{ if .Values.ingress.tls.letsEncrypt }}
	secretName: wildcard-domain-tls-secret
	{{ else }}
	secretName: {{ template "my-app.fullname" $ }}-ingress-tls-frontend-secret
	{{ end }}
  {{ end }}

You see that I simply reference the certificate in the TLS section of the manifest. I needed to distinguish between a Let’s Encrypt environment and a self provisioned secret so I made the whole part switchable using variables.


Now you create new hosts in your environment without delays and any rate limits.

Copy link

Hi can you show a demo of this using istio gateway too ... instead of ingress

Copy link

Morgma commented Sep 20, 2019

@librannk Did you happen to find a good example of this? I've found plenty of standard Ingress also, but very view people using a proper Gateway with wildcard. Closest I've found to a working model is this (no wildcard, but AKS + Istio Gateway Ingress + LetsEncrypt).

Copy link

@librannk @Morgma The config I created here is unrelated to the ingress or gateway config. Just setup your istio gateway and point it to the tls secret which is provided by the cert-manager.

Btw: We moved from using cert-manager to the Traefik controller managing the Let's encrypt certificates for us.

Copy link

@Morgma: link shared by you was similar to something I did and is working fine, although auto-rotate of certificate is something which isn't working for me
@marcopage: Any benefits of using Traefic ?

Copy link

Sweet, nice piece of documentation. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment