Quick start: Creating Your First Bundle¶
Step 1: Create a Cluster and Namespace¶
Let's get started by creating your first Bundle using kind to run Kubernetes in a containerized environment:
kind create cluster
# Wait for the cluster to start...
Step 2: Install Trust Manager¶
You can follow the official installation guide, or use the commands below to install Trust Manager and its dependencies.
helm repo add jetstack https://charts.jetstack.io --force-update
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.19.1 \
--set crds.enabled=true
helm upgrade trust-manager jetstack/trust-manager \
--install \
--namespace cert-manager \
--wait
Step 3: Create a Bundle¶
-
Once Trust Manager is running, you can create a Bundle using the default Certificate Authorities (CAs) that were configured during startup. Because we installed Trust Manager with Helm, the default CA package includes publicly trusted certificates derived from a Debian base image.
To create a bundle:
kubectl apply -f - <<EOF apiVersion: trust.cert-manager.io/v1alpha1 kind: Bundle metadata: name: example-bundle spec: sources: - useDefaultCAs: true target: configMap: key: "trust-bundle.pem" EOF -
Now, verify that it synced correctly and that the target ConfigMap was created:
kubectl get bundle example-bundleExpected output:
NAME CONFIGMAP TARGET SECRET TARGET SYNCED REASON AGE example-bundle trust-bundle.pem True Synced ...
Step 4: Inspect the Trust Bundle¶
You can view the contents of the trust bundle, which includes a collection of PEM-formatted certificates:
kubectl get configmap example-bundle -o "jsonpath={.data['trust-bundle\.pem']}" | less
At this point, you have a working trust bundle that your workloads can consume.
Let’s go a step further and add a private Certificate Authority (CA) to the bundle.
Step 5: Create a Private CA with cert-manager¶
-
Use cert-manager to generate a self-signed CA certificate:
kubectl apply -f - <<EOF apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: trust-manager-selfsigned-issuer spec: selfSigned: {} --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: trust-manager-example-ca namespace: cert-manager spec: isCA: true commonName: trust-manager-example-ca secretName: trust-manager-example-ca-secret privateKey: algorithm: ECDSA size: 256 issuerRef: name: trust-manager-selfsigned-issuer kind: ClusterIssuer group: cert-manager.io EOF -
Check the generated Secret:
kubectl get -n cert-manager secret trust-manager-example-ca-secret \ -o "jsonpath={.data['tls\.crt']}" | base64 -dThe
tls.crtfield contains your PEM-encoded CA certificate.
Why tls.crt and not ca.crt?
cert-manager stores the issued certificate in tls.crt. This is consistent across certificate types and simplifies secret management.
Step 6: Update the Bundle to include the Private CA¶
Update the existing Bundle to include both the default CAs and your new private CA.
Warning
This approach is not recommended for production. Combining default and private roots in the same ConfigMap can cause issues during CA rotation. In production, use a separate ConfigMap or Secret for trusted roots.
kubectl apply -f - <<EOF
apiVersion: trust.cert-manager.io/v1alpha1
kind: Bundle
metadata:
name: example-bundle
spec:
sources:
- useDefaultCAs: true
- secret:
name: "trust-manager-example-ca-secret"
key: "tls.crt"
target:
configMap:
key: "trust-bundle.pem"
EOF
Step 7: Verify the update¶
The example-bundle ConfigMap should now be updated automatically. Inspect the ConfigMap again:
kubectl get configmap example-bundle -o "jsonpath={.data['trust-bundle\.pem']}" | less
The last certificate in the list should be your newly created dummy CA.
You’ve successfully created and extended a trust bundle using Trust Manager. You can now distribute and consume this trust data securely across your Kubernetes workloads.
Troubleshooting and validation¶
Bundle not syncing?¶
Check the trust-manager controller logs for error messages:
kubectl logs -n cert-manager deploy/trust-manager
Look for lines mentioning:
-“failed to fetch source”
-
“invalid namespaceSelector”
-
“permissions denied”
These usually indicate configuration or RBAC issues.
Bundle shows Synced=False?¶
Inspect the Bundle’s status:
kubectl describe bundle example-bundle
If the Reason field indicates a source or target issue, verify:
-
The referenced ConfigMap or Secret exists.
-
The
keyfield matches the data key containing your certificate. -
The Trust Manager ServiceAccount has permissions to access the resource.
Certificate not included in bundle?¶
Check your Secret’s contents:
kubectl get secret trust-manager-example-ca-secret -n cert-manager -o yaml
Ensure that:
-
The correct data key (e.g.,
tls.crt) exists. -
The certificate is valid (decode and inspect the PEM block).
Need to reset the bundle?¶
You can safely delete and recreate it:
kubectl delete bundle example-bundle
kubectl apply -f example-bundle.yaml
This will trigger a full resync.