cert-manager is a Kubernetes controller that automates TLS certificate issuance and renewal from Let’s Encrypt, HashiCorp Vault, Venafi, and other CAs. The team that installs it via the official Helm chart gets auto-renewed certificates, multiple ingress integrations, and no more 3am pages about expired certificates. The team that hand-rolls cert management on every cluster has renewal scripts that break, certificates that expire at the worst time, and operators who hate their job.
Table of contents
- What cert-manager does
- Installation via Helm
- Configuring Let’s Encrypt
- Ingress integration patterns
- Operational considerations
- FAQ
What cert-manager does
cert-manager is a Kubernetes controller that watches Certificate, Issuer, and ClusterIssuer custom resources. When the team creates a Certificate resource, cert-manager contacts the configured Issuer (Let’s Encrypt, Vault, internal CA), gets a real X.509 certificate, stores it in a Kubernetes Secret, and watches for expiration. When the certificate is 30 days from expiring, cert-manager renews it automatically.
The Issuer resource configures the CA. A ClusterIssuer is cluster-wide; an Issuer is namespace-scoped. The team that uses ClusterIssuers for prod and staging has one place to configure Let’s Encrypt; the team that uses Issuer per namespace duplicates configuration.
The integration with ingress controllers (nginx-ingress, traefik, contour, istio) is the killer feature. The team that annotates an Ingress with cert-manager.io/cluster-issuer: letsencrypt-prod gets a TLS certificate provisioned automatically when the Ingress is created. No manual certificate generation, no manual Secret creation, no manual renewal.
Installation via Helm
The official Helm chart is at oci://quay.io/jetstack/charts/cert-manager. The team that installs via Helm gets version management, configurable values, and a clean uninstall path. The team that installs via kubectl apply of raw manifests has a harder time upgrading or uninstalling.
Basic install with default values: helm install cert-manager oci://quay.io/jetstack/charts/cert-manager --set crds.enabled=true. The --set crds.enabled=true flag installs the CRDs with Helm managing them. The team that forgets this flag has CRDs that are not managed by Helm, which complicates upgrades.
Customize for production with a values file: set replicaCount: 2 (or 3 for HA), set resources for CPU/memory limits, set ingressShim.defaultIssuerName and defaultIssuerKind: ClusterIssuer so Ingress annotations work without specifying an issuer every time.
Configuring Let’s Encrypt
Create a ClusterIssuer for Let’s Encrypt staging first, then production. Staging has rate limits that don’t matter for testing; production has rate limits (50 certificates per week per registered domain) that the team hits fast during testing. The team that tests with prod rate-limits themselves out of certificates for the week.
HTTP-01 challenge needs port 80 open to the cluster. The Let’s Encrypt validation server makes an HTTP request to http://your-domain/.well-known/acme-challenge/.... The team that blocks port 80 (common for security reasons) needs to use DNS-01 challenge instead, which requires DNS provider credentials.
DNS-01 challenge works for wildcard certificates and behind-firewall scenarios. The team that needs *.example.com certs uses DNS-01 because HTTP-01 cannot issue wildcards. The team that runs services behind a firewall with no inbound port 80 also uses DNS-01. DNS provider credentials are stored as a Kubernetes Secret referenced by the Issuer.
Ingress integration patterns
The annotation pattern: annotate the Ingress, cert-manager provisions the certificate. cert-manager.io/cluster-issuer: letsencrypt-prod on an Ingress triggers cert-manager to create a Certificate for the hostnames in the Ingress. The team that uses this pattern adds one annotation per Ingress and gets auto-renewed TLS.
The Ingress-shim default pattern: configure ingressShim.defaultIssuerName once in Helm values. Every Ingress without an explicit annotation uses the default Issuer. The team that sets a default Issuer has zero-annotation Ingress with auto-TLS; the team that annotates every Ingress has boilerplate they could avoid.
The Gateway API pattern: cert-manager supports Gateway resources via cert-manager.io/gateway-shim. The team that uses Gateway API (the modern replacement for Ingress) gets the same auto-TLS behavior with Gateway resources. The team that uses both Ingress and Gateway can run cert-manager with both integrations enabled.
Operational considerations
Monitor certificate expiration with kubectl get certificates -A. The team that monitors this watches for certificates that are not being renewed (READY=False, or expiration within 30 days). The team that ignores certificates has outages from time-to-time when renewals silently fail.
Watch the cert-manager logs for renewal failures. Common failures: ACME rate limits hit, DNS provider credentials expired, HTTP-01 challenge blocked by firewall. The team that reads cert-manager logs catches these failures before certificates expire.
Plan for upgrade cadence. cert-manager releases every few months. The team that upgrades within one minor version of latest has access to bug fixes and new features; the team that runs a year-old cert-manager hits bugs that are already fixed in newer releases.
FAQ
What is the difference between Issuer and ClusterIssuer?
An Issuer is namespace-scoped - it can only issue certificates in its namespace. A ClusterIssuer is cluster-scoped - it can issue certificates in any namespace. The team that uses ClusterIssuers for shared CAs (Let’s Encrypt, internal CA) has one configuration; the team that uses Issuer per namespace duplicates configuration across namespaces.
How do I get a wildcard certificate with cert-manager?
Use DNS-01 challenge with a DNS provider that cert-manager supports (Cloudflare, Route53, Google Cloud DNS, Azure DNS, etc.). HTTP-01 challenge cannot issue wildcards. The team that needs *.example.com configures DNS-01 with provider credentials stored in a Kubernetes Secret.
What happens if cert-manager is down when a certificate expires?
The certificate expires and TLS connections fail. The cluster keeps running but clients see certificate errors. The team that runs cert-manager with HA (replicaCount 2 or 3) has resilience against single-pod failures; the team that runs with 1 replica has a single point of failure.
Can cert-manager work with internal CAs?
Yes. Configure an Issuer with ca.crt and ca.key from your internal CA. The team that uses an internal CA for internal services (and Let’s Encrypt for public-facing) has both patterns configured. Vault Issuer support adds another option for teams using HashiCorp Vault.
How do I uninstall cert-manager?
helm uninstall cert-manager then kubectl delete crd certificates.cert-manager.io issuers.cert-manager.io clusterissuers.cert-manager.io ... to remove the CRDs. The team that removes CRDs after uninstall cleans up the API surface; the team that leaves CRDs has stale CRD definitions in the cluster.
Does cert-manager work with Kubernetes 1.30+?
Yes. cert-manager keeps pace with Kubernetes releases. The team that runs the latest stable cert-manager version (currently 1.16.x) supports recent Kubernetes versions. Older cert-manager versions may not work on the latest Kubernetes due to API deprecations.
How this fits the rest of the stack
For a sense of what the full project costs before it commits, the RunxBuild hosting calculator shows the line items together. The API, the database, the storage, the worker, the bandwidth - each one is a separate number, and the team’s mental model for the platform is the sum of those numbers.
Useful related references: