Table of Contents
In this article, we will see how to install and use cert manager and cmctl for certificate generation and renewal in Kubernetes Cluster. If you are looking for kubernetes native tool that automatically issues, renew and revoke TLS certificates for workloads running in your cluster then you should always go for cert-manager. It not only solves the problem of manually handling the certificates but also integrates with variety of certificate authorities including Let's Encrypt, HashiCorp Vault, Venafi and private PKI, thus simplifying the whole process.
Cert Manager automatically requests a TLS certificate, stores it in a Kubernetes secret, and handles renewals. It directly integrates with Nginx Controller such as NGINX, Traefik, HAProxy which helps us automatically enabling the TLS encryption. It can easily track certificates that are going to expire, renew them before expiration, and then update them in Kubernetes secrets. Check more on official website.
How to Install and Use Cert Manager and cmctl for certificate generation and renewal
Also Read: How to Install kube-downscaler in Kubernetes cluster using Kubectl
Step 1: Prerequisites
a) You should have a running kubernetes
cluster.
b) You should have go utility with minimum version 1.23
installed in your System. To install latest go version, check How to Install latest version of Golang(Go) in Linux
c) You should have kubectl
utility installed in your System. To install kubectl on Ubuntu 22.04
system, check How to Install kubectl on Ubuntu 22.04 LTS (Jammy Jellyfish)
Step 2: Install Cert Manager
You can visit official download page of cert manager, get the latest version YAML file and use it to deploy all the k8s objects required to set up cert manager in your cluster using kubectl
utility as shown below.
cyberithub@cluster:~$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.3/cert-manager.yaml namespace/cert-manager created customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/challenges.acme.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/clusterissuers.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/issuers.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/orders.acme.cert-manager.io created serviceaccount/cert-manager-cainjector created serviceaccount/cert-manager created serviceaccount/cert-manager-webhook created clusterrole.rbac.authorization.k8s.io/cert-manager-cainjector created clusterrole.rbac.authorization.k8s.io/cert-manager-controller-issuers created clusterrole.rbac.authorization.k8s.io/cert-manager-controller-clusterissuers created clusterrole.rbac.authorization.k8s.io/cert-manager-controller-certificates created clusterrole.rbac.authorization.k8s.io/cert-manager-controller-orders created clusterrole.rbac.authorization.k8s.io/cert-manager-controller-challenges created clusterrole.rbac.authorization.k8s.io/cert-manager-controller-ingress-shim created clusterrole.rbac.authorization.k8s.io/cert-manager-cluster-view created clusterrole.rbac.authorization.k8s.io/cert-manager-view created clusterrole.rbac.authorization.k8s.io/cert-manager-edit created clusterrole.rbac.authorization.k8s.io/cert-manager-controller-approve:cert-manager-io created clusterrole.rbac.authorization.k8s.io/cert-manager-controller-certificatesigningrequests created clusterrole.rbac.authorization.k8s.io/cert-manager-webhook:subjectaccessreviews created clusterrolebinding.rbac.authorization.k8s.io/cert-manager-cainjector created clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-issuers created clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-clusterissuers created clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-certificates created clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-orders created clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-challenges created ..............................................
Step 3: Verify Cert Manager Status
You can list all the pods created under cert-manager
namespace using kubectl get pods -n cert-manager
command as shown below.
cyberithub@cluster:~$ kubectl get pods -n cert-manager NAME READY STATUS RESTARTS AGE cert-manager-6bf4d69c6-frlrc 1/1 Running 0 116s cert-manager-cainjector-6f96cbbcc7-pxpxc 1/1 Running 0 116s cert-manager-webhook-5f6d4756f4-5qszq 1/1 Running 0 116s
Step 4: Install cmctl
While cert-manager itself automates certificate issuance and renewal, cmctl utility can simplify the whole process by allowing us to create, inspect, approve, and renew certificates without writing full YAML manifests. It also helps in diagnosing and troubleshooting certificate issues, thus allowing us to solve the problem faster. You can download this utility by using go install github.com/cert-manager/cmctl/v2@latest
command as shown below.
cyberithub@cluster:~$ go install github.com/cert-manager/cmctl/v2@latest go: downloading github.com/cert-manager/cert-manager v1.15.3 go: downloading k8s.io/kubectl v0.31.0 go: downloading sigs.k8s.io/controller-runtime v0.19.0 go: downloading github.com/go-logr/logr v1.4.2 go: downloading github.com/spf13/pflag v1.0.5 go: downloading k8s.io/apimachinery v0.31.0 go: downloading k8s.io/component-base v0.31.0 go: downloading k8s.io/klog/v2 v2.130.1 go: downloading github.com/spf13/cobra v1.8.1 ..............................
After downloading cmctl binary, copy it to /usr/local/bin
directory using cp /home/cyberithub/go/bin/cmctl /usr/local/bin/
command as shown below.
cyberithub@cluster:~$ cp /home/cyberithub/go/bin/cmctl /usr/local/bin/
Step 5: Check cmctl version
After successful installation, you can check the current version by using cmctl version
command as shown below. It should show both client and server version as you can see below.
cyberithub@cluster:~$ cmctl version Client Version: util.Version{GitVersion:"canary", GitCommit:"", GitTreeState:"", GoVersion:"go1.23.5", Compiler:"gc", Platform:"linux/amd64"} Server Version: &versionchecker.Version{Detected:"v1.16.3", Sources:map[string]string{"crdLabelVersion":"v1.16.3"}}
Step 6: Check Cert Manager API
To verify cert manager API is properly running and available in your Kubernetes cluster, run cmctl check api
command. It should show "The cert-manager API is ready"
on the output as shown below.
cyberithub@cluster:~$ cmctl check api The cert-manager API is ready
Step 7: Create test certificate
Now that all the tools and utilities are installed and verified, let's create a test certificate using below test-resources.yaml
manifest file. This manifest file will create a namespace called cert-manager-test
and deploy a self signed certificate called selfsigned-cert
in it.
cyberithub@cluster:~$ vi test-resources.yaml apiVersion: v1 kind: Namespace metadata: name: cert-manager-test --- apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: test-selfsigned namespace: cert-manager-test spec: selfSigned: {} --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: selfsigned-cert namespace: cert-manager-test spec: dnsNames: - example.com secretName: selfsigned-cert-tls issuerRef: name: test-selfsigned
To deploy above test certificate in your cluster, run kubectl apply -f test-resources.yaml
command as shown below.
cyberithub@cluster:~$ kubectl apply -f test-resources.yaml namespace/cert-manager-test created issuer.cert-manager.io/test-selfsigned created certificate.cert-manager.io/selfsigned-cert created
Step 8: Verify Certificate
To verify deployed certificate in namespace cert-manager-test
, run kubectl get certificate -n cert-manager-test
command as shown below.
cyberithub@cluster:~$ kubectl get certificate -n cert-manager-test NAME READY SECRET AGE selfsigned-cert True selfsigned-cert-tls 83s
Step 9: Renew Certificate
Although cert-manager can renew certificate automatically but in case you would like to do it manually then you can renew the deployed self signed certificate manually by using cmctl renew selfsigned-cert -n cert-manager-test
command as shown below.
cyberithub@cluster:~$ cmctl renew selfsigned-cert -n cert-manager-test Manually triggered issuance of Certificate cert-manager-test/selfsigned-cert
Step 10: Check Certificate Request
To retrieve all certificate request under a namespace called cert-manager-test
, run kubectl get certificaterequest -n cert-manager-test
command as shown below. Similarly, you can retrieve all certificate request under any namespace by using kubectl get certificaterequest -n <namespace>
syntax.
cyberithub@cluster:~$ kubectl get certificaterequest -n cert-manager-test NAME APPROVED DENIED READY ISSUER REQUESTER AGE selfsigned-cert-1 True True test-selfsigned system:serviceaccount:cert-manager:cert-manager 10m selfsigned-cert-2 True True test-selfsigned system:serviceaccount:cert-manager:cert-manager 58s
Step 11: Check Certificate Status
To check the certificate expiration and current status, run cmctl status certificate selfsigned-cert -n cert-manager-test
command as shown below. You can also check all the other certificate details such as created data, issuer, secret etc.
cyberithub@cluster:~$ cmctl status certificate selfsigned-cert -n cert-manager-test Name: selfsigned-cert Namespace: cert-manager-test Created at: 2025-02-02T20:15:06Z Conditions: Ready: True, Reason: Ready, Message: Certificate is up to date and has not expired DNS Names: - example.com Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Issuing 11m cert-manager-certificates-trigger Issuing certificate as Secret does not exist Normal Generated 11m cert-manager-certificates-key-manager Stored new private key in temporary Secret resource "selfsigned-cert-4jznb" Normal Requested 11m cert-manager-certificates-request-manager Created new CertificateRequest resource "selfsigned-cert-1" Normal Reused 2m11s cert-manager-certificates-key-manager Reusing private key stored in existing Secret resource "selfsigned-cert-tls" Normal Requested 2m11s cert-manager-certificates-request-manager Created new CertificateRequest resource "selfsigned-cert-2" Normal Issuing 2m10s (x2 over 11m) cert-manager-certificates-issuing The certificate has been successfully issued Issuer: Name: test-selfsigned Kind: Issuer Conditions: Ready: True, Reason: IsReady, Message: Events: <none> Secret: Name: selfsigned-cert-tls Issuer Country: Issuer Organisation: Issuer Common Name: Key Usage: Digital Signature, Key Encipherment Extended Key Usages: Public Key Algorithm: RSA Signature Algorithm: SHA256-RSA Subject Key ID: Authority Key ID: Serial Number: 68795ee0a7a4a7d95c74e861c3c61151 Events: <none> Not Before: 2025-02-02T20:24:46Z Not After: 2025-05-03T20:24:46Z Renewal Time: 2025-04-03T20:24:46Z No CertificateRequest found for this Certificate