🇧🇷 Leia a versão em português aqui.
With the Ingress Controller already configured (see the previous article in this addons series), the cluster can route multiple HTTP domains to the correct Services. The natural next step is enabling HTTPS on those domains — and doing that manually, renewing certificates before they expire, doesn't scale well as the number of domains grows. That's exactly the problem cert-manager solves: it automates the issuance, renewal, and management of TLS certificates inside the cluster, integrating directly with certificate authorities like Let's Encrypt.
🔗 Official site: https://cert-manager.io/
Installing cert-manager
Installation is done by applying the project's official manifest, referencing the desired version:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.1/cert-manager.yaml
Always check the cert-manager releases page to install the latest stable version — the link above references v1.16.1 as an example, but the project releases new versions frequently, and it's worth using one compatible with your Kubernetes version.
This manifest creates cert-manager's components (controller, webhook, and cainjector) in a dedicated namespace (cert-manager), plus the Custom Resource Definitions (CRDs) needed — such as ClusterIssuer, Certificate, and CertificateRequest — which become new object types in the cluster.
Creating a ClusterIssuer
cert-manager, on its own, doesn't know where to issue certificates from — you need to configure an Issuer (scoped to a namespace) or a ClusterIssuer (available cluster-wide), pointing to a certificate authority.
A common example, using Let's Encrypt with HTTP-01 validation (which depends on the Ingress Controller already being in place, since validation happens through an HTTP request to the domain):
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: your-email@bagarote.com.br
privateKeySecretRef:
name: letsencrypt-prod-key
solvers:
- http01:
ingress:
ingressClassName: nginx
Where:
-
server: Let's Encrypt's production API address (a staging environment also exists, recommended for testing, avoiding hitting the production environment's certificate issuance rate limits); -
email: used by Let's Encrypt for notifications about expiration or issues with certificates; -
solvers.http01.ingress.ingressClassName: indicates that validation will be done through the already-installednginxIngress Controller.
Applying the ClusterIssuer:
kubectl apply -f clusterissuer.yaml
To confirm it was created correctly:
kubectl get clusterissuer
Enabling HTTPS on the application's Ingress
With the ClusterIssuer created, just annotate the application's Ingress so cert-manager automatically issues and manages that domain's certificate:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ecommerce-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- ecommerce.bagarote.com.br
secretName: ecommerce-tls
rules:
- host: ecommerce.bagarote.com.br
http:
paths:
- pathType: "Prefix"
path: "/"
backend:
service:
name: ecommerce
port:
number: 80
The cert-manager.io/cluster-issuer annotation tells cert-manager which ClusterIssuer to use for that domain, and the tls block defines which Secret (ecommerce-tls, in the example) the issued certificate should be stored in.
Tracking certificate issuance
After applying the Ingress, cert-manager automatically starts the process of requesting and validating the certificate. You can track each stage through a few commands:
Check whether the Secret with the certificate has already been created:
kubectl get secrets
Check the status of the Certificate object (automatically created by cert-manager from the Ingress annotation):
kubectl get certificate
kubectl describe certificate ecommerce-tls
If the certificate doesn't become Ready quickly, the next level of detail is the CertificateRequest — the actual issuance request:
kubectl describe certificaterequest ecommerce-tls-2ld57
And, going even deeper, the Challenge — which represents the domain validation step with Let's Encrypt (this is usually where DNS or Ingress routing issues show up):
kubectl describe challenges --all-namespaces
Finally, to view all the Custom Resource Definitions installed by cert-manager (useful for understanding the extent of what was added to the cluster):
kubectl get crd
Final thoughts
With cert-manager configured, new domains get TLS certificates issued and renewed automatically, just by adding the correct annotation to the respective Ingress — with no future manual intervention needed. When something doesn't work as expected, the Certificate → CertificateRequest → Challenge sequence is the natural investigation path, since each object represents a more granular step of the issuance process.
Top comments (0)