Certificate Manager#
cert-manager is a Kubernetes add-on that automates the management and issuance of TLS certificates from various issuing sources. In this cluster, it handles all TLS certificate provisioning for ingress resources using Let's Encrypt as the certificate authority with CloudFlare DNS-01 challenges.
Overview#
The cert-manager deployment in this cluster provides:
- Automated certificate issuance from Let's Encrypt (staging and production)
- DNS-01 challenge solving via CloudFlare API integration
- Wildcard certificate support
- Automatic certificate renewal before expiration
- Certificate distribution across namespaces via Reflector
- Integration with Traefik ingress controller
Deployment Details#
Helm Chart Installation#
cert-manager is deployed via ArgoCD using the Kustomize Helm chart integration. The deployment is managed in /apps/certmanager/ with sync wave priority 1, making it one of the first applications to be deployed after core infrastructure.
Version: v1.19.0 (Helm chart from https://charts.jetstack.io)
ArgoCD Application: apps/argo-cd-apps/01-certmanager.yaml
Key Configuration Options:
DNS Challenge Configuration#
The cluster uses DNS-01 challenges instead of HTTP-01 challenges. This approach has several advantages:
- Supports wildcard certificates
- Works behind firewalls or private networks
- No need to expose port 80 during validation
The DNS challenge uses recursive nameservers (Quad9 and Cloudflare) to ensure reliable DNS propagation checking before attempting validation with Let's Encrypt.
ClusterIssuers#
Two ClusterIssuers are configured for certificate management:
Production Issuer#
Name: cloudflare-issuer-production
ACME Server: https://acme-v02.api.letsencrypt.org/directory
This issuer is used for production certificates with Let's Encrypt's rate limits enforced. It is the default issuer for all production ingress resources.
Staging Issuer#
Name: cloudflare-issuer-staging
ACME Server: https://acme-staging-v02.api.letsencrypt.org/directory
This issuer should be used for testing certificate configuration before switching to production. The staging server has much higher rate limits and issues certificates from a test CA that browsers will not trust.
ClusterIssuer Configuration#
Both issuers are configured with the following key settings:
The ClusterIssuer definitions are stored in encrypted form at /apps/certmanager/cloudflare_issuer.enc.yaml.
CloudFlare DNS Integration#
cert-manager uses a CloudFlare API token to manipulate DNS records for DNS-01 challenge validation. The API token is stored as an encrypted Kubernetes secret in /apps/certmanager/secrets.enc.yaml.
CloudFlare API Token Requirements#
The API token must have the following permissions:
- Zone: DNS:Edit for the zones you want to issue certificates for
- Zone: Zone:Read for the zones you want to issue certificates for
Secret Configuration#
The CloudFlare API token is stored in a Kubernetes secret:
This secret is referenced by both ClusterIssuers and must be available in the certmanager namespace before certificate issuance can succeed.
Wildcard Certificates#
The cluster uses pre-provisioned wildcard certificates that are automatically distributed to all namespaces using the Reflector operator. This approach has several advantages:
- Single certificate covers all subdomains
- Reduces Let's Encrypt rate limit consumption
- Certificates are available immediately in new namespaces
- Centralized certificate management
Wildcard Certificate Resources#
Two wildcard certificates are configured in /apps/certmanager/wildcard.enc.yaml:
- wildcard-cloudflare-production-01: Covers the primary domain
- wildcard-cloudflare-production-02: Covers a secondary domain
Example certificate configuration:
Certificate Distribution via Reflector#
The secretTemplate section includes Reflector annotations that automatically distribute the certificate secret to all namespaces:
- reflector.v1.k8s.emberstack.com/reflection-allowed: "true": Enables the secret to be reflected
- reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true": Automatically creates copies in all namespaces
This means that once a wildcard certificate is issued in the certmanager namespace, it is immediately available in all other namespaces without manual intervention.
Using Certificates in Ingress Resources#
Standard Ingress with Wildcard Certificate#
Most ingress resources in this cluster use the pre-provisioned wildcard certificates. Here's an example:
Key points:
- The tlssection references one of the wildcard certificate secrets
- The secret is automatically available in the namespace via Reflector
- No cert-manager annotations are needed when using pre-provisioned certificates
- The hostname must match the wildcard pattern
Requesting Application-Specific Certificates#
If you need a certificate for a specific application that is not covered by the wildcard certificates, you can create a Certificate resource:
Then reference it in your Ingress:
Certificate Renewal#
cert-manager automatically renews certificates before they expire. The default renewal window is 30 days before expiration (for Let's Encrypt's 90-day certificates, renewal happens around day 60).
Monitoring Certificate Expiration#
You can check certificate status using kubectl:
Certificate Renewal Process#
- cert-manager monitors certificate expiration dates
- When a certificate enters the renewal window, cert-manager creates a CertificateRequest
- The ClusterIssuer creates a DNS challenge record via CloudFlare API
- Let's Encrypt validates the DNS record
- cert-manager retrieves the new certificate and updates the Secret
- Reflector automatically distributes the updated certificate to all namespaces
Troubleshooting#
Checking cert-manager Logs#
Common Issues and Solutions#
Certificate Not Issuing#
Symptoms: Certificate remains in "Pending" state
Troubleshooting steps:
-  Check the Certificate status: 
-  Check for CertificateRequest objects: 
-  Check the Order and Challenge status: 
-  Verify CloudFlare API token permissions and validity 
DNS Challenge Failing#
Symptoms: Challenge remains in "Pending" state, events show DNS validation failures
Troubleshooting steps:
-  Verify the CloudFlare API token secret exists: 
-  Check if DNS records are being created in CloudFlare: - Log into CloudFlare dashboard - Navigate to DNS records for your domain - Look for _acme-challengeTXT records
-  Verify DNS propagation: 
-  Check cert-manager can reach DNS servers: 
Certificate Not Distributing to Namespaces#
Symptoms: Certificate exists in certmanager namespace but not in other namespaces
Troubleshooting steps:
-  Verify Reflector is running: 
-  Check Reflector annotations on the certificate secret: 
-  Check Reflector logs: 
-  Verify the certificate secret exists in the source namespace: 
Rate Limiting#
Symptoms: Certificate issuance fails with rate limit errors
Solutions:
-  Use the staging issuer for testing: - Change issuerRef.nametocloudflare-issuer-staging- Test your configuration thoroughly - Switch back to production issuer once verified
-  Let's Encrypt rate limits: - 50 certificates per registered domain per week - 5 duplicate certificates per week - Use wildcard certificates to reduce certificate count 
-  Wait for rate limit window to reset (usually 7 days) 
Extracting Certificate for External Use#
If you need to extract a certificate and private key for use outside Kubernetes:
Security note: Handle private keys with extreme care. Never commit them to version control or share them insecurely.
Manual Certificate Renewal#
To force certificate renewal (e.g., after fixing an issue):
Integration with Other Components#
Traefik Ingress Controller#
All ingress resources in this cluster use Traefik as the ingress controller. Traefik automatically reads certificate secrets referenced in the tls section of Ingress resources.
Example Traefik ingress with TLS:
Secret Management with SOPS#
All cert-manager configuration files containing sensitive data are encrypted using SOPS with age encryption:
- /apps/certmanager/cloudflare_issuer.enc.yaml: ClusterIssuer definitions with encrypted email addresses
- /apps/certmanager/wildcard.enc.yaml: Certificate resources with encrypted domain names
- /apps/certmanager/secrets.enc.yaml: CloudFlare API token secret
To decrypt and edit these files:
For more information on secret management, see Secret Management.
Testing Certificate Configuration Locally#
Before committing changes to certificate configuration, test them locally:
Best Practices#
- Use wildcard certificates: Reduces certificate count and simplifies management
- Test with staging issuer: Always test new configurations with the staging issuer before production
- Monitor certificate expiration: Set up alerts for certificates nearing expiration (built into kube-prometheus-stack)
- Secure API tokens: Ensure CloudFlare API tokens have minimal required permissions
- Encrypt sensitive data: Use SOPS to encrypt all configuration containing domain names, emails, or tokens
- Document custom certificates: If creating application-specific certificates, document the reason for not using wildcards
- Regular secret rotation: Rotate CloudFlare API tokens periodically (recommended annually)
Related Documentation#
- Secret Management: SOPS encryption and decryption workflows
- Reflector: Certificate distribution across namespaces
- Network Architecture: Traefik ingress controller configuration
- ArgoCD: Application deployment and sync waves
- Monitoring: Certificate expiration alerts