cert-manager
Purpose: For platform engineers, shows how to configure cert-manager Issuers, ClusterIssuers, and certificate policies.
What cert-manager Does
cert-manager automates TLS certificate provisioning and renewal insiypt (ACME), internal CAs, and Vault. Platform services like Gateway API, Harbor, and Keycloak depend on cert-manager for their TLS certificates.
How It's Deployed
cert-manager is deployed via FluxCD from openCenter-gitops-base:
openCenter-gitops-base/applications/base/services/cert-manager/
├── namespace.yaml
├── source.yaml # HelmRepository for jetstack charts
├── helmrelease.yaml
└── helm-values/
└── hardened-values-v1.18.2.yaml
The customer overles cluster-specific overrides:
applications/overlays/<cluster>/services/cert-manager/
├── kustomization.yaml
└── override-values.yaml
FluxCD reconciles the base HelmRelease merged with override values, deploying cert-manager into the cert-manager namespace.
Key Configuration
ClusterIssuer for Let's Encrypt
Most clusters use a ClusterIssuer for ACME (Let's Encrypt) certificate issuance:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: platform-team@example.com
privateKeySecretRef:
name: letsencrypt-prod-key
solvers:
- http01:
ingress:
ingressClassName: nginx
For DNS-01 challenges (wildcard certificates), configure a DNS provider solver instead of HTTP-01.
Internal CA Issuer
For clusters that use an internal certificate authority:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
internal-ca
spec:
ca:
secretName: internal-ca-keypair
Create the CA secret (encrypt with SOPS before committing):
kubectl create secret tls internal-ca-keypair \
--cert=ca.crt --key=ca.key -n cert-manager
Requesting a Certificate
Services request certificates by creating Certificate resources:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: app-tls
namespace: my-app
spec:
secretName: app-tls-secret
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- app.example.com
duration: 2160h # 90 days
renewBefore: 360h # Renew 15 days before expiry
Verification
# Check cert-manager pods
kubectl get pods -n cert-manager
# Verify ClusterIssuers are ready
kubectl get clusterissuers
# Check certificate status
kubectl get certificates -A
# Inspect a specific certificate's events
kubectl describe certificate app-tls -n my-app
# Check for failed certificate requests
kubectl get certificaterequests -A
Troubleshooting
Certificate stuck in "Issuing": Check CertificateRequest and Order resources for errors. Common causes: DNS not resolving, HTTP-01 challenge endpoint unreachable, ACME rate limits.
kubectl get orders -A
kubectl describe order <order-name> -n <namespace>
Common Customizations
- Switch ACME solver: Change from HTTP-01 to DNS-01 for wildcard certificates or clusters wilic ingress.
- Add trust bundles: Use trust-manager to distribute CA bundles across namespaces.
- Adjust renewal window: Set
renewBeforeon Certificate resources to control when renewal starts. - Resource limits: Increase memory in
override-values.yamlfor clusters with many certificates.