{"record":{"id":"0285b83a16c122b0","repo":"kubernetes/kops","slug":"must-configure-at-least-one-controlplane-instanceg","errorCode":null,"errorMessage":"must configure at least one ControlPlane InstanceGroup","messagePattern":"must configure at least one ControlPlane InstanceGroup","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/apis/kops/validation/legacy.go","lineNumber":291,"sourceCode":"\t\treturn errs.ToAggregate()\n\t}\n\n\tif len(groups) == 0 {\n\t\treturn fmt.Errorf(\"must configure at least one InstanceGroup\")\n\t}\n\n\tcontrolPlaneGroupCount := 0\n\tnodeGroupCount := 0\n\tfor _, g := range groups {\n\t\tif g.IsControlPlane() {\n\t\t\tcontrolPlaneGroupCount++\n\t\t} else {\n\t\t\tnodeGroupCount++\n\t\t}\n\t}\n\n\tif controlPlaneGroupCount == 0 {\n\t\treturn fmt.Errorf(\"must configure at least one ControlPlane InstanceGroup\")\n\t}\n\n\tif nodeGroupCount == 0 {\n\t\treturn fmt.Errorf(\"must configure at least one Node InstanceGroup\")\n\t}\n\n\tfor _, g := range groups {\n\t\terrs := CrossValidateInstanceGroup(g, c, cloud, strict)\n\n\t\t// Additional cloud-specific validation rules\n\t\tif c.GetCloudProvider() != kops.CloudProviderAWS && len(g.Spec.Volumes) > 0 {\n\t\t\terrs = append(errs, field.Forbidden(field.NewPath(\"spec\", \"volumes\"), \"instancegroup volumes are only available with aws at present\"))\n\t\t}\n\n\t\tif len(errs) != 0 {\n\t\t\treturn errs.ToAggregate()\n\t\t}\n\t}","sourceCodeStart":273,"sourceCodeEnd":309,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/apis/kops/validation/legacy.go#L273-L309","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nspec:\n  role: Node\n  machineType: m5.large\n// after\nspec:\n  role: ControlPlane\n  machineType: m5.large\n  minSize: 1\n  maxSize: 1","handlingStrategy":"validation","validationCode":"var cp, node int\nfor _, g := range groups {\n    switch {\n    case g.IsControlPlane():\n        cp++\n    case g.IsMaster(): // legacy role check fallback\n        cp++\n    default:\n        node++\n    }\n}\nif cp == 0 { return errors.New(\"add an InstanceGroup with spec.role: ControlPlane\") }\nif node == 0 { return errors.New(\"add an InstanceGroup with spec.role: Node\") }","typeGuard":"func hasControlPlaneGroup(groups []*kops.InstanceGroup) bool {\n    for _, g := range groups {\n        if g.IsControlPlane() {\n            return true\n        }\n    }\n    return false\n}","tryCatchPattern":"if err := validation.DeepValidate(cluster, groups, strict, vfsContext, cloud); err != nil {\n    if strings.Contains(err.Error(), \"ControlPlane InstanceGroup\") {\n        return fmt.Errorf(\"cluster %s lacks a ControlPlane instance group; set spec.role: ControlPlane on one group\", cluster.Name)\n    }\n    return err\n}","preventionTips":["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"],"tags":["kops","validation","control-plane","instance-group"],"backgroundTag":"missing-required-config","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}