kubernetes/kops · error
cannot determine control-plane zones
Error message
cannot determine control-plane zones
What it means
setupControlPlane could not determine any availability zone for control-plane nodes. The code marks this as "should be unreachable": control-plane zones default to the general --zones list, so if that list is empty and --control-plane-zones was not given, cluster construction cannot proceed and this defensive error is returned.
Source
Thrown at upup/pkg/fi/cloudup/new_cluster.go:1003
}
if controlPlaneCount == 0 {
// If control-plane count is not specified, default to the number of control-plane zones
controlPlaneCount = int32(len(controlPlaneZones))
}
} else {
// controlPlaneZones not set; default to same as node Zones
controlPlaneZones = opt.Zones
if controlPlaneCount == 0 {
// If control-plane count is not specified, default to 1
controlPlaneCount = 1
}
}
if len(controlPlaneZones) == 0 {
// Should be unreachable
return nil, fmt.Errorf("cannot determine control-plane zones")
}
for i := 0; i < int(controlPlaneCount); i++ {
zone := controlPlaneZones[i%len(controlPlaneZones)]
name := zone
if cloudProvider == api.CloudProviderDO {
if int(controlPlaneCount) >= len(controlPlaneZones) {
name += "-" + strconv.Itoa(1+(i/len(controlPlaneZones)))
}
} else {
if int(controlPlaneCount) > len(controlPlaneZones) {
name += "-" + strconv.Itoa(1+(i/len(controlPlaneZones)))
}
}
g := &api.InstanceGroup{}
g.Spec.Role = api.InstanceGroupRoleControlPlane
g.Spec.MinSize = new(int32(1))View on GitHub (pinned to 4c8573c808)
Solutions
- Pass an explicit --zones flag with at least one zone (and --control-plane-zones if you want a distinct control-plane set).
- Check that zone discovery works for your cloud/region (credentials, region setting) so kops can fill defaults.
- If calling the API from Go, ensure NewClusterOptions.Zones or ControlPlaneZones is non-empty before NewCluster.
Example fix
// before kops create cluster my.cluster --control-plane-count 3 # no zones // after kops create cluster my.cluster --zones us-east-1a,us-east-1b,us-east-1c --control-plane-count 3
Defensive patterns
Strategy: validation
Validate before calling
[ -n "$ZONES" ] || [ -n "$CP_ZONES" ] || { echo "provide --zones or --control-plane-zones"; exit 1; } Try / catch
if err := createCluster(); err != nil && strings.Contains(err.Error(), "cannot determine control-plane zones") { /* supply --zones explicitly and retry */ } Prevention
- Always pass --zones explicitly in automation
- Confirm zone discovery works for your cloud/region
- Quote shell variables so --zones never expands empty
When it happens
Trigger: Calling NewCluster (via `kops create cluster`) with neither --zones nor --control-plane-zones resolvable to a non-empty list, e.g. omitting --zones while cloud zones lookup yields nothing, or programmatic use of NewClusterOptions with empty Zones and ControlPlaneZones.
Common situations: Scripted cluster creation where --zones was dropped or is empty due to a variable expansion failure; using a cloud/region combination where zone discovery returns no zones; constructing NewClusterOptions in Go tests without setting Zones.
Related errors
- control-plane InstanceGroup %s did not specify any Subnets
- hetzner cloud provider currently supports only one zone (loc
- scaleway cloud provider currently supports only one availabi
- subnet %s not found in network %s
- specified %d control-plane zones, but also requested %d cont
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/82f3eb67ae5321c9.
Report an issue: GitHub.