kubernetes/kops · error
found VMSS without SSH config
Error message
found VMSS without SSH config
What it means
After confirming LinuxConfiguration exists, Find() requires osProfile.linuxConfiguration.ssh to be present so it can read the authorized public keys. A nil SSH block means the scale set has no SSH configuration at all, which kOps treats as unmodelable and returns this error.
Source
Thrown at upup/pkg/fi/cloudup/azuretasks/vmscaleset.go:172
var loadBalancerID *azure.LoadBalancerID
if ipConfig.Properties.LoadBalancerBackendAddressPools != nil {
for _, i := range ipConfig.Properties.LoadBalancerBackendAddressPools {
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{View on GitHub (pinned to 4c8573c808)
Solutions
- Reconcile the scale set via `kops update cluster --yes` so SSH config is regenerated from the cluster spec.
- If authored externally, add the ssh block with at least one publicKey under linuxConfiguration.
- Check the SSH key data in the cluster spec (`kops get cluster -oyaml`, sshPublicKey field) and update it if it was removed.
- Fix test fixtures to include SSHConfiguration with PublicKeys.
Example fix
// before
"linuxConfiguration": { "disablePasswordAuthentication": true }
// after
"linuxConfiguration": { "disablePasswordAuthentication": true, "ssh": { "publicKeys": [ { "path": "/home/azureuser/.ssh/authorized_keys", "keyData": "ssh-rsa AAAA..." } ] } } Defensive patterns
Strategy: validation
Validate before calling
if vmss.Properties.VirtualMachineProfile.OSProfile.LinuxConfiguration.SSH == nil {
return fmt.Errorf("VMSS %s lacks SSH configuration", fi.ValueOf(vmss.Name))
} Type guard
func hasSSHConfig(lc *compute.VirtualMachineScaleSetLinuxConfiguration) bool {
return lc != nil && lc.SSH != nil
} Prevention
- Always include the ssh block when defining linuxConfiguration externally
- Set sshPublicKey in the cluster spec and let kops render SSH config
- Avoid editors/tooling that strip nested ARM fields
- Cover the ssh block in template/unit tests
When it happens
Trigger: Find() on a VMSS where linuxConfiguration is set but linuxConfiguration.ssh is nil — e.g. linuxConfiguration created with only disablePasswordAuthentication and no ssh sub-object, or stripped by external tooling.
Common situations: Custom ARM/Bicep/Terraform definitions of node pools omitting the ssh block; drift after manual portal edits; test fixtures that populate linuxConfiguration partially.
Related errors
- found VMSS without Linux config
- found VMSS without SSH public keys
- 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/45dc29614d2a0c80.
Report an issue: GitHub.