kubernetes/kops · error
error adding SSH public key: %v
Error message
error adding SSH public key: %v
What it means
After successfully reading the file given by --ssh-public-key, `kops update cluster` adds it to the cluster's SSH credential store via AddSSHPublicKey. If that backend write fails, the error is surfaced as `error adding SSH public key: %v`. The key was read fine but could not be persisted to the cluster secrets backend.
Source
Thrown at cmd/kops/update_cluster.go:302
return results, err
}
secretStore, err := clientset.SecretStore(cluster)
if err != nil {
return results, err
}
if c.SSHPublicKey != "" {
fmt.Fprintf(out, "--ssh-public-key on update is deprecated - please use `kops create secret --name %s sshpublickey admin -i ~/.ssh/id_rsa.pub` instead\n", cluster.ObjectMeta.Name)
c.SSHPublicKey = utils.ExpandPath(c.SSHPublicKey)
authorized, err := os.ReadFile(c.SSHPublicKey)
if err != nil {
return results, fmt.Errorf("error reading SSH key file %q: %v", c.SSHPublicKey, err)
}
err = sshCredentialStore.AddSSHPublicKey(ctx, authorized)
if err != nil {
return results, fmt.Errorf("error adding SSH public key: %v", err)
}
klog.Infof("Using SSH public key: %v\n", c.SSHPublicKey)
}
var phase cloudup.Phase
if c.Phase != "" {
switch strings.ToLower(c.Phase) {
case string(cloudup.PhaseNetwork):
phase = cloudup.PhaseNetwork
case string(cloudup.PhaseSecurity), "iam": // keeping IAM for backwards compatibility
phase = cloudup.PhaseSecurity
case string(cloudup.PhaseCluster):
phase = cloudup.PhaseCluster
default:
return results, fmt.Errorf("unknown phase %q, available phases: %s", c.Phase, strings.Join(cloudup.Phases.List(), ","))
}
}View on GitHub (pinned to 4c8573c808)
Solutions
- Inspect the wrapped error for the backend cause; fix credentials/permissions and retry
- Verify the key file contains a valid one-line OpenSSH public key
- Use `kops create secret sshpublickey admin -i <file>` directly to isolate and diagnose the store error
- Ensure no concurrent kops command holds the cluster update lock
Example fix
// before authorized="" # accidentally truncated file kops update cluster c.k8s.local --ssh-public-key ./admin.pub --yes // after ssh-keygen -y -f ~/.ssh/id_ed25519 > ./admin.pub # regenerate valid key kops update cluster c.k8s.local --ssh-public-key ./admin.pub --yes
Defensive patterns
Strategy: validation
Validate before calling
data, err := os.ReadFile(utils.ExpandPath(keyPath))
if err != nil || len(bytes.TrimSpace(data)) == 0 {
return fmt.Errorf("SSH public key %q is empty or unreadable", keyPath)
}
if _, _, _, _, err := ssh.ParseAuthorizedKey(data); err != nil {
return fmt.Errorf("%q is not a valid OpenSSH public key", keyPath)
}
// safe to call update / AddSSHPublicKey Prevention
- Validate the key parses with golang.org/x/crypto/ssh before storing
- Ensure the state-store backend is writable (credentials, IAM, KMS) beforehand
- Avoid concurrent kops secret mutations
- Regenerate keys with ssh-keygen if a file is truncated or corrupted
When it happens
Trigger: AddSSHPublicKey fails: underlying secret store unavailable or unwritable (S3/GCS/etcd backend errors, permission denied), SSH key rejected (empty file, invalid format), or concurrency conflict updating the secret.
Common situations: State-store credentials expired mid-run; SSH key file accidentally empty; bucket/KMS permissions changed; cluster locked by another concurrent kops operation.
Related errors
- must specify %q label with cluster name to create SSHCredent
- spec.PublicKey is required
- error reading SSH key file %q: %v
- error writing updated configuration: %v
- error reading SSH public key files %q: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/9ac61c181132cd16.
Report an issue: GitHub.