This article shows how to secure the deployment of 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.
Actions 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.
Architecture
Architecture securing web app with cert-manager and let`s encrypt : Image reference : https://medium.com/geekculture/aks-with-cert-manager-f24786e87b20
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
Update your local Helm chart repository cache
helm repo add jetstack https://charts.jetstack.io
Install CRDs with kubectl
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.7.1/cert-manager.crds.yaml
Install Cert-Manager with Helm Chart
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: youreemail@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.
Renewal
Let’s Encrypt certificates have a validity period of 90 days, and it is recommended to renew them every 60 days to ensure that there is enough time to complete the renewal process before the certificate expires. Let’s Encrypt provides an automated mechanism for renewing certificates called ACME (Automated Certificate Management Environment) protocol, which is supported by Cert-manager.
When you configure Cert-manager to use Let’s Encrypt as a certificate issuer, it will automatically request and renew certificates using the ACME protocol. Cert-manager will handle the entire renewal process, including validating domain ownership and updating the certificate in Kubernetes secrets.
This automatic renewal process ensures that your TLS/SSL certificates are always up to date, reducing the risk of certificate expiration and potential security vulnerabilities.