SSL Using Let’s Encrypt CA on AKS

Phylypo Tum
7 min readJan 16, 2022

--

This tutorial is part of the series on server certificates to secure websites with HTTPS.

  1. First, we look at how to automate the creation of certificates from your company Certificate Authority (CA) on Windows OS.
  2. Then we look at how to use free issuer “Let’s Encrypt” to generate the certificate on Windows and Linux.
  3. Now in this tutorial, we will look into setting up a certificate on Kubernetes.

In this step-by-step tutorial, we are going to set up SSL/TLS on the Ingress Controller using Nginx-ingress to handle HTTPS traffic to the Kubernetes service running on Azure Kubernetes Service (AKS). The certificate we are using is issued by Let’s Encrypt, a free service running as an Automated Certificate Management Environment (ACME) by using cert-manager.

The code is mainly based on the tutorial by Marcel Dempers in the reference section but updated for Kubernetes running on Azure cloud or Azure Kubernetes Service (AKS) rather than running locally using miniKube or Kind.

The source code can be found here: https://github.com/phylypo/kubernetes

Let’s Get Started

We assume you have Azure account to create resources like AKS. So first, log in to the Azure portal. We will be using Azure API to run all of our commands by using Cloud Shell. Click on the Cloud Shell icon as highlighted below. If this is the first time running Cloud Shell, you need to set up a storage account first.

After you launched Cloud Shell, you should see the terminal like below.

Now you can clone the code from this project in GitHub that contains the source code so you can follow along.

git clone https://github.com/phylypo/kubernetes.git
cd kubernetes/cert_devops

The directory cert_devops contains the configuration files that are needed for this tutorial. All the commands are in cert_devops.sh file.

Create AKS cluster

First, we need to create an Azure Kubernetes Cluster. We are going to use a new resource group “k8rg” to place all our resources which can be easily cleaned up afterward.

az group create --name k8rg --location westus2
az aks create --resource-group k8rg --name myAKSCluster --node-count 1

The last command can take a few minutes. Once done we want to set up the credential for kubectl. The get-credentials commands will ask to override or merge the configuration if the config exists. Then we can test out the kubectl commands.

az aks get-credentials --resource-group k8rg --name myAKSCluster
# test kubectl
kubectl get pod
kubectl get services

Install Cert-Manager

Now install cert-manager to handle certificate creation. We will test with a self-signed certificate first to ensure cert-manager is working properly. Then proceed with Let’s Encrypt in the later section.

kubectl apply --validate=false -f cert-manager.yaml
kubectl -n cert-manager get all

Create a self-signed certificate to test the cert-manager.

# create a test namespace 
kubectl create ns cert-manager-test
# create a self sign issuer
kubectl apply -f ss_issuer.yaml
# create certificate
kubectl apply -f ss_certificate.yaml

Now verify that the certificate is created.

kubectl describe certificate -n cert-manager-test
kubectl get secrets -n cert-manager-test
# cleanup by deleting the namespace and testing resources
kubectl delete ns cert-manager-test

Create Ingress Controller

We are going to create an Ingress Controller in the namespace “ingress-nginx”.

kubectl create ns ingress-nginx 
kubectl -n ingress-nginx apply -f deploy-ingress-ctl.yaml
# see all the different components created
kubectl -n ingress-nginx get all

Now browse to the public IP to see if the ingress is showing the nginx reponse. From the screen above, it is in the service output under the EXTERNAL-IP which is 20.64.143.87. You should see “404 Not Found” message from nginx since we have not configured the ingress controller.

Setup DNS

Now we can set up our DNS that will be used in the URL to point to this IP address. This Ingress Controller listens to both ports 80 and 443 for HTTPS.

Here is an example for my DNS cert.tovnah.com to point to this IP. This change may take some time to propagate depending on your service provider. Mine took about 15 mins. You can verify by checking nslookup command (nslookup cert.tovnah.com) and you should see the new ip address you updated.

Setup Let’s Encrypt Issuer

Now we will set up the certificate issuer, in this case, we use “Let’s Encrypt” that will be signing our certificate.

kubectl apply -f cert-issuer-nginx-ingress.yaml 
kubectl describe clusterissuer letsencrypt-cluster-issuer

Now we can deploy a test app for the ingress controller to forward the traffic.

kubectl apply -f deployment-app.yaml
kubectl apply -f service-app.yaml
kubectl get pods

Next, we need to point the ingress controller to this app. First edit ingress.yaml and replace “<your.dns.com>” with the correct hostname in my case “cert.tovnah.com”.

code ingress.yaml
kubectl apply -f ingress.yaml
kubectl get servies

Now browse to our new app and we should see the “Hello World!” message using the public IP of the app.

Setup Certificate

Now, we will create a certificate that will be issued by Let’s Encrypt issuer.

# first edit the certificate.yaml by updating the dns name
code certificate.yaml
kubectl apply -f certificate.yaml

Verify that the certificate is created successfully.

kubectl describe certificate example-app

You should see the last entry if a successful message in the Events section.

The certificate has been successfully issued

Check secret and should see the type: kubernetes.io/tls

kubectl get secret

Now test browsing to the DNS name and you should see the lock and valid certificate issued by Let’s Encrypt (R3).

Summary

We have looked at how to create a Kubernetes cluster, install cert-manager that allows us to use “Let’s Encrypt” to issue us a certificate. We deployed an nginx Ingress Controller and an example app in the Kubernetes cluster. Then we create a certificate to bind to the ingress controller that points to the example app. This allowed us to use HTTPS to access our app. We are using Azure API through Cloud Shell which allows us to run all the commands via a web browser.

This concludes our series on setting up server certificates. I hope this gives you a good understanding of setting up a certificate for your app.

To delete all of the resources in Azure that we have set up in this tutorial so that we don’t pay for the unused resources in Azure, we can simply delete the resource group that we initially created.

az group delete --name k8rg --yes --no-wait

If you follow the tutorial from Youtube below by creating your local Kubernetes cluster on your home machine, you need to make sure your router settings is forwarding the traffic on specific ports to your machine.

In the router settings, you need to open both 80 and 443 port forwarding to the machine IP. Notice that port 80 is needed for Let’s Encrypt challenges.

In my Linksys router it looks something like this under Security:

In addition, if you have McAfee running, you will need to disable McAfee Firewall temporarily. If you have the Windows firewall as your primary service, you will need to disable that.

--

--