kubernetes/kops · error

error instance group cannot span public and private subnets

Error message

error instance group cannot span public and private subnets

What it means

Thrown by validateAllPrivateOrPublicSubnets during `kops toolbox instance-selector` subnet validation. It counts subnets prefixed with "utility-" (kOps public subnets) and rejects the request when the subnet list mixes utility (public) and non-utility (private) subnets, because an instance group spanning both public and private subnets is not a supported configuration.

Source

Thrown at cmd/kops/toolbox_instance-selector.go:489

		}
		if !userSubnetValid {
			return fmt.Errorf("error subnets must exist in the cluster")
		}
	}
	return nil
}

// validateAllPrivateOrPublicSubnets makes sure the passed in subnets are all utility (public) subnets or private subnets
func validateAllPrivateOrPublicSubnets(userSubnets []string) error {
	utilitySubnets := 0
	for _, userSubnet := range userSubnets {
		if strings.HasPrefix(userSubnet, "utility-") {
			utilitySubnets++
		}
	}

	if utilitySubnets != 0 && len(userSubnets) != utilitySubnets {
		return fmt.Errorf("error instance group cannot span public and private subnets")
	}
	return nil
}

func createInstanceGroup(groupName, clusterName string, subnets []string) *kops.InstanceGroup {
	ig := &kops.InstanceGroup{}
	ig.ObjectMeta.Name = groupName
	ig.Spec.Role = kops.InstanceGroupRoleNode
	ig.Spec.Subnets = subnets
	ig.ObjectMeta.Labels = make(map[string]string)
	ig.ObjectMeta.Labels[kops.LabelClusterName] = clusterName

	ig.AddInstanceGroupNodeLabel()
	return ig
}

func decorateWithInstanceGroupSpecs(instanceGroup *kops.InstanceGroup, instanceGroupOpts *InstanceSelectorOptions) *kops.InstanceGroup {
	ig := instanceGroup

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Use only private subnets for the instance group: drop the utility- prefixed entries from --subnets
  2. Or use only utility- (public) subnets if the group truly must be public (rare for nodes; typical only for bastions)
  3. Check the cluster topology: `kops get cluster -o yaml` and match instance group subnets to one class of subnets
  4. For a public-facing role, create a separate instance group rather than mixing subnets in one group

Example fix

// before
kops toolbox instance-selector --name nodes --subnets us-east-1a,utility-us-east-1b

// after (private group)
kops toolbox instance-selector --name nodes --subnets us-east-1a,us-east-1b
Defensive patterns

Strategy: validation

Validate before calling

utility := 0
for _, s := range requestedSubnets {
    if strings.HasPrefix(s, "utility-") { utility++ }
}
if utility != 0 && utility != len(requestedSubnets) {
    return fmt.Errorf("subnets mix public (utility-*) and private; pick one class")
}

Prevention

When it happens

Trigger: Passing a --subnets list to `kops toolbox instance-selector` that contains at least one "utility-*" subnet and at least one subnet without the "utility-" prefix (e.g. --subnets us-east-1a,utility-us-east-1a).

Common situations: Mixing public and private subnets when defining node instance groups; assuming kOps will auto-route a group across both; generated scripts from a public cluster reused on a private-topology cluster (or vice versa); misunderstanding that the utility- prefix denotes public subnets.

Related errors


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