kubernetes/kops · error
secrets path is not cluster readable: %v
Error message
secrets path is not cluster readable: %v
What it means
Analogous to the keypair store, the secrets store path must be readable by cluster nodes. run() throws this when the resolved SecretStore's VFS path fails vfs.IsClusterReadable. Without node-readable secrets storage, bootstrap cannot fetch required secrets.
Source
Thrown at upup/pkg/fi/cloudup/populate_cluster_spec.go:209
}
secretStore, err := clientset.SecretStore(cluster)
if err != nil {
return err
}
if cluster.Spec.ConfigStore.Secrets == "" {
hasVFSPath, ok := secretStore.(fi.HasVFSPath)
if !ok {
// We will mirror to ConfigBase
basedir := configBase.Join("secrets")
cluster.Spec.ConfigStore.Secrets = basedir.Path()
} else if vfs.IsClusterReadable(hasVFSPath.VFSPath()) {
vfsPath := hasVFSPath.VFSPath()
cluster.Spec.ConfigStore.Secrets = vfsPath.Path()
} else {
// We could implement this approach, but it seems better to get all clouds using cluster-readable storage
return fmt.Errorf("secrets path is not cluster readable: %v", hasVFSPath.VFSPath())
}
}
// Normalize k8s version
versionWithoutV := strings.TrimSpace(cluster.Spec.KubernetesVersion)
versionWithoutV = strings.TrimPrefix(versionWithoutV, "v")
if cluster.Spec.KubernetesVersion != versionWithoutV {
klog.V(2).Infof("Normalizing kubernetes version: %q -> %q", cluster.Spec.KubernetesVersion, versionWithoutV)
cluster.Spec.KubernetesVersion = versionWithoutV
}
if cluster.Spec.CloudProvider.Openstack == nil {
if cluster.Spec.API.DNS == nil && cluster.Spec.API.LoadBalancer == nil {
subnetTypesByName := map[string]kopsapi.SubnetType{}
for _, subnet := range cluster.Spec.Networking.Subnets {
subnetTypesByName[subnet.Name] = subnet.Type
}
View on GitHub (pinned to 4c8573c808)
Solutions
- Set configStore.secrets to a cluster-readable path (or leave unset to mirror into <configBase>/secrets).
- Grant node instance profiles/roles read access to the secrets bucket.
- Verify with the path in the error message that the scheme and bucket are correct and accessible from nodes.
Example fix
# before configStore: secrets: file:///etc/kops/secrets # after configStore: secrets: s3://my-kops-state-bucket/cluster.example.com/secrets
Defensive patterns
Strategy: validation
Validate before calling
if cluster.Spec.ConfigStore.Secrets != "" && !strings.HasPrefix(cluster.Spec.ConfigStore.Secrets, "s3://") {
return fmt.Errorf("secrets store path must be cluster readable")
} Prevention
- Leave configStore.secrets unset to mirror into configBase/secrets
- Keep secrets in the same bucket as config with node read access
- Re-check secret store permissions after IAM or account changes
When it happens
Trigger: cluster.spec.configStore.secrets is empty and the SecretStore's VFS path (via fi.HasVFSPath) is not cluster readable — e.g. a secrets bucket inaccessible to node IAM roles.
Common situations: Secrets stored in a separate bucket with restrictive permissions; local file:// secret store used with a real cloud cluster; cloned cluster configs referencing another account's storage.
Related errors
- error loading secret %q: %w
- cannot parse SecretStore %q: %w
- ConfigStore.Base path is not cluster readable: %v
- keyStore path is not cluster readable: %v
- error writing secret to %q: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/c586702a9c63c3d5.
Report an issue: GitHub.