How to set up SSL certificates to renew automatically using Google Cloud DNS and GCP Kubernetes

TL;DR: this is a small tutorial to deploy a pod in your Kubernetes cluster that will create and renew your SSL certificates automatically and store it inside a TLS secret using your Google Cloud DNS as a challenge provider.

Assumptions

  • You have a billing account enabled at your Google Cloud Platform.
  • You have a Kubernetes cluster up an running and knows the basics about deployments, pods, containers, etc.
  • You have access to your DNS provider (this post uses GC DNS but you can use other provider if you have the correct API Keys and secrets).
  • You’ve downloaded the deployment files here!

1. Install Helm & Tiller

You can find all the guide here but basically all you need is this, if you are on Linux:

$ sudo snap install helm --classic
$ helm init

PS: Ensure that you are using the desired cluster before initialize helm:

$ kubectl config get-contexts
$ kubectl config use-context [name-of-your-context]
# Check if it is running
$ kubectl get pods -n kube-system
NAME                          READY   STATUS    RESTARTS   AGE
cert-manager-7d4bfc44ff-nrbb4 1/1 Running 0 5d

2. Deploy the cert-manager in your cluster

Install it using Helm:

$ helm install \
--name cert-manager \
--namespace kube-system \
stable/cert-manager

3. Create the ClusterIssuer

This is how cert-manager will challenge your DNS provider using Let’s Encrypt API. Since we are using Cloud DNS as a provider we need a IAM service account key to manage DNS zones.

  • Create a Service Account with DNS Admin role in your GCP project
  • Download its JSON key
  • Deploy the key in you cluster as a secret
$ kubectl create secret generic clouddns \
--from-file=clouddns.key.json=[./PATH-TO-YOUR-KEY.json] \
--namespace=[YOUR-NAMESPACE]
  • Deploy the ClusterIssuer (I’m using the let’s encrypt production API)

Don’t forget to change the variables inside the YAML file before execute the command:

[YOUR-NAMESPACE]: The namespace you are using
[YOUR-EMAIL]
: Use a real email
[YOUR-PROJECT]: Your GCP project
$ kubectl apply -f clusterissuer-lets-encrypt-production.yaml
# You can check your cluster issuers with
$ kubectl get clusterissuer
NAME                     AGE
letsencrypt-production 5d
letsencrypt-staging 7d

4. Create the DNS Zone(s)

The DNS Zones will handle your DNS names. You can find it under the menu Network Services > Cloud DNS.

PS: Make sure your domain registrar points the NS records to this zone.

5. Deploy the certificate

Cert-manager will use the Certificate definition to request the certificate to the Issuer. In the example we are requesting a wildcard certificate for our domain. Change the variables for your needs and deploy it.

[CERTIFICATE-NAME]: The name of your certificate
[YOUR-NAMESPACE]: The namespace you are deploying your stuff
[SECRET-NAME]: The TLS secret name you are gonna use in your ingress file
[*.YOUR-FQDN.COM]: *.yourdomain.com
[YOUR-FQDN-DNS-ZONE-NAME]: The DNS Zone name that you created in the previous step. This is important when you have more than 1 DNS Zone.
$ kubectl apply -f certificate-wildcard-example.yaml
# You can check your cluster issuers with
$ kubectl get certificates --all-namespaces

6. Use ingress to request the SSL certificates

Once you deploy a Ingress file to use a TLS secret, cert-manager will match the secret name with a Certificate and request it to Let’s Encrypt. After the challenge is completed, cert-manager will create a TLS secret with that name and store the key and the certificate under it.

[INGRESS-NAME]: The name of your ingress
[YOUR-NAMESPACE]: The namespace you are deploying your stuff
[EXAMPLE.YOUR-FQDN.COM]: The domain, or sub-domain, you are using
[SECRET-NAME]: The secret name that you have created on the previous step
[SOME-SERVICE]: The backend pods/deployment you are routing this path.
[MY-SERVICE-PORT]: The port of the service
$ kubectl apply -f ingress-example.yaml

Wrapping up!

That’s it. Now you have a pod that will request certificates and renew them without worrying again. For now on, just deploy new certificates and ingress files.

You can always check the cert-manager logs to see if everything is going well

$ kubectl logs cert-manager-[SOME-GIBBERISH] -n kube-system

If you need different approaches and this is not your use-case, I’d recommend you to check this other tutorial here. The author brings 4 ways that you can work with SSL in Kubernetes.

See ya!