TLS Configuration in GKE the (really) simple way
We all know that our websites and API’s should be served using TLS/HTTPS, right? The problem is, historically that’s meant the pain of OpenSSL, CSR’s, X.509 digital certificates, and a whole heap of operations overheads. Plus, of course, the cost of all those certificates your enterprise needed added up quickly. And then, the inevitable downtime when someone missed an expired certificate. If big players like Microsoft and LinkedIn can get it wrong, what chance do the regular guys have?
The good news is, assuming you’re working with GKE as your container orchestrator there’s now a really simple option to manage the certificates providing TLS for your ingresses. And better yet, you end up with high quality certificates for free! So there really is no reason not to go all in on TLS.
Note: this is the simplest option for GKE, but if you are using another K8s environment like Azure AKS, or a private K8s cluster, you can get similar features from the Cert-Manager project. It’s a little more work to set up, but well worth it!
There are a few basic requirements your cluster needs to fulfil for the approach here to work.
- Your cluster needs to at Kubernetes v1.10 or greater
- You need to be using the default GKE Ingress, that provision a Google Cloud Load Balancer
If you can’t match all of these, don’t worry; it’ll be a little tougher, but the Managed Certificated that Google Cloud Platform provides can always be set up by hand — I’ll cover that another time. For now, let’s assume that you’re cool with these requirements, and get our cluster ready to go.
To get the cluster ready, we need to add a Custom Resource Definition to manage our certificates, and some code to handle the integration with LetsEncypt, who will handle providing the certificates.
The install is pretty straight forward, first clone Git repo containing the deployment scripts. Navigate to the
deploy folder, and with kubectl connected to your cluster install the CRD
kubectl apply -f managedcertificates-crd.yaml
And then install the controller and RBAC settings
kubectl apply -f managed-certificates-controller.yaml
You should now be able to issue the following command,
kubectl get managedcertificates
and see that there are no managed certificates in the cluster. If you get an error that the cluster doesn’t have a ManagedCertificate resource, something in the above install failed.
Enable TLS for an Ingress
Now that the cluster is set up ready to communicate with LetsEncrypt, we can configure our ingress to use the certificate to provide TLS support for the load balancer that the ingress controller creates.
First, ensure that the public IP of the ingress has an DNS A record for the domain your want to secure.
Now create a ManagedCertificate in the cluster for this domain
Now we can add an annotation to the ingress, which ties it up with the managed certificate.
kubectl annotate ingress [your-ingress-name] networking.gke.io/managed-certificates=mydomain-certificate
If you re-run the command to list managed certificates in the cluster, you should now see the
mydomain-certificate in the cluster, and that it’s in the Provisioning state. It should take somewhere betwean 15 and 30 minutes for the certificate to be issue, at which point the state will change to Active, and TLS will be enabled in the load balancer, and available to your users.
Here’s the great news. If you check your certificate in a browser, you’ll see it has a three month expiry, typical of LetsEncrypt certificates. Googles ManagedCertificate will handle tracking this expiry, and automatically ensure the certificate is renewed before it expires. No muss, no fuss, and no accidental downtime!
Support for TLS/HTTPS is a must have now, very soon browsers will start flagging any HTTP site as ‘potentially insecure’, which is going to put users off. By using GCP’s Managed Certificates, and a little bit of Kubernetes magic, we can ensure that we provide great TLS support, with no management overhead, and no cost. There really is no reason not to go TLS…