kubernetes/kops · error

control-plane InstanceGroup %s did not specify any Subnets

Error message

control-plane InstanceGroup %s did not specify any Subnets

What it means

Control-plane instance groups must have at least one subnet so kops knows where to place the masters. During instance-group finalization, a control-plane group with empty spec.subnets aborts creation with this message.

Source

Thrown at upup/pkg/fi/cloudup/new_cluster.go:575

				}
			}

		}

		if ig.Spec.Tenancy != "" && ig.Spec.Tenancy != "default" {
			switch cluster.GetCloudProvider() {
			case api.CloudProviderAWS:
				if _, ok := awsDedicatedInstanceExceptions[g.Spec.MachineType]; ok {
					return nil, fmt.Errorf("invalid dedicated instance type: %s", g.Spec.MachineType)
				}
			default:
				klog.Warning("Trying to set tenancy on non-AWS environment")
			}
		}

		if ig.IsControlPlane() {
			if len(ig.Spec.Subnets) == 0 {
				return nil, fmt.Errorf("control-plane InstanceGroup %s did not specify any Subnets", g.ObjectMeta.Name)
			}
		} else if ig.IsAPIServerOnly() && cluster.Spec.IsIPv6Only() {
			if len(ig.Spec.Subnets) == 0 {
				for _, subnet := range cluster.Spec.Networking.Subnets {
					if subnet.Type != api.SubnetTypePrivate && subnet.Type != api.SubnetTypeUtility {
						ig.Spec.Subnets = append(g.Spec.Subnets, subnet.Name)
					}
				}
			}
		} else {
			if len(ig.Spec.Subnets) == 0 {
				for _, subnet := range cluster.Spec.Networking.Subnets {
					if subnet.Type != api.SubnetTypeDualStack && subnet.Type != api.SubnetTypeUtility {
						g.Spec.Subnets = append(g.Spec.Subnets, subnet.Name)
					}
				}
			}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Add subnets to the control-plane instance group: `spec: subnets: [us-east-1a, us-east-1b]` matching cluster subnets.
  2. When using `kops create cluster`, pass --zones (and --networking/ topology flags) so kops auto-assigns subnets instead of hand-writing IG specs.
  3. Edit with `kops edit ig <name>` / fix the YAML, then `kops update cluster` again.

Example fix

// before
# control-plane IG yaml
metadata:
  name: master-us-east-1a
spec:
  role: ControlPlane
// after
metadata:
  name: master-us-east-1a
spec:
  role: ControlPlane
  subnets:
  - us-east-1a
Defensive patterns

Strategy: validation

Validate before calling

for _, ig := range instanceGroups {
    if ig.IsControlPlane() && len(ig.Spec.Subnets) == 0 {
        return fmt.Errorf("control-plane IG %s needs subnets before create", ig.Name)
    }
}

Type guard

func controlPlaneSubnetsSet(ig *api.InstanceGroup) bool {
    return ig != nil && ig.IsControlPlane() && len(ig.Spec.Subnets) > 0
}

Try / catch

_, err := NewCluster(opt, cluster, zoneMap)
if err != nil {
    if strings.Contains(err.Error(), "did not specify any Subnets") {
        return fmt.Errorf("add spec.subnets to the control-plane IG or pass --zones: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: `kops create cluster` with explicit instance group YAML lacking `subnets:`, or `kops create ig -f` for a control-plane group without subnets specified.

Common situations: Hand-written instance group manifests; templating that dropped the subnets field; converting clusters to explicit networking topology without updating IG specs.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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