Skip to content

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

  1. 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
    
  2. Now, verify that it synced correctly and that the target ConfigMap was created:

    kubectl get bundle example-bundle
    

    Expected 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

  1. 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
    
  2. Check the generated Secret:

    kubectl get -n cert-manager secret trust-manager-example-ca-secret \
      -o "jsonpath={.data['tls\.crt']}" | base64 -d
    

    The tls.crt field 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 key field 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.