Skip to main content
  1. Posts/

Cert Manager and Letsencrypt

·882 words·5 mins
Kubernetes Certificate Cert-Manager Certificate Kubernetes
Andreas Marqvardsen
Author
Andreas Marqvardsen
Always curious, always learning
Table of Contents

This article will quickly go through how to create wildcard certificates and automatically renew them with Lets Encrypt and Cert-Manager

Cert-Manager
#

cert-manager adds certificates and certificate issuers as resource types in Kubernetes clusters, and simplifies the process of obtaining, renewing and using those certificates.

It can issue certificates from a variety of supported sources, including Let’s Encrypt, HashiCorp Vault, and Venafi as well as private PKI.

It will ensure certificates are valid and up to date, and attempt to renew certificates at a configured time before expiry. link

Install Cert-Manager
#

I prefer the Helm way so lets add the cert-manager helm chart:

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

Then we need to deploy cert-manager. This can be done out-of-the-box with the commands given from the official docs (this also installed the necessary CRDs):

helm install \
  cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.9.1 \
  --set installCRDs=true

Or if you need to customize some settings, as I needed to do, I used this command:

helm install -f /path/to/cert-manager.values.yaml cert-manager jetstack/cert-manager   --namespace cert-manager   --version v1.9.1   --set installCRDs=true --set 'extraArgs={--dns01-recursive-nameservers-only,--dns01-recursive-nameservers=xx.xx.xx.xx:53\,xx.xx.xx:53}'

The above command takes care of the cert-manager installation including the necessary CRDs, but it will also adjust the DNS servers Cert-Manager will use to verify the ownership of my domain.

DNS01 - Wildcard certificate
#

In this post I will go with wildcard certificate creation. I find it easier to use instead of having a separate cert for everthing I do, as long as they are within the same subdomain. So if I have my services in *.example.com they can use the same certificate. But if I have services in *.int.example.com I can not use the same certificate as LetsEncrypt certificates dont support that. Then you need to create a separate wildcard cert for each subdomain. But Cert-manager will handle that for you very easy.

The offiicial Cert-Manager supported DNS01 providers are:

There is also an option to use Webhooks. I did try that as my previous DNS registrar were not on the DNS01 supported list. I did not succeed with using the webhook approach. It could be an issue with the specific webhooks I used or even with my registrar so I decided to migrate over to CloudFlare which is on the supported list, “out of the box”.

Issuer - CloudFlare and LetsEncrypt
#

The first we need to do is to create a secret for Cert-Manager to use when “interacting” with CloudFlare. I went with API Token. So head over to your CloudFlare control panel and create a token for Cert Manager like this:

Here is the permissions:

Now use the tokens to create your secret:

apiVersion: v1
kind: Secret
metadata:
  name: cloudflare-api-token-secret
  namespace: cert-manager
type: Opaque
stringData:
  api-token:

Apply it kubect apply -f name.of.yaml

Now create your issuer. LetsEncrypt have two repos, one called staging and one production. Start out with staging until everything works so you dont hit the LetsEncrypt limit. In regards to this I created two issuers, one for staging and one for production. When everything was working and I have verified the certificates etc I deployed the certs using the prod-issuer.

Issuer-staging:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    # ACME Server
    # prod : https://acme-v02.api.letsencrypt.org/directory
    # staging : https://acme-staging-v02.api.letsencrypt.org/directory
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    # ACME Email address
    email: xxx.xxx@xxx.xxx
    privateKeySecretRef:
      name: letsencrypt-key-staging # staging or production
    solvers:
    - dns01:
        cloudflare:
          apiTokenSecretRef:
            name: cloudflare-api-token-secret ## created and applied above
            key: api-token

Issuer-production:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
  namespace: cert-manager
spec:
  acme:
    # ACME Server
    # prod : https://acme-v02.api.letsencrypt.org/directory
    # staging : https://acme-staging-v02.api.letsencrypt.org/directory
    server: https://acme-v02.api.letsencrypt.org/directory
    # ACME Email address
    email: xxx.xxx@xxx.xxx
    privateKeySecretRef:
      name: letsencrypt-key-prod # staging or production
    solvers:
    - dns01:
        cloudflare:
          apiTokenSecretRef:
            name: cloudflare-api-token-secret # created and applied above
            key: api-token

Request certificate
#

Now that the groundwork for cert-manager has been setup, its time to “print” some certificates. Prepare your yamls for both the staging key and production key.

Wildcard-staging:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: name-tls-test
  namespace: namespace-you-want-the-cert-in
spec:
  secretName: name-tls-staging
  issuerRef:
    name: letsencrypt-staging
    kind: ClusterIssuer
  duration: 2160h # 90d
  renewBefore: 720h # 30d before SSL will expire, renew it
  dnsNames:
    - "*.example.com"

Wildcard-production:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: name-tls-production
  namespace: namespace-you-want-the-cert-in
spec:
  secretName: name-tls-prod
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  duration: 2160h # 90d
  renewBefore: 720h # 30d before SSL will expire, renew it
  dnsNames:
    - "*.example.com"

Apply the staging request first. Check your certificate status with this command:

$ kubectl get certificate -n namespace-you-wrote 
NAME               READY   SECRET                AGE
name-tls-staging   True    name-tls-staging      8d

Please note that it can take a couple of minutes before the certificate is ready. This applies for production also.

If everything went well, delete your staging certificate and apply your production certificate with the production yaml. Thats it. Now Cert-Manager will take care of updating your certificate for your, sit back and enjoy your applications with your always up to date certificates.

Troubleshooting tips, commands
#

If something should fail there is a couple of commands you can use to figure out whats going on.

$ kubectl get issuer
$ kubectl get clusterissuer
$ kubectl describe issuer 
$ kubectl describe clusterissuer
$ kubectl describe certificaterequest
$ kubectl describe order
$ kubectl get challenges
$ kubectl describe challenges

For more detailed explanation go here

Related

Traefik Proxy in Kubernetes
·6012 words·29 mins
Kubernetes Network LoadBalancing Ingress Cert-Manager Proxy Traefik Loadbalancing Ingress
In this post I will go through how I have configured and run Traefik in my Kubernetes lab.
vSphere 8 with Tanzu using NSX-T & Avi LoadBalancer
·6151 words·29 mins
Kubernetes Tanzu Networking NSX AVI Tanzu Kubernetes Network Lodbalancing Ingress
Deploy Tanzu in vSphere 8 with NSX and Avi Loadbalancer: # This post will go through how to install Tanzu in vSphere 8 using NSX networking (including built in L4 loadbalancer) and Avi as L7 loadbalancer.
AKO Explained
·1056 words·5 mins
Kubernetes LoadBalancing AVI Kubernetes Ingress Loadbalancing Ako
What is AKO?