kubernetes/kops · error
kube-controller-manager nodes requires the…
Error message
kube-controller-manager nodes requires the ExperimentalRoles feature flag to be enabled
What it means
NewCluster validation guard: fires when an instance group has a kube-controller-manager-only role (nodes running only KCM) but the ExperimentalRoles feature flag is not enabled. Creating such instance groups is unsupported without the flag, so cluster creation is aborted.
Solutions
- Enable the flag: `export KOPS_FEATURE_FLAGS=ExperimentalRoles` and retry.
- Change the instance group role so kube-controller-manager runs on the control plane (default topology).
- Upgrade kops if the component split has since been stabilized.
Example fix
// before kops create cluster --name=example.com # kcm-only IG, flag unset // after export KOPS_FEATURE_FLAGS=ExperimentalRoles kops create cluster --name=example.com
Defensive patterns
Strategy: validation
Validate before calling
if hasRole(igGroups, "kube-controller-manager") && !featureFlagEnabled("ExperimentalRoles") {
return errors.New("ExperimentalRoles flag required for dedicated kcm IGs")
} Try / catch
_, err := NewCluster(opt, cluster, zoneMap)
if err != nil {
if strings.Contains(err.Error(), "kube-controller-manager nodes requires") {
return fmt.Errorf("enable ExperimentalRoles or run kcm on control plane: %w", err)
}
return err
} Prevention
- Validate IG role strings before submitting specs
- Centralize feature-flag configuration
- Only split control-plane components when the flag is intentionally enabled
When it happens
Trigger: `kops create cluster` (or adding an IG) where a group's role has the kube-controller-manager component while KOPS_FEATURE_FLAGS lacks ExperimentalRoles.
Common situations: Highly customized cluster layouts; specs copied from experimental setups; environments where feature-flag env vars are stripped for security.
Related errors
- apiserver nodes requires the APIServerNodes feature flag to…
- etcd nodes requires the ExperimentalRoles feature flag to…
- scheduler nodes requires the ExperimentalRoles feature flag…
- building amiSelectorTerms for
- building tags for
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/0c7d5e99caa2adee.
Report an issue: GitHub.
Appendix: source
Thrown at upup/pkg/fi/cloudup/new_cluster.go:550
} else if g.Spec.Role.HasBastion() {
if g.Spec.MachineType == "" {
g.Spec.MachineType, err = defaultMachineType(cloud, cluster, g)
if err != nil {
return nil, fmt.Errorf("error assigning default machine type for bastions: %v", err)
}
}
} else {
if g.IsAPIServerOnly() && !featureflag.APIServerNodes.Enabled() {
return nil, fmt.Errorf("apiserver nodes requires the APIServerNodes feature flag to be enabled")
}
if !featureflag.ExperimentalRoles.Enabled() {
switch {
case g.Spec.Role.HasEtcd():
return nil, fmt.Errorf("etcd nodes requires the ExperimentalRoles feature flag to be enabled")
case g.Spec.Role.HasScheduler():
return nil, fmt.Errorf("scheduler nodes requires the ExperimentalRoles feature flag to be enabled")
case g.Spec.Role.HasKubeControllerManager():
return nil, fmt.Errorf("kube-controller-manager nodes requires the ExperimentalRoles feature flag to be enabled")
}
}
if g.Spec.MachineType == "" {
g.Spec.MachineType, err = defaultMachineType(cloud, cluster, g)
if err != nil {
return nil, fmt.Errorf("error assigning default machine type for nodes: %v", err)
}
}
}
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:View on GitHub (pinned to 4c8573c808)