Secure AKS Ingress with LetsEncrypt

Shailender Choudhary
Dev Genius
Published in
4 min readMar 3, 2022

--

This article shows how to deploy the NGINX ingress controller in an Azure Kubernetes Service (AKS) cluster. The ingress controller is configured with a static public IP address on Azure Standard Load Balancer. The cert-manager project is used to automatically generate and configure Let’s Encrypt certificates. A custom domain will be integrated with a certificate to run the application publicly.

Steps to be performed:

  • Create a namespace ingress-basic for Ingress Controller where all ingress controller-related resources will be created.
  • Create a DNS Zone and Alias record for the custom domain.
  • Install cert-manager for SSL certificates in ingress-basic namespace using Helm.
  • Create a CA cluster issuer for issuing certificates.
  • Create first application and service.
  • Create Second application and service.
  • Create an ingress route to configure the rules that route traffic to one of the two applications.
  • Verify the automatic created certificate.
  • Test the applications using Custom Domain.

Create an ingress controller

# Create a namespace for ingress resources
kubectl create namespace ingress-basic

# Add the Helm repository
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# Use Helm to deploy an NGINX ingress controller
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-basic \
--set controller.replicaCount=2

Create DNS Zone and A record

A record of custom domain will be the Public IP of Ingress Controller.

Install cert-manager

# Label the cert-manager namespace to disable resource validation
kubectl label namespace ingress-basic cert-manager.io/disable-validation=true
# Add the Jetstack Helm repository
helm repo add jetstack https://charts.jetstack.io
# Update your local Helm chart repository cache
helm repo update
# Install CRDs with kubectl
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.7.1/cert-manager.crds.yaml
# Install the cert-manager Helm chart
helm install cert-manager jetstack/cert-manager \
--namespace ingress-basic \
--version v1.7.1

Create a CA cluster issuer

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: shailender.choudhary@gmail.com
privateKeySecretRef:
name: letsencrypt
solvers:
- http01:
ingress:
class: nginx
podTemplate:
spec:
nodeSelector:
"kubernetes.io/os": linux

To create the issuer, use the kubectl command.

kubectl apply -f cluster-issuer.yaml --namespace ingress-basic

Run demo applications

Create a aks-helloworld-one.yaml file and copy in the following example YAML:

apiVersion: apps/v1
kind: Deployment
metadata:
name: aks-helloworld-one
spec:
replicas: 1
selector:
matchLabels:
app: aks-helloworld-one
template:
metadata:
labels:
app: aks-helloworld-one
spec:
containers:
- name: aks-helloworld-one
image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
ports:
- containerPort: 80
env:
- name: TITLE
value: "Welcome to Azure Kubernetes Service (AKS)"
---
apiVersion: v1
kind: Service
metadata:
name: aks-helloworld-one
spec:
type: ClusterIP
ports:
- port: 80
selector:
app: aks-helloworld-one

Create a aks-helloworld-two.yaml file and copy in the following example YAML:

apiVersion: apps/v1
kind: Deployment
metadata:
name: aks-helloworld-two
spec:
replicas: 1
selector:
matchLabels:
app: aks-helloworld-two
template:
metadata:
labels:
app: aks-helloworld-two
spec:
containers:
- name: aks-helloworld-two
image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
ports:
- containerPort: 80
env:
- name: TITLE
value: "AKS Ingress Demo"
---
apiVersion: v1
kind: Service
metadata:
name: aks-helloworld-two
spec:
type: ClusterIP
ports:
- port: 80
selector:
app: aks-helloworld-two

Run the two demo applications using kubectl:

kubectl apply -f aks-helloworld-one.yaml --namespace ingress-basic
kubectl apply -f aks-helloworld-two.yaml --namespace ingress-basic

Create an ingress route

The ingress resource configures the rules that route traffic to one of the two applications.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-world-ingress
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt
nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
tls:
- hosts:
- mydevsecops.com
secretName: tls-secret
rules:
- host: mydevsecops.com
http:
paths:
- path: /hello-world-one(/|$)(.*)
pathType: Prefix
backend:
service:
name: aks-helloworld-one
port:
number: 80
- path: /hello-world-two(/|$)(.*)
pathType: Prefix
backend:
service:
name: aks-helloworld-two
port:
number: 80
- path: /(.*)
pathType: Prefix
backend:
service:
name: aks-helloworld-one
port:
number: 80

Create the ingress resource using the kubectl:

kubectl apply -f hello-world-ingress.yaml --namespace ingress-basic

Verify certificate

To verify that the certificate was created successfully, use the kubectl describe certificate tls-secret --namespace ingress-basic command.

Test the ingress configuration

Open a web browser to the FQDN of your Kubernetes ingress controller, such as https://mydevsecops.com/hello-world-one and https://mydevsecops.com/hello-world-two

Now the applications are secured using TLS certificate and are reachable using the custom domain. Applications are also getting host based routing using ingress controller.

--

--