GCP HTTPS Load Balancer with Let’s Encrypt certificate

  • Google managed certificate does not allow us to use wildcard domain like “*.yourdomain.com”.
  • Adding new domains to the existing Google managed certificate might not be easy. It needs more steps to do compare to the self managed certificate.

Prerequisites

This article won’t go too much in details about what the certificate is, what the Kubernetes ingress is. We will assume that the following knowledges are already in place:

  • Helm — We will use it to deploy the Nginx ingress controller and Cert Manager on GKE.
  • cert-manager — The tool that we use for obtaining the certificates from Let’s Encrypt issuer, but not limit to. We will not go too much about how to setup it but will provide the ready to use YAML files that make cert-manager able to talk to Let’s Encrypt and help Let’s Encrypt to perform DNS challenge with Cloud DNS.
  • Cloud DNS — We will use Cloud DNS to manage the domain demonstrated in this article.
  • Services in Google Cloud Platform (GCP) knowledges for example, firewall, GKE and HTTPS load balancer.
  • We assume that you already have your own domain that you can add the “A” records. I will use my own its-software-services.com domain.
  • Kubernetes knowledge.

Source Code

The source codes relate to this article are kept publicly in the GitHub repository here — https://github.com/its-knowledge-sharing/setup-gke-lb-lets-encrypt. I would recommend to clone the code and read them at the same time you read this article.

Create the GKE cluster

I’m assuming that we are familiar to the Google Cloud Platform (GCP) and already have the GCP account. See this script for more detail 01-setup-gke.bash.

gcloud container clusters create gke-lets-encrypt --zone us-central1-a --project ${PROJECT}
gcloud container clusters get-credentials gke-lets-encrypt --zone us-central1-a --project ${PROJECT}

Create service account (SA)

To allow cert-manager to perform the DNS challenging with Let’s Encrypt, we will need to provide the SA for cert-manager to talk to Cloud DNS. The cert-manager will actually add the TXT record (value received from Let’s Encrypt) to domain we hosted in the Cloud DNS. This will make Let’s Encrypt trusts that we’re indeed the owner of the domain we want it to issue the certificate.

gcloud iam service-accounts create ${SA_NAME} --project ${PROJECT} --display-name="Service account for GKE"
gcloud projects add-iam-policy-binding ${PROJECT} \
--member="serviceAccount:${SA_NAME}@${PROJECT}.iam.gserviceaccount.com" \
--project ${PROJECT} \
--role="roles/dns.admin"

Create DNS zone in Cloud DNS

In this article we will use the subdomain demo1.its-software-services.com and test1.demo1.its-software-services.com for Let’s Encrypt to issue the certificate. We will create DNS managed zone “demo1” and later the “A” record will be put here. We don’t have any script to create the DNS zone, we need to create it manually as shown below.

Create external IP and “A” record

To make the outside world able to connect to our services on GKE, we will need to create the external IP address first and then map it to the domain demo1.its-software-services.com and test1.demo1.its-software-services.com. Later we will assign this IP address to the HTTPS load balancer.

#!/bin/bashsource .env
IP_NAME=ingress-ip-1
# Create IP
gcloud compute addresses create ${IP_NAME} \
--global \
--ip-version IPV4 \
--project ${PROJECT}
IP=$(gcloud compute addresses describe ${IP_NAME} --global --project=${PROJECT} | grep 'address:' | cut -d':' -f2)gcloud dns record-sets transaction add ${IP} \
--name=${DOMAIN1} \
--ttl=300 \
--type=A \
--zone=${MANAGED_ZONE1} \
--project ${PROJECT}
gcloud dns record-sets transaction add ${IP} \
--name="test1.${DOMAIN1}" \
--ttl=300 \
--type=A \
--zone=${MANAGED_ZONE1} \
--project ${PROJECT}

Deploy cert-manager to GKE

The easiest way we deploy cert-manager into Kubernetes is by using Helm. The cert-manager also provided it’s own Helm chart here https://charts.jetstack.io/. What we need to do is to create the Helm values file to customize what we need and run some Helm commands to get everything.

# Create service account secretgcloud iam service-accounts keys create ${KEY_FILE} --iam-account=${SA}kubectl delete secret ${SECRET} -n ${NS}
kubectl create secret generic ${SECRET} --from-file=${KEY_FILE}=${KEY_FILE} -n ${NS}
helm repo add cert-manager https://charts.jetstack.io/
helm template cert-manager cert-manager/cert-manager \
-f cert-manager/cert-manager.yaml \
--version 1.7.1 \
--namespace ${NS} > tmp-cert-manager.yaml
kubectl apply -n ${NS} -f tmp-cert-manager.yaml
CLUSTER_ISSUER_FILE=cert-manager/cluster-issuer.yaml
cp ${CLUSTER_ISSUER_FILE} ${CLUSTER_ISSUER_FILE}.tmp
sed -i "s#__PROJECT__#${PROJECT}#g" ${CLUSTER_ISSUER_FILE}.tmp
kubectl apply -n ${NS} -f ${CLUSTER_ISSUER_FILE}.tmp

Deploy Nginx ingress controller to GKE

We will need to deploy Nginx ingress controller and we will use it to be the backend of the Google HTTPS load balancer. The ingress controller will act like the entry point to serve the traffics come from Google HTTPS load balancer, the traffics will then be routed to the backend services in GKE depended on how we configure the controller.

Create Let’s Encrypt certificate

Now it is the time to create the certificate. By Kubernetes point of view, the certificate is just the Secret resource with type kubernetes.io/tls. We will create the Cluster resource as shown below in order for cert-manager to request Let’s Encrypt to issue the certificate.

Create HTTPS load balancer via Kubernetes Ingress resource

Now it is time to deploy the certificate we created earlier to Google HTTPS load balancer. To create the load balancer, we will create the Ingress resource as show below.

Add new subdomain

Let’s assume the situation that we need a new subdomain to be added into the certificate. Actually, we won’t be able to modify the existing certificate that has been issued, we need to modify the existing Certificate resource (no need to change the resource name) instead.

Certificate renewal

Let’s Encrypt normally issues the 90-days valid certificate. Fortunately, cert-manager will keep checking to see if the certificates soon to expire or not. If yes, it will resubmit the request for new certificate from Let’s Encrypt. Once the new certificate is available, the GKE cloud controller will detect this and will propagate the new certificate to GCP HTTPS load balancer.

Supports

Congratulation!!! if you’ve read the entire article and it is able to help you solve your issues. You can support me by:

  • Follow me.
  • Buy me a coffee via ADA address below if you want.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store