kubernetes/kops · error

error parsing ServiceNodePortRange %q

Error message

error parsing ServiceNodePortRange %q

What it means

buildCertificatePairTask (pkg/model/context.go:402) parses kubeAPIServer.serviceNodePortRange from the cluster spec using utilnet.PortRange.Set. The default is 30000-32767; if the user-provided range string cannot be parsed by k8s.io/apimachinery's PortRange (wrong format, non-numeric, or an invalid base/size combination), this error is returned.

Source

Thrown at pkg/model/context.go:402

func (b *KopsModelContext) IsIPv6Only() bool {
	return b.Cluster.Spec.IsIPv6Only()
}

// WellKnownServiceIP returns a service ip with the service cidr
func (b *KopsModelContext) WellKnownServiceIP(id int) (net.IP, error) {
	return components.WellKnownServiceIP(&b.Cluster.Spec.Networking, id)
}

// NodePortRange returns the range of ports allocated to NodePorts
func (b *KopsModelContext) NodePortRange() (utilnet.PortRange, error) {
	// defaultServiceNodePortRange is the default port range for NodePort services.
	defaultServiceNodePortRange := utilnet.PortRange{Base: 30000, Size: 2768}

	kubeApiServer := b.Cluster.Spec.KubeAPIServer
	if kubeApiServer != nil && kubeApiServer.ServiceNodePortRange != "" {
		err := defaultServiceNodePortRange.Set(kubeApiServer.ServiceNodePortRange)
		if err != nil {
			return utilnet.PortRange{}, fmt.Errorf("error parsing ServiceNodePortRange %q", kubeApiServer.ServiceNodePortRange)
		}
	}

	return defaultServiceNodePortRange, nil
}

// UseServiceAccountExternalPermissions returns true if we are using service-account bound IAM roles.
func (b *KopsModelContext) UseServiceAccountExternalPermissions() bool {
	return b.Cluster.Spec.IAM != nil &&
		fi.ValueOf(b.Cluster.Spec.IAM.UseServiceAccountExternalPermissions)
}

// NetworkingIsCalico returns true if we are using calico networking
func (b *KopsModelContext) NetworkingIsCalico() bool {
	return b.Cluster.Spec.Networking.Calico != nil
}

// NetworkingIsCilium returns true if we are using cilium networking

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Set serviceNodePortRange to a valid single string of the form 'base-size', e.g. "30000-32768" (this field is Base+Size semantics, not lo-hi)
  2. Remove the field entirely to fall back to the default 30000-32767 range
  3. Check for whitespace or stray characters in the YAML value
  4. Re-run 'kops update cluster' and verify the api-server manifest gets the correct --service-node-port-range

Example fix

// before
kubeAPIServer:
  serviceNodePortRange: 30000-32000  # parsed as wrong type/overflows base semantics
// after
kubeAPIServer:
  serviceNodePortRange: "30000-2001"  # base=30000, size=2001 => ports 30000-32000
Defensive patterns

Strategy: validation

Validate before calling

re := regexp.MustCompile(`^(\d+)-(\d+)$`)
m := re.FindStringSubmatch(spec.KubeAPIServer.ServiceNodePortRange)
if m == nil { return errors.New("serviceNodePortRange must look like \"30000-2001\" (base-size)") }
base, _ := strconv.Atoi(m[1]); size, _ := strconv.Atoi(m[2])
if base < 0 || size <= 0 || base+size > 65536 { return errors.New("port range out of bounds") }

Try / catch

pr := utilnet.PortRange{Base: 30000, Size: 2768}
if err := pr.Set(spec.KubeAPIServer.ServiceNodePortRange); err != nil {
	// fall back to default and surface a warning
	log.Warningf("invalid ServiceNodePortRange %q: %v; using default", spec.KubeAPIServer.ServiceNodePortRange, err)
}

Prevention

When it happens

Trigger: Setting spec.kubeAPIServer.serviceNodePortRange to a string like '30000-32000 ' with stray characters, 'abc', '30000/', or a range whose base+size overflows the valid port space (base+size > 65536, size 0).

Common situations: Customizing the NodePort range to narrow it (e.g. '30000-30100') and mistyping the syntax; copying a range from Kubernetes docs written as YAML list instead of the single string form kOps expects.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/19db51d932615de4. Report an issue: GitHub.