Automatic LetsEncrypt SSL Registration for Kubernetes Using Cert-Manager

A

I don’t think many will argue that the status quo of security on the Internet today dictates that the use of SSL for web services is a must. This used to be quite a painful and expensive standard to maintain for many as SSL registration isn’t exactly cheap and requires ongoing maintenance of SSL certificates as they reach their expiration. Thankfully, in an effort to create a more secure Internet, there has been an advent of free ACME based SSL registration services such as LetsEncrypt. This project even took a lot of the headache out of the process by providing facilities to handle automatic renewal of these certificates since they are much shorter lived (3 months) than the traditional SSL certificates of one or more years. This is great until you start working with more modern environments that use container orchestration as opposed to the traditional bare metal or virtual machine based servers.

Enter Cert-Manager for Kubernetes. This is one of a number of projects that have provided a simple and reliable solution for bridging the gap in automation left by this transition. You should find that this tutorial will be rather short and sweet to achieving this goal. You do however need to make sure you have already implemented a proper ingress controller as this is a key dependency of making all of this work. If you haven’t done so yet, check out my tutorial on deploying the Nginx Ingress Controller for Kubernetes as that will get you where you need to be to make use of this.

Let’s jump right into it as this will go very quickly. Execute the following commands in a kubectl enabled environment to install Cert-Manager to your Kubernetes environment:

cm_version=$(curl --silent "https://api.github.com/repos/cert-manager/cert-manager/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/$cm_version/cert-manager.yaml

Now you need to create some ACME providers for Cert-Manager to use for SSL registration. For this tutorial, I will be focusing on the use of LetsEncrypt given it’s popularity. Execute the following commands after updating the “cm_email” value to an email address that you would like to receive LetsEncrypt expiration notifications at:

cm_email=your-alias@your-company.domain

echo 'apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt
spec:
  acme:
    email: '"$cm_email"'
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-production-account-key
    solvers:
    - http01:
        ingress:
          class: nginx' | kubectl apply -f -

echo 'apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    email: '"$cm_email"'
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-staging-account-key
    solvers:
    - http01:
        ingress:
          class: nginx' | kubectl apply -f -

That’s it! Now you’re ready to start deploying services and ingress controllers that receive automatic SSL registration. The previous commands will setup configuration for both the LetsEncrypt production and staging environments so you can test configurations before pounding the production instance with bad requests.

Let’s take a look at what a simple scenario using the Cert-Manager looks like to obtain a temporary SSL certificate from the LetsEncrypt staging environment. If you want to setup an ingress object to use the LetsEncrypt production environment, you just need to change the “letsencrypt-staging” string below to “letsencrypt” and update the object. I recommend you start out always using the staging environment first until you get the hang of the whole process through repetition.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: http-lb
  namespace: website-namespace
  annotations:
    kubernetes.io/tls-acme: "true"
    cert-manager.io/cluster-issuer: "letsencrypt-staging"
    cert-manager.io/issue-temporary-certificate: "true"
    acme.cert-manager.io/http01-edit-in-place: "true"
spec:
  rules:
  - host: your.website.domain
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: http-svc
            port:
              number: 80
  tls:
  - hosts:
    - your.website.domain
    secretName: http-lb-cert

It’s very important to remember that you need to have the DNS configuration complete and propagated before pushing one of these configurations to the Kubernetes environment. If you don’t then there is a good chance you will cause a negative query hit for the domain you’re trying to register SSL certificates for and that will take longer to clear out of the internal DNS cache. Thankfully, Cert-Manager has proper local verification features that will prevent the request from going to LetsEncrypt before all pieces are in place but that will not mitigate the aforementioned delay should you get ahead of yourself.

About the author

Add Comment

By Matt

Matt

Get in touch

If you would like to contact me, head over to my company website at https://azorian.solutions.