kubernetes/kops · error

must specify %q label with cluster name to replace SSHCreden

Error message

must specify %q label with cluster name to replace SSHCredential

What it means

When replacing an SSHCredential object, `kops replace` derives the target cluster from the metadata label `kops.k8s.io/cluster` (kopsapi.LabelClusterName). The manifest lacks that label, so the command cannot determine which cluster's SSH credential store to write to and aborts.

Source

Thrown at cmd/kops/replace.go:200

					}
				}
				switch ig {
				case nil:
					klog.Infof("instanceGroup: %v was not found, creating resource now", igName)
					_, err = clientset.InstanceGroupsFor(cluster).Create(ctx, v, metav1.CreateOptions{})
					if err != nil {
						return fmt.Errorf("error creating instanceGroup: %v", err)
					}
				default:
					_, err = clientset.InstanceGroupsFor(cluster).Update(ctx, v, metav1.UpdateOptions{})
					if err != nil {
						return fmt.Errorf("error replacing instanceGroup: %v", err)
					}
				}
			case *kopsapi.SSHCredential:
				clusterName := v.ObjectMeta.Labels[kopsapi.LabelClusterName]
				if clusterName == "" {
					return fmt.Errorf("must specify %q label with cluster name to replace SSHCredential", kopsapi.LabelClusterName)
				}
				if v.Spec.PublicKey == "" {
					return fmt.Errorf("spec.PublicKey is required")
				}

				cluster, err := clientset.GetCluster(ctx, clusterName)
				if err != nil {
					return err
				}

				sshCredentialStore, err := clientset.SSHCredentialStore(cluster)
				if err != nil {
					return err
				}

				sshKeyArr := []byte(v.Spec.PublicKey)
				err = sshCredentialStore.AddSSHPublicKey(ctx, sshKeyArr)
				if err != nil {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Add the label to the manifest: `metadata.labels.kops.k8s.io: <cluster-name>` (the exact kops.k8s.io/cluster key).
  2. Or export an existing correct manifest with `kops get sshpublickey <cluster> -o yaml` as a template.
  3. Specify the cluster on the command line (`kops replace -f ssh.yaml --name <cluster>`) where supported, so other fields are validated against the right cluster.

Example fix

# before
metadata:
  name: admin
# after
metadata:
  name: admin
  labels:
    kops.k8s.io/cluster: mycluster.example.com
Defensive patterns

Strategy: validation

Validate before calling

func validateSSHCred(manifest map[string]interface{}) error {
    meta, _ := manifest["metadata"].(map[string]interface{})
    labels, _ := meta["labels"].(map[string]interface{})
    if labels["kops.k8s.io/cluster"] == "" {
        return fmt.Errorf("manifest must set metadata.labels.kops.k8s.io/cluster")
    }
    return nil
}

Prevention

When it happens

Trigger: Applying an SSHCredential YAML that has no `metadata.labels.kops.k8s.io/cluster: <clustername>` entry, e.g. a hand-written manifest or one exported from a source that stripped labels.

Common situations: Hand-authoring an SSH credential manifest from documentation examples; copying a manifest between clusters and removing/renaming labels; exporting with a tool that drops metadata labels.

Related errors


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