Automate TLS certificate management using cert-manager, which integrates with Let’s Encrypt to provide automatic certificate issuance and renewal.
Prerequisites
Before setting up cert-manager, ensure you have:
Helm installed (installation guide )
A Kubernetes cluster with Ingress controller
A domain name with DNS configured
Install cert-manager
Install cert-manager using Helm:
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--set installCRDs= true
Refer to the cert-manager Helm installation guide for detailed options.
Create a ClusterIssuer to handle certificate requests with Let’s Encrypt:
apiVersion : cert-manager.io/v1
kind : ClusterIssuer
metadata :
name : letsencrypt-prod
spec :
acme :
email : [email protected]
server : https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef :
name : letsencrypt-prod
solvers :
- http01 :
ingress :
class : nginx
Apply the ClusterIssuer:
kubectl apply -f issuer.yml
Verify the ClusterIssuer was created:
kubectl get clusterissuer
kubectl describe clusterissuer letsencrypt-prod
Replace [email protected] with your actual email address. Let’s Encrypt uses this for certificate expiration notifications.
Certificate Management
Option 1: Standalone Certificate Resource
Create a standalone Certificate resource:
apiVersion : cert-manager.io/v1
kind : Certificate
metadata :
name : exchange-cert
namespace : default
spec :
secretName : exchange-tls
issuerRef :
name : letsencrypt-prod
kind : ClusterIssuer
commonName : exchange.example.com
dnsNames :
- exchange.example.com
Apply the certificate:
kubectl apply -f certificate.yml
Option 2: Automatic Certificate via Ingress Annotations
Define certificates directly in your Ingress resource (recommended):
apiVersion : networking.k8s.io/v1
kind : Ingress
metadata :
name : app-ingress
annotations :
cert-manager.io/cluster-issuer : "letsencrypt-prod"
spec :
ingressClassName : nginx
tls :
- hosts :
- app.example.com
secretName : app-tls
rules :
- host : app.example.com
http :
paths :
- path : /
pathType : Prefix
backend :
service :
name : app-service
port :
number : 80
Using Ingress annotations is preferred as it keeps certificate configuration alongside routing rules.
Verify Certificates
Check certificate status:
kubectl get certificate
kubectl describe certificate exchange-cert
Inspect the generated TLS secret:
kubectl get secret exchange-tls -n default -o yaml
View certificate details:
kubectl get secret exchange-tls -n default -o jsonpath='{.data.tls\.crt}' | base64 --decode | openssl x509 -text -noout
Troubleshooting TLS Issues
Certificate Not Issued
Check certificate status:
kubectl describe certificate < cert-nam e >
Check certificate request:
kubectl get certificaterequest
kubectl describe certificaterequest < request-nam e >
Check ACME challenge:
kubectl get challenges
kubectl describe challenge < challenge-nam e >
Common Issues
DNS not configured : Ensure your domain points to your cluster’s Ingress IP
kubectl get ingress
nslookup your-domain.com
HTTP-01 challenge failing : Verify that port 80 is accessible and not redirected before certificate issuance
Rate limits : Let’s Encrypt has rate limits. Use staging server for testing:
server : https://acme-staging-v02.api.letsencrypt.org/directory
Delete and Recreate Certificate
If you need to start fresh:
kubectl delete certificate exchange-cert
kubectl delete secret exchange-tls
Then reapply your certificate configuration.
Additional Resources
cert-manager Video Tutorial Step-by-step guide for setting up cert-manager in Kubernetes
When following external tutorials, use the issuer configuration provided in this documentation to match your cluster setup.