cert-manager
Automated TLS certificate management for Kubernetes.
cert-manager is the de-facto standard Kubernetes controller for managing X.509 certificates. It automates the issuance and renewal of certificates from various sources including Let's Encrypt, HashiCorp Vault, and internal CAs. It is needed in this cluster to provision TLS certificates for all HTTPS ingress routes and to serve internal PKI needs (e.g. webhook certificates for operators that rely on it, such as kubevela).
Alternatives considered
Self Hosted
| Tool | Open Source | Full Features | Notes |
|---|---|---|---|
| Vault PKI | Yes | Yes | Heavy-weight; cert-manager can also use Vault as a backend |
| step-ca | Yes | Yes | Lightweight ACME CA; works well with cert-manager |
Installation
Architecture
HelmRelease cert-manager in namespace cert-manager, consuming the chart through chartRef from an OCIRepository at oci://quay.io/jetstack/charts/cert-manager; the chart layer is selected explicitly (layerSelector) so a provenance layer shipped ahead of it cannot be picked up by mistake. CRDs installed via crds.enabled: true in chart values. Gateway API integration enabled (enableGatewayAPI: true). Components: cert-manager controller, webhook, cainjector, and startupapicheck — all with matching resource limits.
Security
All three controllers (controller, webhook, cainjector) share the same resource profile. No custom securityContext is set at the HelmRelease level; the chart defaults apply. RBAC is cluster-wide (cert-manager requires cluster-level access to watch Ingress, Gateway, and CertificateRequest resources).
Updates
Managed by Renovate, which bumps the OCIRepository tag. The OCI artifact is not cosign-verified by Flux: Jetstack signs the chart with a static key using a sha512 payload digest and no Rekor entry, which source-controller cannot check. Supply-chain verification for cert-manager therefore happens at admission instead — the pod images are covered by the verify-platform-images policy on the Kyverno page.
Usage
Operators create Certificate, ClusterIssuer, and Issuer resources to request certificates. HTTPRoutes and Ingress objects can reference cert-manager-managed secrets for TLS termination. Other controllers (kubevela) use cert-manager for their admission webhook certificates via admissionWebhooks.certManager.enabled: true.
Cluster-specific deviations from the above live in the per-cluster README — see k8s/platform/cert-manager/talos/README.md.
Cluster Deployment
- Talos
- Edge
cert-manager — Talos cluster
Deviations from defaults
- Images pinned by digest. All five images (controller, webhook, cainjector, acmesolver, startupapicheck) carry
tag+digestincert-manager-values.yamlbecause the Kyverno policyverify-platform-imagesverifies cert-manager's cosign signature withverifyDigest: true— a tag-only reference is rejected at admission. Renovate updates tag and digest together (renovate: imageannotation) and groups them with the chart bump.
- HelmRelease:
cert-manager@v1.21.2 - HelmRepo:
cert-manager(oci://quay.io/jetstack/charts/cert-manager)
Rendered manifests (kustomize build)
apiVersion: v1
data:
values.yaml: |
# Every cert-manager image is pinned by tag AND digest: the Kyverno policy
# verify-platform-images checks the cert-manager cosign signature with
# verifyDigest: true, which rejects tag-only image references at admission.
# The chart renders `repository:tag@digest`. Renovate keeps tag + digest in
# lockstep through the "renovate: image" annotation (custom manager in
# renovate.json); the stock helm-values manager is disabled for this file so
# it cannot bump the tag while leaving the digest behind. The chart version
# in base/helm-release.yaml and these tags are grouped into one PR.
image:
repository: quay.io/jetstack/cert-manager-controller
# renovate: image datasource=docker depName=quay.io/jetstack/cert-manager-controller
tag: v1.21.2
digest: sha256:70f532fd9cfde0b09d55687200942399d89838bc2d5d5b45152eb799a15912b8
resources: &resources
limits:
memory: 200Mi
requests:
cpu: 10m
memory: 100Mi
webhook:
resources: *resources
image:
repository: quay.io/jetstack/cert-manager-webhook
# renovate: image datasource=docker depName=quay.io/jetstack/cert-manager-webhook
tag: v1.21.2
digest: sha256:a60e2dac46dbb8a7f3df95c54ce941012f54c2fe022f0ee55aaa1ab40ed957ae
cainjector:
resources: *resources
image:
repository: quay.io/jetstack/cert-manager-cainjector
# renovate: image datasource=docker depName=quay.io/jetstack/cert-manager-cainjector
tag: v1.21.2
digest: sha256:c85268c64f2e0e76684bf5fe8906caff34b82523561c6affe0fae3546bd87562
# The ACME HTTP-01 solver runs as short-lived pods created by the controller
# (--acme-http01-solver-image); they pass admission like any other pod.
acmesolver:
image:
repository: quay.io/jetstack/cert-manager-acmesolver
# renovate: image datasource=docker depName=quay.io/jetstack/cert-manager-acmesolver
tag: v1.21.2
digest: sha256:699b40d622211ab7accad8a21b04c5fbaa1841ef7a12621e8de492dbe27b2503
startupapicheck:
resources: *resources
image:
repository: quay.io/jetstack/cert-manager-startupapicheck
# renovate: image datasource=docker depName=quay.io/jetstack/cert-manager-startupapicheck
tag: v1.21.2
digest: sha256:46e75b6866359ffb5d82624f41e3ed1c70b2994982702ced547ce5edb418a8f5
config:
apiVersion: controller.config.cert-manager.io/v1alpha1
kind: ControllerConfiguration
enableGatewayAPI: true
kind: ConfigMap
metadata:
name: cert-manager-values-mgg9c74786
namespace: cert-manager
- HelmRelease:
cert-manager@v1.21.2 - HelmRepo:
cert-manager(oci://quay.io/jetstack/charts/cert-manager)
Rendered manifests (kustomize build)
apiVersion: v1
data:
values.yaml: |
resources: &resources
limits:
memory: 100Mi
requests:
cpu: 10m
memory: 100Mi
webhook:
resources: *resources
cainjector:
resources: *resources
startupapicheck:
resources: *resources
config:
apiVersion: controller.config.cert-manager.io/v1alpha1
kind: ControllerConfiguration
enableGatewayAPI: true
kind: ConfigMap
metadata:
name: cert-manager-values-b6kt9bkfbd
namespace: cert-manager