Introduction
Managing TLS certificates manually in Kubernetes environments is error-prone and unscalable. As organizations deploy hundreds of services requiring secure communication, manual certificate management becomes a significant operational burden and security risk. cert-manager addresses this challenge by automating the entire certificate lifecycleโfrom issuance through renewal to rotationโintegrating seamlessly with Kubernetes-native resources.
In 2026, with zero-trust security architectures becoming standard and regulatory compliance requirements tightening, automated certificate management is no longer optional. This comprehensive guide covers cert-manager architecture, deployment, configuration, and production best practices for Kubernetes environments.
What is cert-manager?
cert-manager is a Kubernetes-native certificate controller that automates certificate issuance and management. It extends Kubernetes with custom resources for certificate management, integrating with various certificate authorities (CAs) including Let’s Encrypt, Venafi, HashiCorp Vault, and internal PKI systems.
Key Capabilities
Automated Issuance: Certificates are automatically requested and issued based on Kubernetes resources.
Automatic Renewal: Certificates are renewed before expiration, eliminating manual processes.
Multiple CA Support: Integration with Let’s Encrypt, Venafi, Vault, self-signed, and custom CAs.
Certificate Rotation: Seamless certificate rotation without service disruption.
DNS Challenge: Domain validation through DNS records for wildcard certificates.
HTTP Challenge: Domain validation through HTTP well-known paths.
Secret Integration: Generated certificates are stored as Kubernetes Secrets.
Architecture
Understanding cert-manager’s architecture is essential for troubleshooting and optimization.
Components
cert-manager consists of several Kubernetes controllers:
Certificate Controller: Watches Certificate resources and manages certificate lifecycle, including requesting new certificates and renewing existing ones.
Issuers/ClusterIssuers: Define certificate authorities and configuration for certificate issuance.
ACME Controller: Handles ACME protocol interactions for Let’s Encrypt and other ACME providers.
Vault PKI Controller: Manages Vault PKI certificate issuance.
Venafi Controller: Integrates with Venafi for enterprise certificate management.
Custom Resources
cert-manager extends Kubernetes with several custom resource definitions:
- Certificate: Defines desired certificate properties
- Issuer: Namespaced certificate authority configuration
- ClusterIssuer: Cluster-wide certificate authority configuration
- CertificateRequest: Pending certificate requests
Installation
Install cert-manager using Helm:
# Add Jetstack Helm repository
helm repo add jetstack https://charts.jetstack.io
helm repo update
# Install cert-manager
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.16.0 \
--set installCRDs=true \
--set prometheus.enabled=true \
--set 'extraArgs={--dns01-recursive-nameservers-only=true,--dns01-recursive-nameservers=1.1.1.1:53}'
Verify installation:
kubectl get pods -n cert-manager
kubectl get crd | grep cert-manager
Issuer Configuration
Issuers define how cert-manager obtains certificates from certificate authorities.
Let’s Encrypt Issuer (HTTP01)
The most common issuer configuration using HTTP-01 challenge:
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt-http
namespace: production
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef:
name: letsencrypt-account-key
solvers:
- http01:
ingress:
class: traefik
Let’s Encrypt Issuer (DNS01)
For wildcard certificates and environments where HTTP01 isn’t suitable:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-dns
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef:
name: letsencrypt-dns-key
solvers:
- dns01:
cloudflare:
email: [email protected]
apiKeySecretRef:
name: cloudflare-api-key
key: api-key
Multiple DNS providers are supported:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: multi-dns-issuer
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef:
name: letsencrypt-multi-dns-key
solvers:
- selector:
dnsZones:
- "example.com"
dns01:
route53:
region: us-east-1
hostedZoneID: ZONE_ID
- selector:
dnsZones:
- "app.example.com"
dns01:
cloudflare:
apiKeySecretRef:
name: cloudflare-api-key
key: api-key
Venafi Issuer
For enterprise environments with Venafi:
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: venafi-issuer
namespace: production
spec:
venafi:
url: https://venafi.example.com
zone: "DevOps\\Kubernetes"
secretRef:
name: venafi-credentials
key: apikey
---
apiVersion: v1
kind: Secret
metadata:
name: venafi-credentials
namespace: production
type: Opaque
stringData:
apikey: VENAFI_API_KEY
HashiCorp Vault PKI
For internal PKI using Vault:
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: vault-issuer
namespace: production
spec:
vault:
server: https://vault.example.com:8200
path: pki_int
auth:
appRole:
roleId: ROLE_ID
secretRef:
name: vault-approle
key: secretId
---
apiVersion: v1
kind: Secret
metadata:
name: vault-approle
namespace: production
type: Opaque
stringData:
secretId: SECRET_ID
Certificate Management
Certificates define the desired certificate properties and trigger automatic issuance.
Basic Certificate
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-com
namespace: production
spec:
secretName: example-com-tls
issuerRef:
name: letsencrypt-http
kind: Issuer
group: cert-manager.io
dnsNames:
- example.com
- www.example.com
duration: 2160h # 90 days
renewBefore: 360h # 15 days before expiry
privateKey:
algorithm: RSA
size: 2048
usages:
- server auth
- client auth
revisionHistoryLimit: 3
Wildcard Certificate
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: wildcard-example-com
namespace: production
spec:
secretName: wildcard-example-com-tls
issuerRef:
name: letsencrypt-dns
kind: ClusterIssuer
dnsNames:
- "*.example.com"
- example.com
duration: 2160h
renewBefore: 360h
privateKey:
algorithm: ECDSA
size: 256
Multi-Domain Certificate
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: multi-domain
namespace: production
spec:
secretName: multi-domain-tls
issuerRef:
name: letsencrypt-http
dnsNames:
- example.com
- www.example.com
- api.example.com
- app.example.com
duration: 2160h
renewBefore: 360h
Ingress Integration
cert-manager integrates with ingress controllers for automatic TLS.
Basic Ingress TLS
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
cert-manager.io/issuer: letsencrypt-http
kubernetes.io/ingress.class: nginx
spec:
tls:
- hosts:
- myapp.example.com
secretName: myapp-tls
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80
Ingress with ClusterIssuer
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-dns
kubernetes.io/ingress.class: traefik
spec:
tls:
- hosts:
- "*.example.com"
- example.com
secretName: wildcard-tls
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80
HTTP01 Challenge Configuration
Configure how HTTP01 challenges are solved:
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt-http-custom
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef:
name: letsencrypt-key
solvers:
- http01:
ingress:
class: nginx
podTemplate:
spec:
nodeSelector:
"kubernetes.io/os": linux
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
Advanced Configuration
Certificate Specifications
Configure certificate properties for specific requirements:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: advanced-cert
namespace: production
spec:
secretName: advanced-cert-tls
issuerRef:
name: venafi-issuer
dnsNames:
- app.example.com
duration: 17520h # 2 years
renewBefore: 720h # 30 days
organization:
- Example Inc
organizationalUnit:
- DevOps
- Engineering
isCA: false
privateKey:
algorithm: ECDSA
size: 384
encoding: PKCS8
usages:
- digital signature
- key encipherment
- server auth
keyEncoding: PKCS8
revisionHistoryLimit: 5
additionalOutputFormats:
- type: DER
secretKey: tls.der
- type: CombinedPEM
secretKey: tls-ca-bundle.pem
External Account Binding
For CA operators requiring external account binding:
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: zerossl-issuer
spec:
acme:
server: https://acme.zerossl.com/v1/DZ26
email: [email protected]
externalAccountBinding:
keyID: ZEROSSL_ACCOUNT_ID
keySecretRef:
name: zerossl-eab
key: secret-key
keyAlgorithm: HS256
privateKeySecretRef:
name: zerossl-key
solvers:
- http01:
ingress:
class: nginx
Monitoring and Troubleshooting
Certificate Status
Check certificate status:
# Get certificate status
kubectl get certificate -n production
# Describe certificate for details
kubectl describe certificate example-com -n production
# Check certificate secret
kubectl get secret example-com-tls -n production -o yaml
# View certificate details
kubectl get secret example-com-tls -n production -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -text
Troubleshooting Common Issues
Challenge Failure:
# Check challenge status
kubectl get challenges
kubectl describe challenge <challenge-name>
# Common issues:
# - DNS not propagated
# - Firewall blocking port 80
# - Ingress class misconfigured
# - Token not accessible
Rate Limiting:
# Check for rate limiting errors
kubectl get orders
kubectl describe order <order-name>
Certificate Not Issuing:
# Check cert-manager logs
kubectl logs -n cert-manager -l app.kubernetes.io/name=cert-manager
# Verify issuer is ready
kubectl get issuer letsencrypt-http -n production -o yaml
Prometheus Metrics
Enable metrics collection:
# values.yaml
prometheus:
enabled: true
servicemonitor:
enabled: true
Key metrics:
certmanager_certificate_expiration_timestamp_seconds: Certificate expiration timecertmanager_certificate_ready_status: Certificate ready statuscertmanager_acme_client_request_count: ACME client requestscertmanager_certificates_key_usage: Key usage bits
Security Best Practices
Secure Secret Storage
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: secure-cert
spec:
secretName: secure-cert-tls
issuerRef:
name: vault-issuer
dnsNames:
- secure.example.com
# Use separate secret for CA certificate
caSecretName: custom-ca-secret
RBAC Configuration
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: cert-manager-role
namespace: production
rules:
- apiGroups: ["cert-manager.io"]
resources: ["certificates", "issuers"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "create", "delete"]
Network Policies
Restrict cert-manager network access:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: cert-manager-policy
namespace: cert-manager
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: cert-manager
policyTypes:
- Egress
egress:
- to:
- namespaceSelector: {}
ports:
- protocol: TCP
port: 443
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
High Availability
Deploy cert-manager for high availability.
Multiple Replicas
# values.yaml
replicaCount: 3
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: cert-manager
topologyKey: kubernetes.io/hostname
Pod Disruption Budget
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: cert-manager-pdb
namespace: cert-manager
spec:
minAvailable: 2
selector:
matchLabels:
app.kubernetes.io/name: cert-manager
Production Checklist
Before deploying to production:
- Choose appropriate issuer type (HTTP01 vs DNS01)
- Configure DNS challenge for wildcards
- Set up monitoring and alerting
- Configure appropriate renewal windows
- Test certificate issuance in staging
- Plan for CA rate limits
- Document incident response procedures
- Configure backup for private keys
- Set up metrics dashboards
- Configure appropriate resource limits
Conclusion
cert-manager has become the essential tool for TLS automation in Kubernetes environments. By automating the entire certificate lifecycle, it eliminates manual certificate management overhead while improving security through automatic rotation and renewal. Whether using Let’s Encrypt for public-facing services or integrating with enterprise CAs for internal PKI, cert-manager provides the flexibility and reliability required for modern cloud-native deployments.
As organizations continue their journey toward zero-trust architectures and automated security, cert-manager’s role in providing cryptographic protection will only grow. Understanding its architecture and capabilities enables platform teams to build secure, compliant, and operationally efficient Kubernetes environments.
Resources
- cert-manager Official Documentation
- Let’s Encrypt Rate Limits
- cert-manager GitHub Repository
- Kubernetes TLS Guide
- Venafi Integration
Comments