Cert-Manager Helm Chart
This Helm chart deploys cert-manager with configurable certificate issuers for automatic SSL certificate management in Kubernetes.
Features
- Multiple Issuer Support: Let's Encrypt (production/staging), Step CA, self-signed
- Challenge Solvers: HTTP01 and DNS01 (Cloudflare, Route53)
- Network Policies: Optional security policies
- Monitoring: Prometheus metrics and ServiceMonitor
- Flexible Configuration: Comprehensive values file with examples
Quick Start
- Configure values: Copy an example from
examples/directory:- Let's Encrypt: Copy
values-letsencrypt-example.yaml(orvalues-http.yamlfor a minimal setup) and update email/secret - Step CA: Use the dedicated
argocd-helm-charts/step-ca/examples/values.yaml - DNS01: Copy
values-cloudflare.yamlorvalues-route53.yaml
- Let's Encrypt: Copy
- Deploy: Use ArgoCD or Helm to deploy the chart
- Verify: Check ClusterIssuer status and certificate creation
Certificate Issuer Configuration
Each certificate issuer is added by its own helm chart. "step-ca" runs via the dedicated argocd-helm-charts/step-ca chart (see step-ca/examples/values.yaml). For other issuers like Let's Encrypt, we use the ClusterIssuer template in templates/clusterissuer.yaml (see example in examples/values-letsencrypt-example.yaml).
Supported Issuer Types
Let's Encrypt (ACME)
- Production: Real certificates for production use
- Staging: Test certificates (no rate limits)
- HTTP01: Web server challenge
- DNS01: DNS challenge for wildcard certificates
Step CA
- Internal CA for development and testing
- Custom CA bundle configuration
- Suitable for private/internal domains
Self-Signed
- For testing purposes only
- No external dependencies
Configuration Examples
Let's Encrypt Production
issuer:
name: letsencrypt-prod
enabled: true
production: true
issuerEmail: admin@yourdomain.com
secret: letsencrypt-prod-private-key
solvers:
- type: http
http01:
ingress:
ingressClassName: traefik-cert-manager
Let's Encrypt with DNS01 (Cloudflare)
issuer:
name: letsencrypt-dns01
enabled: true
production: true
issuerEmail: admin@yourdomain.com
secret: letsencrypt-dns01-private-key
solvers:
- type: dns
cloudProvider: cloudflare
issuerEmail: admin@yourdomain.com
cloudProviderSecretRef:
name: cloudflare-api-token
key: api-token
dnsNames:
- "*.yourdomain.com"
- "yourdomain.com"
Step CA
issuer:
name: step-ca
enabled: true
stepCA:
enabled: true
caBundle: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t..."
solvers:
- type: http
http01:
ingress:
ingressClassName: traefik-cert-manager
Examples Directory
The examples/ directory contains ready-to-use configuration files:
values-letsencrypt-example.yaml- Comprehensive Let's Encrypt example (uses ClusterIssuer template)values-http.yaml- Simple Let's Encrypt HTTP01 challengevalues-cloudflare.yaml- Cloudflare DNS01 challengevalues-route53.yaml- Route53 DNS01 challengevalues-multiple-solvers.yaml- Multiple challenge solvers
For the Step CA helm chart, use argocd-helm-charts/step-ca/examples/values.yaml.
Deployment
Using ArgoCD
-
Create values file in your kubeaid-config repository:
k8s/{clustername}/argocd-apps/values-cert-manager.yaml -
Reference the values file in your ArgoCD Application:
sources:- repoURL: https://github.com/Obmondo/KubeAidpath: argocd-helm-charts/cert-managertargetRevision: HEADhelm:valueFiles:- $values/k8s/{clustername}/argocd-apps/values-cert-manager.yaml
Using Helm
helm install cert-manager ./argocd-helm-charts/cert-manager \
--namespace cert-manager \
--create-namespace \
--values examples/values-letsencrypt-production.yaml
Secrets Management
Cloudflare API Token
kubectl create secret generic cloudflare-api-token \
--from-literal=api-token=your-cloudflare-api-token \
--namespace=cert-manager
Sealed Secrets (Recommended)
kubectl create secret generic cloudflare-api-token \
--from-literal=api-token=your-cloudflare-api-token \
--namespace=cert-manager \
--dry-run=client -o yaml | kubeseal \
--controller-name=sealed-secrets \
--controller-namespace=system \
-o yaml > cloudflare-api-token-secret.yaml
Troubleshooting
Common Issues
-
Certificate not issued
kubectl get clusterissuerkubectl describe clusterissuer letsencrypt-prod -
ACME challenges failing
kubectl logs -n cert-manager deployment/cert-managerkubectl get challenges -
DNS01 challenges failing
- Verify DNS provider credentials
- Check DNS propagation
- Verify domain ownership
Useful Commands
# Check ClusterIssuer status
kubectl get clusterissuer
# Check certificate status
kubectl get certificates
# View cert-manager logs
kubectl logs -n cert-manager deployment/cert-manager
# Check certificate details
kubectl describe certificate <certificate-name>
# Check challenges
kubectl get challenges
kubectl describe challenge <challenge-name>
Backup and Recovery
Important Secrets to Backup
- ACME server account credentials
- Cloud provider API tokens
- Step CA certificates and keys
Backup Commands
# Backup ACME account secret
kubectl get secret -n cert-manager -o yaml > cert-manager-secrets.yaml
# Backup ClusterIssuer configurations
kubectl get clusterissuer -o yaml > clusterissuers.yaml
Configuration Reference
Values File Structure
# cert-manager core configuration
cert-manager:
installCRDs: true
clusterResourceNamespace: cert-manager
global:
leaderElection:
namespace: cert-manager
prometheus:
enabled: true
servicemonitor:
enabled: true
# ClusterIssuer configuration
issuer:
name: letsencrypt
enabled: false
production: false
issuerEmail: admin@example.com
secret: letsencrypt-private-key
stepCA:
enabled: false
caBundle: ""
selfSigned: false
solvers:
- type: http
http01:
ingress:
ingressClassName: traefik-cert-manager
# Security and features
networkpolicies: false
enableCertificateOwnerRef: true
Best Practices
- Use staging first: Test with Let's Encrypt staging before production
- Monitor certificates: Set up alerts for certificate expiration
- Backup secrets: Regularly backup ACME account credentials
- Use DNS01 for wildcards: DNS01 challenges support wildcard certificates
- Rate limiting: Be aware of Let's Encrypt rate limits
- Security: Enable network policies in production
References
- cert-manager Documentation
- Let's Encrypt Documentation
- Step CA Documentation
- ACME Challenge Types
- DNS01 Providers
Known ArgoCD Drift
AKS: ValidatingWebhookConfiguration and MutatingWebhookConfiguration namespaceSelector
On AKS clusters, Kubernetes automatically injects a kubernetes.azure.com/managedby: aks expression into the namespaceSelector of all webhook configurations. This field is not present in the Helm chart, causing ArgoCD to permanently show OutOfSync for ValidatingWebhookConfiguration and MutatingWebhookConfiguration.
Add ignoreDifferences to your ArgoCD Application to suppress this expected drift:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: cert-manager
namespace: argocd
spec:
ignoreDifferences:
- group: admissionregistration.k8s.io
kind: ValidatingWebhookConfiguration
jsonPointers:
- /webhooks/0/namespaceSelector
- group: admissionregistration.k8s.io
kind: MutatingWebhookConfiguration
jsonPointers:
- /webhooks/0/namespaceSelector
sources:
- repoURL: https://gitea.obmondo.com/EnableIT/KubeAid
path: argocd-helm-charts/cert-manager
targetRevision: HEAD
helm:
valueFiles:
- $values/k8s/<cluster>/argocd-apps/values-cert-manager.yaml
- repoURL: <your-config-repo>
targetRevision: HEAD
ref: values
See example ArgoCD Application with ignoreDifferences for AKS for a full AKS example, or values-http.yaml for Helm values reference.