6.4. SSL Certificates
Step 6.4.1: Cert Manager installation
flowchart LR
classDef red fill:#f96
subgraph rg: aks
aAks(aks)
aIp(public ip)
end
dDns --> aIp
subgraph rg: dns
dDns(dns)
end
aAks --> aks
subgraph aks
aIp --> sNg
subgraph ns: nginx-ingress
sNg(service) --> pNg(pod)
end
subgraph ns: tests
sTst(service) --> pTst(pod)
pNg --> iTst(ingress) --> sTst
end
subgraph ns: cert-manager
sCm(service):::red --> pCm(pod):::red
end
endCreate a new file named cert_manager.tf and add the following content:
resource "kubernetes_namespace" "cert_manager" {
metadata {
name = "cert-manager"
}
}
resource "helm_release" "cert_manager" {
name = "cert-manager"
repository = "https://charts.jetstack.io"
chart = "cert-manager"
version = "1.18.2"
namespace = kubernetes_namespace.cert_manager.id
atomic = true
reset_values = true
set = [
{
name = "installCRDs"
value = "true"
},
{
name = "global.leaderElection.namespace"
value = kubernetes_namespace.cert_manager.id
},
{
name = "dns01RecursiveNameservers"
value = "9.9.9.10:53"
}
]
}
Now run
terraform apply -var-file=config/dev.tfvars
Step 6.4.2: Cluster Issuer
flowchart LR
classDef red fill:#f96
subgraph rg: aks
aAks(aks)
aIp(public ip)
end
dDns --> aIp
subgraph rg: dns
dDns(dns)
end
aAks --> aks
subgraph aks
aIp --> sNg
subgraph ns: nginx-ingress
sNg(service) --> pNg(pod)
end
subgraph ns: tests
sTst(service) --> pTst(pod)
pNg --> iTst(ingress) --> sTst
end
subgraph ns: cert-manager
sCm(service) --> pCm(pod)
pCm --> cCl(issuer):::red
end
endCreate a new directory structure:
mkdir -p helm/cert_manager_issuer/templates
Create a new file named helm/cert_manager_issuer/Chart.yaml and add the following content:
apiVersion: v2
name: cluster-issuers
description: Let's Encrypt cluster issuer for Cert Manager
version: 1.0.0
Create a new file named helm/cert_manager_issuer/templates/cluster_issuer.yaml and add the following content:
# https://cert-manager.io/docs/configuration/acme/dns01/azuredns/
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: noreply@labz.ch
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
Add the following content to the end of cert_manager.tf:
resource "helm_release" "cluster_issuer" {
name = "cluster-issuer"
chart = "${path.module}/helm/cert_manager_issuer"
version = "1.0.0"
namespace = kubernetes_namespace.cert_manager.metadata.0.name
atomic = true
reset_values = true
depends_on = [helm_release.cert_manager]
}
Now run
terraform apply -var-file=config/dev.tfvars
Explanation
Cert Manager needs to be configured with a ClusterIssuer Kubernetes resource.
This uses a Kubernetes CRD (Custom Resource Definition), which we deploy using a custom Helm chart.
The resource helm_release.cluster_issuer depends on helm_release.cert_manager because it deploys a CRD which
is registered by the Cert Manager, triggering a Kubernetes verification error (API unknown).
Step 6.4.3: Test HTTPS ingress
Create a new file named tests/https.yaml and add the following content:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: secure
namespace: tests
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- secure.YOUR_USERNAME.labz.ch
secretName: tls-secure
rules:
- host: secure.YOUR_USERNAME.labz.ch
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: hello
port:
number: 80
Note: Please replace YOUR_USERNAME with the username assigned to you for this workshop.
Now apply the config by running:
kubectl apply -f tests/https.yaml
Now use curl to access your service:
curl https://secure.YOUR_USERNAME.labz.ch
This should show the following output:
Server address: 10.244.0.11:80
Server name: hello
Date: 26/Mar/2025:14:19:30 +0000
URI: /
Request ID: f159d777a93e189c6955f31dde6dba38
Congratulations! You can now successfully expose a HTTP service via HTTPS.