kubernetes/kubernetes · critical
serviceCIDR and secondaryServiceCIDR are not dualstack (from
Error message
serviceCIDR and secondaryServiceCIDR are not dualstack (from different IPfamiles)
What it means
Fires when both ServiceCIDR and SecondaryServiceCIDR are provided and parse cleanly, netutils.IsDualStackCIDRs returns no error, but the boolean result is false — meaning both CIDRs belong to the same IP family (both IPv4 or both IPv6). KCM requires the secondary range to be the opposite family so services can be dual-stack.
Source
Thrown at cmd/kube-controller-manager/app/core.go:128
}
}
if len(strings.TrimSpace(controllerContext.ComponentConfig.NodeIPAMController.SecondaryServiceCIDR)) != 0 {
_, secondaryServiceCIDR, err = netutils.ParseCIDRSloppy(controllerContext.ComponentConfig.NodeIPAMController.SecondaryServiceCIDR)
if err != nil {
logger.Info("Warning: unsuccessful parsing of service CIDR", "CIDR", controllerContext.ComponentConfig.NodeIPAMController.SecondaryServiceCIDR, "err", err)
}
}
// the following checks are triggered if both serviceCIDR and secondaryServiceCIDR are provided
if serviceCIDR != nil && secondaryServiceCIDR != nil {
// should be dual stack (from different IPFamilies)
dualstackServiceCIDR, err := netutils.IsDualStackCIDRs([]*net.IPNet{serviceCIDR, secondaryServiceCIDR})
if err != nil {
return nil, fmt.Errorf("failed to perform dualstack check on serviceCIDR and secondaryServiceCIDR error: %w", err)
}
if !dualstackServiceCIDR {
return nil, fmt.Errorf("serviceCIDR and secondaryServiceCIDR are not dualstack (from different IPfamiles)")
}
}
// only --node-cidr-mask-size-ipv4 and --node-cidr-mask-size-ipv6 supported with dual stack clusters.
// --node-cidr-mask-size flag is incompatible with dual stack clusters.
nodeCIDRMaskSizes, err := setNodeCIDRMaskSizes(controllerContext.ComponentConfig.NodeIPAMController, clusterCIDRs)
if err != nil {
return nil, err
}
client, err := controllerContext.NewClient("node-controller")
if err != nil {
return nil, err
}
nodeIpamController, err := nodeipamcontroller.NewNodeIpamController(
ctx,
controllerContext.InformerFactory.Core().V1().Nodes(),View on GitHub (pinned to b882c60b40)
Solutions
- Make the secondary CIDR the opposite family of the primary (IPv6 if primary is IPv4, vice versa)
- If dual-stack is not the goal, remove --secondary-service-cluster-ip-range entirely
- Validate with: python3 -c "import ipaddress; print(ipaddress.ip_network('fd00::/112').version)" for each range
Example fix
# before --service-cluster-ip-range=10.96.0.0/12 --secondary-service-cluster-ip-range=10.97.0.0/16 # both IPv4 -> fails # after --service-cluster-ip-range=10.96.0.0/12 --secondary-service-cluster-ip-range=fd00:1234::/112
Defensive patterns
Strategy: validation
Validate before calling
func assertDualStackFamilies(primary, secondary string) error {
_, p, _ := net.ParseCIDR(primary)
_, s, _ := net.ParseCIDR(secondary)
if p == nil || s == nil { return errors.New("invalid CIDR") }
if (p.IP.To4() == nil) == (s.IP.To4() == nil) {
return errors.New("primary and secondary service CIDRs share an IP family; make one IPv4 and one IPv6")
}
return nil
} Type guard
null
Try / catch
null
Prevention
- If you only need one family, omit the secondary flag
- CI: assert that exactly one of the two service CIDRs is IPv6
- Generate CIDRs from a single dual-stack allocation rather than two manual strings
When it happens
Trigger: Operator sets --service-cluster-ip-range and --secondary-service-cluster-ip-range to two IPv4 CIDRs (or two IPv6 CIDRs) intending to widen the address space rather than enable dual-stack. The IsDualStackCIDRs check at core.go:127 returns false and KCM refuses to start.
Common situations: Adding a second IPv4 service range to avoid exhaustion without realizing the secondary flag is reserved for the other family; migrating to dual-stack by copying the primary CIDR and editing only the prefix; docs/templates that show two ranges of the same family.
Related errors
- failed to perform dualstack check on serviceCIDR and seconda
- len of ClusterCIDRs==%v and they are not configured as dual
- length of clusterCIDRs is:%v more than max allowed of 2
- --service-cluster-ip-range can not contain more than two ent
- --cidr-allocator-type is set to 'CloudAllocator' but cloud p
AI-assisted analysis of kubernetes/kubernetes@b882c60b40 (2026-08-07).
Data as JSON: /api/errors/6c1a6e434c22d2b1.
Report an issue: GitHub.