kubernetes/kops · error

configuration must include Subnets

Error message

configuration must include Subnets

What it means

retrieveClusterRefs loads the cluster from the state store and its channel, then asserts the cluster spec declares networking subnets. Subnets are mandatory because instance groups are placed into them (zone derivation uses these subnet entries), so a cluster without subnets cannot be used by the instance-selector.

Source

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

func retrieveClusterRefs(ctx context.Context, f commandutils.Factory, clusterName string) (simple.Clientset, *kops.Cluster, *kops.Channel, error) {
	clientset, err := f.KopsClient()
	if err != nil {
		return nil, nil, nil, err
	}

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

	channel, err := cloudup.ChannelForCluster(clientset.VFSContext(), cluster)
	if err != nil {
		return nil, nil, nil, err
	}

	if len(cluster.Spec.Networking.Subnets) == 0 {
		return nil, nil, nil, fmt.Errorf("configuration must include Subnets")
	}

	return clientset, cluster, channel, nil
}

func getFilters(commandline *cli.CommandLineInterface, region string, zones []string) selector.Filters {
	flags := commandline.Flags
	var cpuArch ec2types.ArchitectureType
	if v, ok := flags[cpuArchitecture]; ok {
		cpuArch = ec2types.ArchitectureType(*commandline.StringMe(v))
	}
	var uc ec2types.UsageClassType
	if v, ok := flags[usageClass]; ok {
		uc = ec2types.UsageClassType(*commandline.StringMe(v))
	}
	return selector.Filters{
		VCpusRange:             commandline.Int32RangeMe(flags[vcpus]),
		MemoryRange:            commandline.ByteQuantityRangeMe(flags[memory]),

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Add subnets to the cluster spec: `kops edit cluster <name>` and list subnets under spec.networking.subnets with proper type (e.g. public/private) and zones.
  2. Alternatively recreate the cluster manifest via `kops create cluster --zones ...` so subnets are generated.
  3. Confirm you are pointing at the intended cluster (`--name`) — another cluster in the state store may lack subnets.
  4. Run `kops validate cluster` / `kops get cluster -o yaml` to inspect the persisted spec before retrying.

Example fix

// before (cluster.yaml)
spec:
  networking:
    nonMasqueradeCIDR: 100.64.0.0/10
// after
spec:
  networking:
    nonMasqueradeCIDR: 100.64.0.0/10
    subnets:
      - name: us-east-1a
        type: Public
        zone: us-east-1a
        cidr: 172.20.32.0/19
Defensive patterns

Strategy: validation

Validate before calling

// Before running the selector:
clusterYaml=$(kops get cluster "$CLUSTER" -o yaml)
echo "$clusterYaml" | grep -q 'subnets:' || { echo "cluster has no subnets; edit cluster first"; exit 1; }

Try / catch

cluster, _, _, err := retrieveClusterRefs(clientset, cluster)
if err != nil {
	if strings.Contains(err.Error(), "must include Subnets") {
		return fmt.Errorf("cluster %s lacks subnets; run `kops edit cluster` and add spec.networking.subnets", clusterName)
	}
	return err
}

Prevention

When it happens

Trigger: Running `kops toolbox instance-selector` against a cluster whose manifest (or state store spec) has an empty cluster.Spec.Networking.Subnets list — e.g. a hand-edited or newly created cluster manifest that omitted subnets before instance groups were defined.

Common situations: Manually authored cluster YAML missing the `subnets:` section under spec.networking; a cluster created by tooling that defers subnet assignment; editing out subnets while refactoring the manifest.

Related errors


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