kubernetes/kubernetes · error

discovery failed for ClusterTrustBundle: %w

Error message

discovery failed for ClusterTrustBundle: %w

What it means

The kube-apiserver-serving ClusterTrustBundle publisher probes each certificates API group version (v1, v1beta1, v1alpha1) via discovery to find one that serves the 'clustertrustbundles' resource. clusterTrustBundlesAvailable calls ServerResourcesForGroupVersion; if it returns an error other than NotFound (which is handled), discovery is treated as failed and the controller aborts.

Source

Thrown at cmd/kube-controller-manager/app/certificates.go:335

		certificatesv1alpha1.SchemeGroupVersion: ctbpublisher.NewAlphaClusterTrustBundlePublisher,
		certificatesv1beta1.SchemeGroupVersion:  ctbpublisher.NewBetaClusterTrustBundlePublisher,
		certificatesv1.SchemeGroupVersion:       ctbpublisher.NewGAClusterTrustBundlePublisher,
	}

	apiserverSignerClient, err := controllerContext.NewClient("kube-apiserver-serving-clustertrustbundle-publisher")
	if err != nil {
		return nil, err
	}

	var runner ctbpublisher.PublisherRunner
	for _, gv := range []schema.GroupVersion{
		certificatesv1.SchemeGroupVersion,
		certificatesv1beta1.SchemeGroupVersion,
		certificatesv1alpha1.SchemeGroupVersion,
	} {
		ctbAvailable, err := clusterTrustBundlesAvailable(apiserverSignerClient, gv)
		if err != nil {
			return nil, fmt.Errorf("discovery failed for ClusterTrustBundle: %w", err)
		}

		if !ctbAvailable {
			continue
		}

		runner, err = schemaControllerMapping[gv](
			"kubernetes.io/kube-apiserver-serving",
			servingSigners,
			apiserverSignerClient,
		)
		if err != nil {
			return nil, fmt.Errorf("error creating kube-apiserver-serving signer certificates publisher: %w", err)
		}
		break
	}

	if runner == nil {

View on GitHub (pinned to b882c60b40)

Solutions

  1. Confirm apiserver discovery works: kubectl api-resources --api-group=certificates.k8s.io and kubectl get --raw=/apis/certificates.k8s.io/v1 (and v1beta1/v1alpha1).
  2. Check apiserver health and logs for 5xx/throttling at startup; restart kube-controller-manager after apiserver is stable.
  3. Verify the controller-manager's credentials/RBAC permit discovery of certificates.k8s.io.
  4. If ClusterTrustBundle is not required, disable the feature gate (ClusterTrustBundle) so this publisher is not constructed.
Defensive patterns

Strategy: retry

Validate before calling

# Pre-flight: confirm discovery of certificates.k8s.io works and CTB exists in some version.
kubectl api-resources --api-group=certificates.k8s.io | grep -i clustertrustbundle || echo "warn: no clustertrustbundles discovered in any version"
kubectl get --raw=/apis/certificates.k8s.io/v1 2>/dev/null | grep -i clustertrustbundle || true
# Confirm RBAC permits discovery for the controller-manager's identity.

Try / catch

// clusterTrustBundlesAvailable returns a transient error on transport/5xx failures;
// NotFound is already handled (returns false,nil). Treat the non-NotFound error as
// retryable: back off and re-run NewController* after the apiserver is stable.
ctbAvailable, err := clusterTrustBundlesAvailable(apiserverSignerClient, gv)
if err != nil && !apierrors.IsNotFound(err) {
    return nil, fmt.Errorf("discovery failed for ClusterTrustBundle: %w", err)
}

Prevention

When it happens

Trigger: certificates.go:333 calls clusterTrustBundlesAvailable(apiserverSignerClient, gv) which calls client.Discovery().ServerResourcesForGroupVersion(gv). It returns a non-nil, non-NotFound error (certificates.go:363-376) on a discovery transport error, an unexpected apiserver 5xx, auth failure, or a partial/nil resList with an error.

Common situations: Transient apiserver unavailability or throttling during controller-manager startup. RBAC denying discovery of certificates.k8s.io. Network/TLS blip to the apiserver. Aggregated apiserver/extension apiserver backing certificates.k8s.io returning errors. The ClusterTrustBundle feature gate enabled on a cluster whose apiserver is mid-rollout.

Related errors


AI-assisted analysis of kubernetes/kubernetes@b882c60b40 (2026-08-07). Data as JSON: /api/errors/33b92c04f4b54f5d. Report an issue: GitHub.