kubernetes/kops · error
there should be an odd number of control-plane-zones, for et
Error message
there should be an odd number of control-plane-zones, for etcd's quorum. Hint: Use --zones and --control-plane-zones to declare worker and control plane node zones separately
What it means
etcd requires an odd number of members to have a well-defined quorum; an even count gives no additional fault tolerance. run() throws this when the number of distinct etcd member names in any etcd cluster is even. The message hints at using --zones and --control-plane-zones to separate worker and control-plane zones.
Source
Thrown at upup/pkg/fi/cloudup/populate_cluster_spec.go:158
return fmt.Errorf("EtcdMembers found with same name %q in etcd-cluster %q", m.Name, etcd.Name)
}
instanceGroupName := fi.ValueOf(m.InstanceGroup)
if _, ok := etcdInstanceGroups[instanceGroupName]; ok {
klog.Warningf("EtcdMembers are in the same InstanceGroup %q in etcd-cluster %q (fault-tolerance may be reduced)", instanceGroupName, etcd.Name)
}
//if clusterSubnets[zone] == nil {
// return fmt.Errorf("EtcdMembers for %q is configured in zone %q, but that is not configured at the k8s-cluster level", etcd.Name, m.Zone)
//}
etcdNames[m.Name] = m
etcdInstanceGroups[instanceGroupName] = m
}
if (len(etcdNames) % 2) == 0 {
// Not technically a requirement, but doesn't really make sense to allow
return fmt.Errorf("there should be an odd number of control-plane-zones, for etcd's quorum. Hint: Use --zones and --control-plane-zones to declare worker and control plane node zones separately")
}
}
}
}
configBase, err := clientset.VFSContext().BuildVfsPath(cluster.Spec.ConfigStore.Base)
if err != nil {
return fmt.Errorf("error parsing ConfigStore.Base %q: %v", cluster.Spec.ConfigStore.Base, err)
}
if !vfs.IsClusterReadable(configBase) {
// We could implement this approach, but it seems better to get all clouds using cluster-readable storage
return fmt.Errorf("ConfigStore.Base path is not cluster readable: %v", cluster.Spec.ConfigStore.Base)
}
keyStore, err := clientset.KeyStore(cluster)
if err != nil {
return err
}View on GitHub (pinned to 4c8573c808)
Solutions
- Use an odd number of etcd members (typically 3 or 5) by using an odd number of control-plane zones/instance groups.
- For worker-heavy even zone counts, pass --control-plane-zones (e.g. 3 zones) separately from --zones.
- If a member was removed leaving an even count, add or remove one more member to restore odd quorum, then `kops update cluster`.
Example fix
# before kops create cluster --zones us-east-1a,us-east-1b --control-plane-count 2 ... # after kops create cluster --zones us-east-1a,us-east-1b,us-east-1c --control-plane-zones us-east-1a,us-east-1b,us-east-1c ...
Defensive patterns
Strategy: validation
Validate before calling
if len(cluster.Spec.EtcdClusters[0].Members)%2 == 0 {
return fmt.Errorf("etcd needs an odd number of members for quorum")
} Prevention
- Use 3 or 5 control-plane nodes/zones for HA etcd
- Pass --control-plane-zones separately from --zones when worker zones are even
- After removing a control-plane instance group, re-check member count is still odd
When it happens
Trigger: Creating/updating a cluster whose etcd cluster has an even number of members (e.g. 2 or 4), often because --zones was given an even number of zones and control-plane groups were spread evenly across them, or a member was removed leaving an even count.
Common situations: `kops create cluster --zones a,b,c,d` without separate --control-plane-zones, yielding 4 etcd members; removing one control-plane instance group/member from a 3-member cluster leaving 2; setting up a test cluster with only 2 control-plane nodes.
Related errors
- issuing certificate: %v
- error parsing path for etcd manifest %s: %v
- error reading etcd manifest %s: %v
- invalid EtcdClusterSpec (expected two tokens): %q
- invalid EtcdClusterSpec (member not found in all nodes): %q
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/4488cd1a40682dbb.
Report an issue: GitHub.