Struggling with certificates can be a headache, but luckily for us in Kubernetes we can use cert-manager and let it manage everything to easily create any certificate that we need.

In this how-to we will cover how to install cert-manager in our cluster as well as how to perform HTTP validation. We will also learn how to create a new certificate for our host by just appending an annotation to our ingress object.

Sounds good! What do I need?

I expect you to meet the following requirements:

Let’s start!

First of all we need to add the helm chart repository for cert-manager:

helm repo add jetstack https://charts.jetstack.io

Now, we proceed to create the namespace and deploy cert-manager in it:

kubectl create ns cert-manager
helm upgrade --install cert-manager 
  --namespace cert-manager 
  --version v1.0.3 
  jetstack/cert-manager 
  --set installCRDs=true

Just give it a few seconds to finish and you should receive a success message.

Creating a ClusterIssuer

We can use either an Issuer or a ClusterIssuer (namespace vs cluster-scoped). It’s the same exact thing, only changes the scope. The Issuer/ClusterIssuer represents the CA from which we want to get the new certificate, in this case we are using LetsEncrypt.

Note that the ClusterIssuer is actually a pretty simple object. The name and the secret name can be anything:

apiVersion: cert-manager.io/v1alpha3
kind: ClusterIssuer
metadata:
  name: my-cluster-issuer
spec:
  acme:
    email: {{ your email }}
    privateKeySecretRef:
      name: my-cluster-issuer
    server: https://acme-v02.api.letsencrypt.org/directory
    solvers:
      - http01:
         ingress:
           class: nginx

Issuing a new certificate

We are going to deploy a simple nginx, expose it as a service and then create an ingress for it. So, go ahead:

kubectl create deployment nginx --image nginx:alpine --namespace test
kubectl expose deployment nginx --port 80 --target-port 80 --namespace test

Create a new ingress object to make it accessible through the ingress controller. Remember to replace with your actual domain in all ocurrences:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  labels:
    app: nginx
  name: nginx
  namespace: test
spec:
  rules:
  - host: nginx.{{ your domain }}
    http:
      paths:
      - backend:
          serviceName: nginx
          servicePort: 80
        path: /
  tls:
  - hosts:
    - nginx.{{ your domain }}
    secretName: nginx-certificate

Apply the new manifest:

kubectl apply -f ingress.yaml

If you try to access now to the host defined in the ingress, you’ll see an error message stating that “Your connection is not private”. To fix this, we are going to issue a new certificate. Edit the ingress that you just created and add the following annotation, replacing the value for whichever was the name you put in your ClusterIssuer:

cert-manager.io/cluster-issuer: my-cluster-issuer

Apply the ingress again (or save changes if your editing it) and now try to check the “cert” objects. You should get something like this:

kubectl get cert -n test

NAME                READY   SECRET              AGE
nginx-certificate   False   nginx-certificate   21s

Now wait for about 1 or 2 minutes and when you check again…

kubectl get cert -n test

NAME                READY   SECRET              AGE
nginx-certificate   True    nginx-certificate   93s

…we got our certificate! Go test it by refreshing the page or just opening a new tab and you should get the Nginx welcome screen. If you inspect the certificate you’ll see that it was indeed issued by LetsEncrypt:

Nginx letsencrypt certificate by cert-manager

Summarizing

What we saw here is:

It was pretty easy overall, don’t you think so? In fact, when you know what to do you can easily replicate this setup virtually to any cluster in a matter of very few minutes.

Cert-manager will take care of all your certificate renewals. You can also create other Issuers or ClusterIssuers that support other CA or use other validation methods (DNS validation) but this is a more advance topic for the future.

I hope that you enjoyed this how-to and that it will be useful to you. Remember that if you need anything we will be glad to hear from you! Also check our blog for more useful posts like this one!

Leave a Reply

Your email address will not be published. Required fields are marked *