Kubernetes Ingress TLS Certificate with cert-manager
Automate TLS certificate management on Kubernetes with cert-manager. Let's Encrypt integration, ClusterIssuer configuration, automatic renewal, wildcard
💡 Quick Answer: cert-manager automates TLS certificate lifecycle on Kubernetes. Install with Helm, create a
ClusterIssuerpointing to Let’s Encrypt, then annotate your Ingress withcert-manager.io/cluster-issuer: letsencrypt-prod. cert-manager automatically issues, stores (as Secret), and renews certificates before expiry.
The Problem
- Manual certificate management is error-prone and certificates expire unexpectedly
- Let’s Encrypt requires ACME challenge automation
- Each Ingress needs its own TLS certificate Secret
- Certificate renewal must happen before expiry (90-day Let’s Encrypt certs)
- Need wildcard certificates for dynamic subdomains
The Solution
Install cert-manager
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.16.0 \
--set crds.enabled=true
# Verify
kubectl get pods -n cert-managerClusterIssuer (Let’s Encrypt)
# Staging (for testing — no rate limits)
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: admin@example.com
privateKeySecretRef:
name: letsencrypt-staging-key
solvers:
- http01:
ingress:
class: nginx
---
# Production
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@example.com
privateKeySecretRef:
name: letsencrypt-prod-key
solvers:
- http01:
ingress:
class: nginxIngress with Automatic TLS
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
namespace: production
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
- api.example.com
secretName: app-tls-cert # cert-manager creates this Secret
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
number: 80
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-server
port:
number: 80DNS-01 Challenge (Wildcard Certs)
# ClusterIssuer with DNS-01 (required for wildcards)
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-dns
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@example.com
privateKeySecretRef:
name: letsencrypt-dns-key
solvers:
- dns01:
cloudflare:
email: admin@example.com
apiTokenSecretRef:
name: cloudflare-api-token
key: api-token
---
# Wildcard Certificate
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: wildcard-cert
namespace: production
spec:
secretName: wildcard-tls
issuerRef:
name: letsencrypt-dns
kind: ClusterIssuer
dnsNames:
- "example.com"
- "*.example.com"Check Certificate Status
# List certificates
kubectl get certificates -A
# NAME READY SECRET AGE
# app-tls-cert True app-tls-cert 5d
# Detailed status
kubectl describe certificate app-tls-cert -n production
# Check certificate request
kubectl get certificaterequest -n production
# Check ACME challenges
kubectl get challenges -A
# View actual certificate
kubectl get secret app-tls-cert -n production -o jsonpath='{.data.tls\.crt}' | \
base64 -d | openssl x509 -text -noout | head -20Gateway API Integration
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: main-gateway
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
gatewayClassName: nginx
listeners:
- name: https
protocol: HTTPS
port: 443
hostname: "app.example.com"
tls:
mode: Terminate
certificateRefs:
- name: app-tls-cert # cert-manager auto-createsCommon Issues
Certificate stuck in “Not Ready” — challenge failing
- Cause: HTTP-01 challenge can’t reach
/.well-known/acme-challenge/on port 80 - Fix: Ensure Ingress is accessible externally on port 80; DNS resolves to ingress IP; no firewall blocking
”rate limited” error from Let’s Encrypt
- Cause: Too many certificate requests for same domain (5/week for prod)
- Fix: Use staging issuer for testing; wait for rate limit reset; use longer-lived certs
”acme: authorization for domain not found”
- Cause: DNS-01 TXT record not propagated; or API token lacks permissions
- Fix: Verify DNS provider credentials; check cert-manager pod logs; add propagation wait
Certificate renewed but pods still use old cert
- Cause: Ingress controller caches TLS; or pods mount Secret that hasn’t refreshed
- Fix: NGINX ingress auto-detects Secret changes. For pod mounts, restart pods or wait kubelet sync
Best Practices
- Start with staging issuer — avoid rate limits while testing
- Use ClusterIssuer over Issuer — works across all namespaces
- HTTP-01 for standard certs — simplest, no DNS provider integration needed
- DNS-01 for wildcards — only solver type that supports
*.example.com - Set
secretNamein Ingress TLS — cert-manager stores cert there - Monitor certificate expiry — cert-manager Prometheus metrics or alerts
- Renewal happens at 2/3 lifetime — 60 days for 90-day Let’s Encrypt certs
Key Takeaways
- cert-manager automates certificate issuance, storage, and renewal on Kubernetes
ClusterIssuer+ Ingress annotation = fully automatic TLS with Let’s Encrypt- HTTP-01: validates domain via HTTP request (port 80 must be reachable)
- DNS-01: validates via DNS TXT record (required for wildcards)
- Certificates stored as Kubernetes Secrets (type
kubernetes.io/tls) - Auto-renewal at 2/3 certificate lifetime (day 60 of 90-day cert)
kubectl describe certificateandkubectl get challenges— primary debugging tools

Recommended
Kubernetes Recipes — The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book →Learn by Doing
CopyPasteLearn — Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses →🎓 Deepen Your Skills — Hands-on Courses
Courses by CopyPasteLearn.com — Learn IT by Doing
