Install and Configure Cert Manager on EKS / Kubernetes Cluster

A guide explains provisioning certificates for your EKS / Kubernetes Cluster

Friday, May 6, 2022

Cert-Manager is an add-on utility for your Kubernetes Cluster, it automates the creating, issuing, and providing of certificates within your clusters. It provides a set of custom resources(YAML configuration) to issue certificates and attach them to services.

One of the most common use cases is securing web apps and APIs with SSL certificates from Let’s Encrypt. The following will guide you to add Cert-Manager to your EKS or Kubernetes cluster and set up a Let’s Encrypt certificate issuer through the YAML configuration file, and acquire and expose a certificate for Pods and Services exposed through your Nginx Ingress.

Install Cert-Manager

The cert-Manager can easily be installed using Helm. Helm is a Kubernetes package manager that lets you add repositories or application resources to your cluster using pre-built charts. Please make sure you have Helm installed on your workspace with a connection to your Kubernetes cluster.

Start by adding the Jetstack repository to your Helm installation. Jetstack originally developed Cert-Manager, now CNCF manages it.

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

next, install Cert-Manager into your cluster:

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

You may also switch or opt for the new version, the new version and other options can be found here at Cert-Manager documentation.

Cert-Manager Kubectl Plugin

Cert-Manager has a Kubectl plugin that simplifies some common management tasks. It also lets you check whether Cert-Manager is up and ready to serve requests.

Install the plugin by downloading its archive and extracting it to the correct directory:

curl -L -o kubectl-cert-manager.tar.gz https://github.com/jetstack/cert-manager/releases/latest/download/kubectl-cert_manager-linux-amd64.tar.gz
tar xzf kubectl-cert-manager.tar.gz
sudo mv kubectl-cert_manager /usr/local/bin

If you are on windows,

  1. Download the latest version from Github.
  2. Extract the archive.
  3. Add the .exe file extension to the extracted kubectl-cert_manager.
  4. Copy kubectl-cert_manager.exe to a location that is in your PATH environment variables.

Run the follwing command to check if the plugin was correctly installed:

kubectl cert-manager check api

If everything works fine, you should see the cert-manager API resulting in ready message in response.

Create a Certificate Issuer

Issuers and cluster issuers are resources that supply certificates to your cluster. The basic Cert-Manager installation created so far is incapable of issuing certificates. Adding an issuer that’s configured to use Let’s Encrypt lets you dynamically acquire new certificates for services in your cluster.

Create a YAML file in your workspace and name it issuer.yml. Add the following content:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: your_email@address.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - http01:
          ingress:
            class: nginx

You should replace the email address with your own contact email, this information will be included with your certificates. Let’s Encrypt may also alert you at the address if it needs to send you alerts about your certificates.

We’re creating a ClusterIssuer as these are available to all resources in your cluster, irrespective of the namespace. A standard Issuer is a namespaced resource that can only supply certificates within its own namespace.

Our issuer configuration instructs Cert-Manager to get certificates from the Let’s Encrypt server.

It’s a good idea to use the staging environment while you’re setting up your integration to avoid hitting Let’s Encrypt’s production rate limits. you may use the following acme server for staging or development environment: https://acme-staging-v02.api.letsencrypt.org/directory

Use kubectl to add the issuer to your cluster:

kubectl create -f issuer.yml

Certificate

Now you can use your issuer to acquire a certificate for a service exposed via an Ingress resource. Cert-Manager automatically monitors Ingress resources and creates certificates using the configuration in their tls field. You just need to add an annotation that names the issuer or cluster issuer you want to use.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app
          image: mockserver/mockserver:latest
          ports:
            - containerPort: 80
 
---

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
    port: 80
 
---

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            backend:
              serviceName: my-service
              servicePort: 80
  tls:
    - hosts:
      - example.com

This YAML file defines a Pod, a Service, and an Ingress exposing the service. It assumes use of nginx-ingress as the Ingress controller. The Pod runs a mockserver container which will be accessible over HTTPS at example.com.

The presence of the cert-manager.io/cluster-issuer annotation in the Ingress resource will be detected by Cert-Manager. It’ll use the letsencrypt-prod cluster issuer created earlier to acquire a certificate covering the hostnames defined in the Ingress’ tls.hosts field.

Please also make sure that you have pointed the CNAME reocrds on your DNS provider.

CNAME example.com a2943a.......elb.amazonaws.com

Summary

Let’s Encrypt can easily be added to a K8 or EKS cluster using Cert-Manager. Install Cert-Manager with Helm, create an issuer with Let’s Encrypt Staging/Production API, then reference that issuer name in your Nginx Ingress resource as cluster-issuer.

You may also configure Cert-Manager with your own options for more advanced control over the generated certificates. You may specify a certificate expiry (use the cert-manager.io/duration Ingress annotation) or use DNS challenges instead of HTTP which can be useful in specific scenarios.

HTTP verification works by updating the Ingress controller resource that provides a temporary .well-known URL that Let’s Encrypt can access. If your domain provides the correct value at that URL, Let’s Encrypt issues the certificate.

You may also want to utilize annotation acme.cert-manager.io/http01-edit-in-place if your ingress controller handling multiple resources or sub-domains for the same hostname.

You can troubleshoot the common problems and scenarios through Cert-Manager Troubleshooting Guide.