kubernetes/kops · error
exactly one 'admin' SSH public key can be specified when run
Error message
exactly one 'admin' SSH public key can be specified when running with Scaleway; please delete a key using `kops delete secret`
What it means
For Scaleway clusters kOps enforces exactly one 'admin' SSH public key. In apply_cluster.go Run, if more than one sshpublickey secret exists the apply is rejected, mirroring the OpenStack rule, because the Scaleway path provisions a single admin keypair.
Source
Thrown at upup/pkg/fi/cloudup/apply_cluster.go:495
return nil, fmt.Errorf("SSH public key must be specified when running with Openstack (create with `kops create secret --name %s sshpublickey admin -i ~/.ssh/id_rsa.pub`)", cluster.ObjectMeta.Name)
}
if len(sshPublicKeys) != 1 {
return nil, fmt.Errorf("exactly one 'admin' SSH public key can be specified when running with Openstack; please delete a key using `kops delete secret`")
}
}
case kops.CloudProviderScaleway:
{
if !featureflag.Scaleway.Enabled() {
return nil, fmt.Errorf("Scaleway support is currently alpha, and is feature-gated. export KOPS_FEATURE_FLAGS=Scaleway")
}
if len(sshPublicKeys) == 0 {
return nil, fmt.Errorf("SSH public key must be specified when running with Scaleway (create with `kops create secret --name %s sshpublickey admin -i ~/.ssh/id_rsa.pub`)", cluster.ObjectMeta.Name)
}
if len(sshPublicKeys) != 1 {
return nil, fmt.Errorf("exactly one 'admin' SSH public key can be specified when running with Scaleway; please delete a key using `kops delete secret`")
}
scwCloud := cloud.(scaleway.ScwCloud)
scwZone = scwCloud.Zone()
}
case kops.CloudProviderLinode:
{
if !featureflag.Linode.Enabled() {
return nil, fmt.Errorf("Akamai (Linode) support is currently alpha, and is feature-gated. Please export KOPS_FEATURE_FLAGS=Linode")
}
}
case kops.CloudProviderMetal:
// Metal is a special case, we don't need to do anything here (yet)
default:
return nil, fmt.Errorf("unknown CloudProvider %q", cluster.GetCloudProvider())View on GitHub (pinned to 4c8573c808)
Solutions
- Delete surplus keys: `kops delete secret sshpublickey <extra-name> --name <cluster>`
- Keep exactly one (typically 'admin'): verify with `kops get secrets`
- Rerun `kops update cluster`
Example fix
// before: admin + laptop keys exist kops delete secret sshpublickey laptop --name scw.example.com // after: only 'admin'; update succeeds
Defensive patterns
Strategy: validation
Validate before calling
count=$(kops get secrets --name "$CLUSTER" | grep -c sshpublickey); [ "$count" -le 1 ] || kops delete secret sshpublickey <extra> --name "$CLUSTER"
Try / catch
if err := updateCluster(); err != nil { if strings.Contains(err.Error(), "exactly one 'admin' SSH public key") { listAndPruneKeys(); retry() } return err } Prevention
- Treat 'admin' as the only sshpublickey; never add additional named keys on scaleway
- Periodically audit secrets for duplicates
- Wrap key rotation so old keys are deleted in the same step new ones are added
When it happens
Trigger: `kops update cluster` on a scaleway cluster whose secret store contains two or more sshpublickey entries.
Common situations: Accumulated keys from repeated `kops create secret sshpublickey` runs with different names, or migrating keys from another provider's cluster.
Related errors
- SSH public key must be specified when running with Scaleway
- exactly one 'admin' SSH public key can be specified when run
- bastion is not set, but useBastion is true
- creating client for Scaleway NodeIdentifier: %w
- Scaleway support is currently alpha, and is feature-gated.
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/3a869602834f2c69.
Report an issue: GitHub.