Cert-manager is a Kubernetes tool that automates the management of TLS certificates in a Kubernetes cluster. It can issue certificates from various sources, such as Let's Encrypt or self-signed certificates.
Cert-manager automatically renews these certificates when 2/3 of the certificate's validity period has expired.
In this tutorial , we will show you how to install and configure Cert-manager to issue Let's Encrypt certificates on your Kubernetes cluster.
Before proceeding with this tutorial, make sure to:
Installing Cert-manager
Step 1
Add the Jetstack repository, which is the only official source of cert-manager Helm charts. Then, update your repositories to use the Jetstack repository with the second command:
helm repo add jetstack https://charts.jetstack.io
helm repo update
Step 2
Install Cert-manager with the following command:
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.12.0 \
--set installCRDs=true
- You are free to use a different namespace name than cert-manager, but this name is easily recognizable.
- Replace v1.12.0 with the latest stable version as seen here on Github.
- The installCRDs option is mandatory, but alternatively, you can comment out the installCRDs option and install the CRDs (Custom Resource Definitions) separately with the command:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.0/cert-manager.crds.yaml
You will see an output similar to the following confirming a successful installation:
NAME: cert-manager LAST DEPLOYED: Tue Jun 13 13:21:23 2023 NAMESPACE: cert-manager STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: cert-manager v1.11.0 has been deployed successfully! In order to begin issuing certificates, you will need to set up a ClusterIssuer or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer). More information on the different types of issuers and how to configure them can be found in our documentation: https://cert-manager.io/docs/configuration/ For information on how to configure cert-manager to automatically provision Certificates for Ingress resources, take a look at the 'ingress-shim' documentation: https://cert-manager.io/docs/usage/ingress/
You can check the status of the Pods and Services created for Cert-manager using the following commands:
kubectl get pods -n cert-manager
kubectl get svc -n cert-manager
Creating a (Cluster)Issuer
In order to use Cert-manager, you need a ClusterIssuer or Issuer. A ClusterIssuer defines a certificate issuer (e.g., Let's Encrypt) that can be used to generate TLS certificates for your entire Kubernetes cluster. An Issuer can only issue certificates for a specific namespace.
Step 1
Create a .yaml file, for example, letsencrypt-issuer.yaml:
nano letsencrypt-issuer.yaml
Give the file the following content:
apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-issuer spec: acme: email: yourmail@example.com server: https://acme-v02.api.letsencrypt.org/directory privateKeySecretRef: name: letsencrypt-issuer solvers: - http01: ingress: class: nginx
Replace the email address with your own email address. Finally, save your changes and exit the file (ctrl + c > y > enter).
Step 2
Apply the configuration from the .yaml file to your cluster:
kubectl apply -f letsencrypt-issuer.yaml
You will see a confirmation that the configuration has been successfully applied:
clusterissuer.cert-manager.io/letsencrypt-issuer created
Note: When generating a certificate (see the next section), you will create an Ingress resource that must use the exact value above, i.e., clusterissuer.cert-manager.io/letsencrypt-issuer
Using Cert-manager
Cert-manager is now ready to be used. We assume that you are using an Nginx Ingress Controller on your Kubernetes cluster. In that case, using Cert-manager involves two steps: 1) creating a certificate and 2) creating an ingress resource. It is recommended to deploy the software you want to use the certificate for before proceeding.
Step 1
Before actually generating the certificate, you need a (sub)domain in your TransIP account. Point the DNS records of this (sub)domain to the public IP address of the load balancer of your Nginx Ingress Controller, as shown in step 5 of this tutorial.
Step 2
Before creating the certificate, you need an ingress resource to associate the certificate with. The exact content of the file depends on your specific use case. As an example, we will use an ingress for Grafana. First, create the resource:
nano grafana-ingress.yaml
Give the file the following content, making sure to modify the following details:
- metadata name: Modify it to match the name of the software you want to use the certificate for.
- namespace: The namespace should match the name of the namespace where you want to use the certificate (can be obtained with kubectl get ns).
- annotations cert-manager.io/cluster-issuer: Modify the value to the name of the issuer you created earlier in this tutorial.
- spec rules host: Modify it to the (sub)domain for which you created the certificate.
- spec tls hosts: Also modify this value to the (sub)domain for which you created the certificate.
- spec tls secretName: Modify it to the name of the secretName value from step 2 of this section.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: grafana
namespace: grafana
annotations:
ingressClassName: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-issuer"
spec:
rules:
- host: subdomain.example.nl
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: grafana
port:
number: 3000
tls:
- hosts:
- subdomain.example.nl
secretName: subdomain-example-nl-tls
Finally, save your changes and exit the file (ctrl + c > y > enter).
Step 3
Apply the created ingress using the kubectl apply command:
kubectl apply -f grafana-ingress.yaml
Step 4
Create a certificate resource, for example, subdomain-example-nl-certificate.yaml:
nano subdomain-example-nl-certificate.yaml
Give the file the following content, making sure to modify the following details:
- metadata name: Replace subdomain-example-nl with a name of your choice, such as your (sub)domain name.
- metadata namespace: Replace ingress-nginx with the name of the namespace where your Nginx Ingress Controller is deployed (if different).
- spec secretName: Replace with a name of your choice, such as your (sub)domain name with the suffix -tls.
- spec issuerRef name: Replace with the issuerRef name you set in step 1 of the previous section. If you followed the code in this tutorial, the name is 'letsencrypt-issuer'.
- spec commonName: The name of your (sub)domain for which you are requesting the certificate.
- dnsNames: The name of the (sub)domain(s) for which you are requesting the certificate, such as example.nl and www.example.nl.
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: subdomain-example-nl
namespace: ingress-nginx
spec:
secretName: subdomain-example-nl-tls
issuerRef:
name: letsencrypt-issuer
kind: ClusterIssuer
commonName: subdomain.example.nl
dnsNames:
- subdomain.example.nl
- www.subdomain.example.nl
Finally, save your changes and exit the file (ctrl + c > y > enter).
Step 5
Generate the certificate using the following kubectl apply command:
kubectl apply -f subdomain-example-nl-certificate.yaml
You will see a confirmation that the certificate has been configured:
certificate.cert-manager.io/subdomain.example.nl configured
Next, check if the certificate has been successfully created using the command:
kubectl get cert -n ingress-nginx
Under 'READY', the status should now be 'True'.
NAME READY SECRET AGE subdomain.example.nl True subdomain-example-nl-tls 2m14s
If you see the status 'False', use the following command to determine the cause of the issue:
kubectl describe cert subdomain.example.nl -n ingress-nginx
That's it! Your certificate is now associated with your application, and in this example, it can be accessed at subdomain.example.nl/grafana