kubernetes/kops · error
must configure at least one ControlPlane InstanceGroup
Error message
must configure at least one ControlPlane InstanceGroup
What it means
DeepValidate requires at least one InstanceGroup with the ControlPlane role, because a Kubernetes cluster needs control-plane (master) nodes. It counts groups where g.IsControlPlane() is true and returns this error when the count is zero, even if node groups exist.
Source
Thrown at pkg/apis/kops/validation/legacy.go:291
return errs.ToAggregate()
}
if len(groups) == 0 {
return fmt.Errorf("must configure at least one InstanceGroup")
}
controlPlaneGroupCount := 0
nodeGroupCount := 0
for _, g := range groups {
if g.IsControlPlane() {
controlPlaneGroupCount++
} else {
nodeGroupCount++
}
}
if controlPlaneGroupCount == 0 {
return fmt.Errorf("must configure at least one ControlPlane InstanceGroup")
}
if nodeGroupCount == 0 {
return fmt.Errorf("must configure at least one Node InstanceGroup")
}
for _, g := range groups {
errs := CrossValidateInstanceGroup(g, c, cloud, strict)
// Additional cloud-specific validation rules
if c.GetCloudProvider() != kops.CloudProviderAWS && len(g.Spec.Volumes) > 0 {
errs = append(errs, field.Forbidden(field.NewPath("spec", "volumes"), "instancegroup volumes are only available with aws at present"))
}
if len(errs) != 0 {
return errs.ToAggregate()
}
}View on GitHub (pinned to 4c8573c808)
Solutions
- Add an InstanceGroup with spec.role: ControlPlane (at least 1 replica, ideally 3 for HA)
- Fix the role field on an existing group from Node to ControlPlane via kops edit ig <name>
- Ensure group names don't implicitly confer roles — role must be explicitly ControlPlane
- Re-run kops update cluster --yes after correcting the group roles
Example fix
// before spec: role: Node machineType: m5.large // after spec: role: ControlPlane machineType: m5.large minSize: 1 maxSize: 1
Defensive patterns
Strategy: validation
Validate before calling
var cp, node int
for _, g := range groups {
switch {
case g.IsControlPlane():
cp++
case g.IsMaster(): // legacy role check fallback
cp++
default:
node++
}
}
if cp == 0 { return errors.New("add an InstanceGroup with spec.role: ControlPlane") }
if node == 0 { return errors.New("add an InstanceGroup with spec.role: Node") } Type guard
func hasControlPlaneGroup(groups []*kops.InstanceGroup) bool {
for _, g := range groups {
if g.IsControlPlane() {
return true
}
}
return false
} Try / catch
if err := validation.DeepValidate(cluster, groups, strict, vfsContext, cloud); err != nil {
if strings.Contains(err.Error(), "ControlPlane InstanceGroup") {
return fmt.Errorf("cluster %s lacks a ControlPlane instance group; set spec.role: ControlPlane on one group", cluster.Name)
}
return err
} Prevention
- Explicitly set spec.role: ControlPlane on at least one group; never rely on defaults
- Check group roles with 'kops get ig -o yaml' after manual edits or template rendering
- Keep control-plane group definitions separate from node templates to avoid accidental role changes
- Run 'kops validate cluster' after edits; it surfaces missing control-plane groups early
When it happens
Trigger: Cluster definitions whose InstanceGroups all have role Node (or role unset/Bastion), passed to kops create cluster / kops update cluster / updateCluster, so controlPlaneGroupCount stays 0.
Common situations: Copy-pasting only node group manifests; setting spec.role: Node on every group by mistake; editing role names to a typo kops doesn't recognize (role defaults to Node); deleting the control-plane group during cluster edits.
Understand the failure class
Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.
Related errors
- InstanceGroup #%d did not have a Name
- duplicate InstanceGroup Name found: %q
- must configure at least one InstanceGroup
- error building node labels: %w
- control-plane InstanceGroup %s did not specify any Subnets
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/0285b83a16c122b0.
Report an issue: GitHub.