Leverage Terraform, NGINX Ingress Controller, cert-manager and Let's Encrypt to quickly create a Kubernetes cluster which can serve webapps over HTTPS.
In this post I demonstrate how easy it has become to create a kubernetes cluster which serves webapplications over HTTPS.
In order to follow along you should clone the sample code from this repository:
git clone https://github.com/timvw/sample-terraform-azure-k8s-nginx-letsencrypt
export ARM_CLIENT_ID="XXXXX-XXXXX-XXXXX-XXXXX-XXXXX" export ARM_CLIENT_SECRET="XXXXX-XXXXX-XXXXX-XXXXX-XXXXX" export ARM_SUBSCRIPTION_ID="XXXXX-XXXXX-XXXXX-XXXXX-XXXXX" export ARM_TENANT_ID="XXXXX-XXXXX-XXXXX-XXXXX-XXXXX"
The resources in this example depend on the following variables: client_id, client_secret, aks_service_principal_app_id and aks_service_principal_client_secret. One way to configure them is by exporting their values as a TF_VAR_xxx:
export TF_VAR_client_id=$ARM_CLIENT_ID export TF_VAR_client_secret=$ARM_CLIENT_SECRET export TF_VAR_aks_service_principal_app_id=$ARM_CLIENT_ID export TF_VAR_aks_service_principal_client_secret=$ARM_CLIENT_SECRET
With all this configuration in place we can instruct Terraform to create the kubernetes cluster:
terraform init terraform apply -auto-approve
After a couple (~10) of minutes your cluster will be ready. Importing the credentials into your ~/.kube/config can be done as following:
az aks get-credentials --resource-group k8s-test --name kaz
kubectx is an awesome tool that allows you to easily switch between contexts.
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.28.0/deploy/static/mandatory.yaml kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.28.0/deploy/static/provider/cloud-generic.yaml
Deploying the NGINX Ingress Controller results in the creation of a loadbalancer and a public ip. Here is how you can fetch that address:
az network public-ip list | grep -Po '(?<="ipAddress": ")([^"]*)'
In this example we want to access our applications as https://XXX.apps.icteam.be. We achieve this by adding an A-record (the azure public ip address) pointing to *.apps.icteam.be
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v0.13.0/cert-manager.yaml kubectl apply -f letsencrypt.yaml
With all this infrastructure in place we can deploy a sample application:
kubectl create deployment hello-node --image=gcr.io/hello-minikube-zero-install/hello-node kubectl expose deployment hello-node --port=8080 kubectl apply -f ingress.yaml
Now we can access our application:
curl -v https://hello-node.apps.icteam.be
Here are some useful commands to help with debugging:
# get some cluster info kubectl cluster-info kubectl proxy # follow logs of the ingress controller kubectl logs -n ingress-nginx deployment/nginx-ingress-controller -f # restart the ingress controller kubectl scale deployment -n ingress-nginx --replicas=0 nginx-ingress-controller kubectl scale deployment -n ingress-nginx --replicas=1 nginx-ingress-controller
Remove the hello-node application (pods/deployment/service/ingress):
kubectl delete all -l app=hello-node
Finally you want to remove everything:
terraform destroy -auto-approve