kubernetes/kops · error

failed to get bootstrap data secret: %w

Error message

failed to get bootstrap data secret: %w

What it means

This error wraps any failure from the controller-runtime client Get when reading the bootstrap-data Secret named after the KopsConfig object (pkg/controllers/clusterapi/kopsconfig_controller.go:155-161). It is thrown only when the Get fails for a reason OTHER than NotFound (NotFound is handled by creating the secret instead), so it indicates the API server rejected or failed the read. The controller cannot proceed to store bootstrap data, and Reconcile returns the error to trigger a retry with backoff.

Source

Thrown at pkg/controllers/clusterapi/kopsconfig_controller.go:161

	parentAPIVersion, parentKind := parent.GetObjectKind().GroupVersionKind().ToAPIVersionAndKind()
	secret.OwnerReferences = []metav1.OwnerReference{
		{
			APIVersion: parentAPIVersion,
			Kind:       parentKind,
			Name:       parent.GetName(),
			UID:        parent.GetUID(),
			Controller: pointer.Bool(true),
		},
	}

	var existing corev1.Secret
	if err := r.client.Get(ctx, secretName, &existing); err != nil {
		if apierrors.IsNotFound(err) {
			if err := r.client.Create(ctx, secret); err != nil {
				return fmt.Errorf("failed to create bootstrap data secret for KopsConfig %s/%s: %w", parent.GetNamespace(), parent.GetName(), err)
			}
		} else {
			return fmt.Errorf("failed to get bootstrap data secret: %w", err)
		}
	} else {
		// TODO: Verify that the existing secret "matches"
		klog.Warningf("TODO: verify that the existing secret matches our expected value")
	}

	parent.Status.DataSecretName = pointer.String(secret.Name)
	parent.Status.Ready = true
	// conditions.MarkTrue(scope.Config, bootstrapv1.DataSecretAvailableCondition)
	return nil
}

func (r *KopsConfigReconciler) buildBootstrapData(ctx context.Context, cluster *kopsapi.Cluster, kopsControlPlane *capikops.KopsControlPlane) ([]byte, error) {
	wellKnownAddresses := model.WellKnownAddresses{}
	for _, systemEndpoint := range kopsControlPlane.Status.SystemEndpoints {
		switch systemEndpoint.Type {
		case capikops.SystemEndpointTypeKopsController:
			wellKnownAddresses[wellknownservices.KopsController] = append(wellKnownAddresses[wellknownservices.KopsController], systemEndpoint.Endpoint)

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check RBAC: ensure the controller's ServiceAccount has get/list on secrets in the KopsConfig namespace (see the +kubebuilder:rbac markers; verify with kubectl auth can-i get secrets --as=system:serviceaccount:<ns>:<sa>).
  2. Check API server health and connectivity from the controller pod (kubectl get --raw /healthz from an exec, or inspect controller logs for connection refused/timeout).
  3. Inspect the wrapped error text after 'failed to get bootstrap data secret:' to identify the exact cause (forbidden vs timeout vs context canceled).
  4. If errors are transient (timeouts), they will be retried by controller-runtime; verify the error clears rather than modifying data.
  5. If a mutating admission webhook intercepts Secrets, verify it is not rejecting or delaying GET-related operations and is reachable.

Example fix

// before: controller RBAC missing secrets read
// (manifest omits ClusterRole rule)
// after
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["create", "get", "list", "watch", "patch", "update"]
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: pre-check secret read access before relying on the controller
err := r.client.Get(ctx, secretName, &existing)
if err != nil && !apierrors.IsNotFound(err) {
	// surface wrapped cause early
}
// CLI RBAC pre-check:
// kubectl auth can-i get secret <name> -n <ns> --as=system:serviceaccount:<ns>:<sa>

Type guard

// Go: classify the error before reacting
func isRealSecretError(err error) bool {
	return err != nil && !apierrors.IsNotFound(err) // NotFound is handled by Create path
}

Try / catch

if err := r.storeBootstrapData(ctx, obj, data); err != nil {
	if apierrors.IsForbidden(err) {
		// fix RBAC (RoleBinding) rather than retrying
		return ctrl.Result{}, fmt.Errorf("fix secrets RBAC: %w", err)
	}
	// transient API server errors: let controller-runtime retry with backoff
	return ctrl.Result{}, err // requeue
}

Prevention

When it happens

Trigger: The Get of Secret <namespace>/<kopsconfig-name> fails with a non-NotFound error: RBAC denial (no get permission on secrets), API server connection errors/timeouts, the secret exists but cannot be read (e.g. too large, corrupted), context cancellation during reconcile, or webhook/authorizer failures.

Common situations: Operators deploying the kops cluster-api controllers without the kubebuilder-generated RBAC for secrets; an API server outage or network partition in the management cluster; reconcile running with an expired or revoked service-account token; a security policy (e.g. PSA restricted, admission webhook) blocking secret reads.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/fa1c24d655d9704b. Report an issue: GitHub.