kubernetes/kops · error
found VMSS without SSH public keys
Error message
found VMSS without SSH public keys
What it means
Find() expects linuxConfiguration.ssh.publicKeys to be a non-nil list so it can read the node SSH public key (sshKeys[0].KeyData). A nil list means the SSH block exists but carries no keys, so kOps cannot recover the cluster's authorized key and aborts.
Source
Thrown at upup/pkg/fi/cloudup/azuretasks/vmscaleset.go:175
if !strings.Contains(*i.ID, "api") {
continue
}
loadBalancerID, err = azure.ParseLoadBalancerID(*i.ID)
if err != nil {
return nil, fmt.Errorf("failed to parse loadbalancer ID %s", *i.ID)
}
}
}
osProfile := profile.OSProfile
if osProfile.LinuxConfiguration == nil {
return nil, fmt.Errorf("found VMSS without Linux config")
}
if osProfile.LinuxConfiguration.SSH == nil {
return nil, fmt.Errorf("found VMSS without SSH config")
}
if osProfile.LinuxConfiguration.SSH.PublicKeys == nil {
return nil, fmt.Errorf("found VMSS without SSH public keys")
}
sshKeys := osProfile.LinuxConfiguration.SSH.PublicKeys
if len(sshKeys) != 1 {
return nil, fmt.Errorf("expecting exactly 1 SSH key for %q, found %d: %+v", *s.Name, len(sshKeys), sshKeys)
}
var userData []byte
if profile.UserData != nil {
userData, err = base64.StdEncoding.DecodeString(*profile.UserData)
if err != nil {
return nil, fmt.Errorf("failed to decode user data: %w", err)
}
}
vmss := &VMScaleSet{
Name: s.Name,
Lifecycle: s.Lifecycle,
ResourceGroup: &ResourceGroup{View on GitHub (pinned to 4c8573c808)
Solutions
- Restore the SSH key: update the cluster spec's sshPublicKey and run `kops update cluster --yes` / `kops rolling-update cluster`.
- If authored externally, add at least one publicKey entry (path + keyData) to linuxConfiguration.ssh.publicKeys.
- Verify the key wasn't lost during a key-rotation edit; re-add it before deleting the old VMSS.
- Fix fixtures to include a publicKeys array with one key.
Example fix
// before
"ssh": { "publicKeys": null }
// after
"ssh": { "publicKeys": [ { "path": "/home/azureuser/.ssh/authorized_keys", "keyData": "ssh-rsa AAAA..." } ] } Defensive patterns
Strategy: validation
Validate before calling
keys := vmss.Properties.VirtualMachineProfile.OSProfile.LinuxConfiguration.SSH.PublicKeys
if keys == nil || len(keys) == 0 {
return fmt.Errorf("VMSS %s has no SSH public keys", fi.ValueOf(vmss.Name))
} Type guard
func hasPublicKeys(lc *compute.VirtualMachineScaleSetLinuxConfiguration) bool {
return lc != nil && lc.SSH != nil && lc.SSH.PublicKeys != nil && len(lc.SSH.PublicKeys) > 0
} Prevention
- Keep at least one ssh key defined in the cluster spec
- Never remove authorized keys directly on the VMSS
- Perform key rotation only via kops edit cluster + update + rolling-update
- Fix partial SSH fixtures in tests
When it happens
Trigger: Find() on a VMSS where linuxConfiguration.ssh is set but ssh.publicKeys is nil — SSH block present with zero keys, or a fixture that only sets the path.
Common situations: Scale sets whose authorized_keys were removed via portal/CLI; externally authored node pools with an empty ssh block; partially populated test fixtures.
Related errors
- found VMSS without Linux config
- found VMSS without SSH config
- expecting exactly 1 SSH key for %q, found %d: %+v
- expected exactly one subnet for InstanceGroup %q; subnets wa
- unexpected subnet type: for InstanceGroup %q; type was %s
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/ef3fe200d5d1ca60.
Report an issue: GitHub.