cert-manager CA Injector Deep Dive
The CA Injector (cainjector) is a cert-manager component that automatically injects CA certificate bundles into Kubernetes resources that need them. It bridges the gap between cert-manager’s certificate management and the Kubernetes API server’s trust requirements for webhooks, CRDs, and aggregated API services.
1. What This Component Does
The CA Injector watches for Kubernetes resources annotated with cert-manager injection annotations and automatically populates their caBundle fields with the correct CA certificate. Its responsibilities include:
- Webhook CA Injection: Injecting CA bundles into
ValidatingWebhookConfigurationandMutatingWebhookConfigurationresources so the Kubernetes API server trusts the webhook’s TLS certificate. - CRD Conversion Webhook Injection: Injecting CA bundles into
CustomResourceDefinitionresources that use conversion webhooks. - API Service Injection: Injecting CA bundles into
APIServiceresources for aggregated API servers. - Continuous Reconciliation: Watching for changes to source Certificates and target resources, updating CA bundles when certificates are renewed.
Why Is It Needed?
Kubernetes webhooks and aggregated API servers use TLS to communicate with the API server. The API server needs to trust the CA that signed the webhook’s serving certificate. Without the CA Injector, operators would need to manually extract the CA certificate from cert-manager Secrets and paste it into webhook configurations, a process that must be repeated every time the CA certificate changes.
2. How It Works
The CA Injector runs as a standalone controller that watches for annotated resources and source Secrets:
graph TD
CERT[Certificate Resource] -->|Issues cert to| SEC[Secret<br>tls.crt + ca.crt]
subgraph CA Injector
CTRL[Injection Controller]
end
CTRL -->|Reads ca.crt from| SEC
CTRL -->|Injects caBundle into| VWH[ValidatingWebhookConfiguration]
CTRL -->|Injects caBundle into| MWH[MutatingWebhookConfiguration]
CTRL -->|Injects caBundle into| CRD[CustomResourceDefinition]
CTRL -->|Injects caBundle into| APIS[APIService]
VWH -.->|Annotated with<br>cert-manager.io/inject-ca-from| CERT
MWH -.->|Annotated with<br>cert-manager.io/inject-ca-from| CERT
CRD -.->|Annotated with<br>cert-manager.io/inject-ca-from| CERT
APIS -.->|Annotated with<br>cert-manager.io/inject-ca-from| CERT
Injection Flow
- A user creates a Certificate resource that issues a TLS certificate for a webhook.
- cert-manager issues the certificate and stores it in a Secret, including the
ca.crtfield. - The user annotates the webhook configuration with
cert-manager.io/inject-ca-from: <namespace>/<certificate-name>. - The CA Injector detects the annotation, reads the
ca.crtfrom the referenced Certificate’s Secret, and patches the webhook configuration’scaBundlefield. - When the certificate is renewed and the CA changes, the CA Injector automatically updates the
caBundle.
3. Injection Sources
The CA Injector supports three annotation types, each specifying a different source for the CA bundle:
cert-manager.io/inject-ca-from
References a cert-manager Certificate resource by <namespace>/<name>. The CA Injector reads the ca.crt from the Certificate’s target Secret.
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: my-webhook
annotations:
cert-manager.io/inject-ca-from: cert-manager/my-webhook-cert
webhooks:
- name: validate.example.com
clientConfig:
caBundle: "" # Will be populated by cainjector
service:
name: my-webhook
namespace: cert-manager
cert-manager.io/inject-ca-from-secret
References a Kubernetes Secret directly by <namespace>/<name>. The CA Injector reads the ca.crt key from the Secret. This is useful when the CA certificate is managed outside of cert-manager.
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: my-webhook
annotations:
cert-manager.io/inject-ca-from-secret: cert-manager/my-ca-secret
cert-manager.io/inject-apiserver-ca
Injects the Kubernetes API server’s CA bundle (from the kube-root-ca.crt ConfigMap or the in-cluster CA). This is used when the webhook uses a certificate signed by the cluster’s CA.
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
name: v1alpha1.example.com
annotations:
cert-manager.io/inject-apiserver-ca: "true"
4. Target Resource Types
ValidatingWebhookConfiguration
Patches the caBundle field in each webhook entry:
webhooks:
- name: validate.example.com
clientConfig:
caBundle: <injected-ca-bundle> # Base64-encoded CA cert
MutatingWebhookConfiguration
Same structure as ValidatingWebhookConfiguration:
webhooks:
- name: mutate.example.com
clientConfig:
caBundle: <injected-ca-bundle>
CustomResourceDefinition
Patches the conversion webhook’s CA bundle:
spec:
conversion:
strategy: Webhook
webhook:
clientConfig:
caBundle: <injected-ca-bundle>
APIService
Patches the CA bundle for aggregated API servers:
spec:
caBundle: <injected-ca-bundle>
5. Internal Architecture
The CA Injector is built around a set of “injector” types, one for each target resource kind:
graph TD
subgraph Sources
CERT[Certificate → Secret]
SEC[Direct Secret]
APICA[API Server CA]
end
subgraph Injectors
VWI[ValidatingWebhook Injector]
MWI[MutatingWebhook Injector]
CRDI[CRD Injector]
APISI[APIService Injector]
end
CERT --> VWI
CERT --> MWI
CERT --> CRDI
CERT --> APISI
SEC --> VWI
SEC --> MWI
SEC --> CRDI
SEC --> APISI
APICA --> VWI
APICA --> MWI
APICA --> CRDI
APICA --> APISI
Each injector:
- Sets up informers to watch its target resource type.
- Filters resources by the presence of cert-manager annotations.
- Resolves the CA source (Certificate Secret, direct Secret, or API server CA).
- Patches the target resource with the CA bundle using a Kubernetes API patch.
Key Code Paths
- Entry Point:
cmd/cainjector/main.go- Starts the CA Injector controller. - Controller Setup:
pkg/controller/cainjector/controller.go- Registers injectors for each target resource type. - Injector Logic:
pkg/controller/cainjector/injector.go- Core injection logic: resolve source, extract CA, patch target. - Source Resolution:
pkg/controller/cainjector/sources.go- Resolves CA bundles from Certificates, Secrets, or the API server CA.
6. Leader Election
The CA Injector uses Kubernetes leader election to ensure only one replica is active at a time. This prevents conflicting patches to webhook configurations from multiple CA Injector instances.
- Leader Election Resource: A Lease object in the
cert-managernamespace. - Configuration: Controlled by
--leader-election-namespaceand--leader-electflags.
7. Configuration
Command-Line Flags
--leader-elect: Enable leader election (default: true).--leader-election-namespace: Namespace for the leader election Lease.--namespace: If set, restricts the CA Injector to watching resources in a specific namespace.--enable-certificates-data-source: Enable thecert-manager.io/inject-ca-fromannotation (default: true).--enable-apiservices-injectable: Enable injection into APIService resources (default: true).
Helm Values
cainjector:
enabled: true
replicaCount: 1
resources:
requests:
cpu: 50m
memory: 64Mi
8. Common Use Cases
Securing a Custom Webhook
The most common use case is injecting the CA bundle for a webhook that uses a cert-manager-issued TLS certificate:
# 1. Certificate for the webhook
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: my-webhook-tls
namespace: my-system
spec:
secretName: my-webhook-tls
issuerRef:
name: internal-ca
kind: ClusterIssuer
dnsNames:
- my-webhook.my-system.svc
- my-webhook.my-system.svc.cluster.local
---
# 2. Webhook configuration with CA injection annotation
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: my-webhook
annotations:
cert-manager.io/inject-ca-from: my-system/my-webhook-tls
webhooks:
- name: validate.my-system.io
clientConfig:
service:
name: my-webhook
namespace: my-system
path: /validate
rules:
- apiGroups: [""]
resources: ["pods"]
operations: ["CREATE"]
Self-Bootstrapping cert-manager
cert-manager’s own webhook uses the CA Injector to inject its CA bundle. This creates a bootstrap sequence:
- cert-manager webhook starts with a self-signed CA.
- The webhook stores its CA in a Secret.
- The CA Injector reads the Secret and injects the CA into the webhook configurations.
- The API server can now communicate with the webhook using the injected CA.
This self-bootstrapping design means cert-manager does not require any external certificate infrastructure to deploy.
9. Operational Considerations
- Startup Order: The CA Injector should start after the webhook has generated its serving certificate. In practice, Kubernetes retries webhook connections, so the order is not strictly enforced.
- Resource Permissions: The CA Injector needs RBAC permissions to read Secrets and patch webhook configurations, CRDs, and API services across the cluster.
- Memory Usage: The CA Injector caches all webhook configurations and watched Secrets in memory. In clusters with many webhooks, memory usage may be significant.
- Disabling: If you do not use cert-manager-issued certificates for webhooks, the CA Injector can be disabled via Helm (
cainjector.enabled: false) to reduce resource consumption.