HTTPS with Cert-Manager on GKE
At some point, typically around release time, you start worrying about things like HTTPS and how to expose your application to the outside world. You have a few options in how you can create and manage your certificates for your domain, but really the best way is the way that you don’t have to manage that stuff — meaning using Cert-Manager and Lets Encrypt within your Cluster.
I want to point out that everything that I’m writing in this article is out there in the wild, I just found it to be obscure and spread out, so after finally figuring it out the first time, and then repeating the process again and again for over a month, I felt it was helpful to write out in one place and hopefully save someone else the hassle when releasing code at 4 am.
If you haven’t gone through or even read the first part of this series you might be lost, have questions where the code is, or what was done previously. Remember this assumes you’re using GCP and GKE. I will always provide the code and how to test the code is working as intended.
HTTP01 vs DNS01
If you go read the documents, and you should at some point, you’ll see there are two ways that you can validate that you are the owner of your domain and that Cert-Manager should install the right certificate into your Cluster: HTTP01 and DNS01.
With HTTP01 you have to have everything set in just the right order so that Cert-Manager and Let’s Encrypt can validate that your site is up and running before issuing your certificate. Furthermore, you must have something available at the root of your domain or the validation will fail.
With DNS01 you have to create a Service Account with GCP and provide the information to Cert-Manager so that Let’s Encrypt can talk directly to your DNS to validate the domain.
I’ll tell you now, DNS01 may seem harder but it is the MUCH easier way to go. Just use DNS01.
Starting this process I am assuming you have a Kubernetes cluster with a Deployment and Service and that is it. Obviously, you can have more but later in this article we will add the Ingress. Okay, let’s get started.
Create A Service Account
Since we are going the easy route and using DNS01 validation we first need to create a Service Account. This is a multistep process, first creating a Service Account in GCP, downloading that account, and using the downloaded account as a secret in your Kubernetes cluster.
First, creating a Service Account in Google Cloud Shell.
Create The Certificate’s Secret
With this file downloaded, we just need to turn it into a secret within your Kubernetes cluster.
With the Service Account stored securely as a secret within your Kubernetes cluster you are ready to move to the next step and create a Certificate Issuer for Let’s Encrypt and Cert-Manager.
Install Helm and Cert-Manager
Now we need to actually install Cert-Manager into your Kubernetes cluster. To do this we will use Helm since it makes complex installs a breeze. If you are unfamiliar with Helm you should check out another post on the matter.
Assuming you have Helm installed in your Kubernetes cluster, we can install Cert-Manager with a single line of code. Magic!
Really it is amazing how much you can do in just a few lines of code. We are over half way there and the hard parts are all done!
Apply The Issuer
When working with Let’s Encrypt, it is required that you provide Let’s Encrypt with contact information for the certificate issuer. What’s wonderful is that Cert-Manager handles the communication with Let’s Encrypt for you, so as long as you provide an Issuer file to your Kubernetes cluster the rest is handled for you.
Let’s look at the Issuer file you’ll need to create.
This creates a Staging and Production ClusterIssuer
file to be used with Cert-Manager. We will only really use the Production ClusterIssuer
file, but the other is nice to have if you want to use it. The important thing is to update the email address to be a contact for your organization.
With this file ready we just need to apply it to our cluster.
Easy peasy! Next step is to create the actual certificate.
Apply The Certificate
Now is the really exciting part — that also requires a bit of patience. We will create a new certificate that will initiate a request through Cert-Manager to Let’s Encrypt to get the TLS certificate.
Like the Issuer, first, we create the Kuberenetes file.
And then we apply the file.
Now the really exciting stuff starts happening. You can watch the progress by continuously running the following command.
Over and over we call this function and watch as Cert-Manager communicates with Let’s Encrypt on our behalf. If you messed up on the ClusterIssuer
or the Certificate
this is the time you’ll find out. By reading the output we may find that the domains are setup improperly or a handful of other issues. These are easy to fix and redeploy the files. Whenever you redeploy any files make sure to also redeploy the certificate.yaml.
After about 10–15 minutes you will finally see the most amazing output that you could hope for, a successful message!
It really is magical! With this done we have just a few more simple steps and we can put down our 4 am work!
Create A Global IP Address
For all this to work we need to create a fixed IP Address for your Kubernetes Cluster to use for all of its Ingress needs. The default IP Address provided to a Kubernetes Cluster by GKE is ephemeral, meaning that it changes whenever it wants, so that doesn’t work. We need to create a static IP Address within GCP for your Cluster. This is really easy and one line of scripting.
This can take a moment but you’ll have your IP Address to route to with your DNS — more about that next.
Point Your Domain To Your IP Address
With your IP Address in hand, we now need to go to your DNS and set the DNS name to point to your IP Address. For my needs, I’m using Cloud DNS as part of GCP. I’m not going to go through these steps as Google did a good job documenting the steps in their Quickstart. Basically, just point your IP Address to the DNS Entry using a CName.
Include TLS With Your Ingress
Through this whole process, we assumed you had a Deployment and a Service, now we are adding the Ingress resource to route to your Service.
This sets up a secure path to your host that all of your services can use utilizing the secrets that are managed by your my-certs
certificate. You’re done!
Conclusion
This is a lot of steps, but they are worth it. Especially since now your SSL certificate will automagically be managed by Cert-Manager and issued by Let’s Encypt without you having to worry about it. You get all of the security without the ongoing headache. This is worth the one-time setup cost.
If you ran through this and had any issues feel free to reach out. I know that this can be complicated and have now gone through these steps many, many, many times.
Jonathan Campos is an avid developer and fan of learning new things. I believe that we should always keep learning and growing and failing. I am always a supporter of the development community and always willing to help. So if you have questions or comments on this story please add them below. Connect with me on LinkedIn or Twitter and mention this story.